<?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: bestbee</title>
    <description>The latest articles on DEV Community by bestbee (@bestbee).</description>
    <link>https://dev.to/bestbee</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%2F4022115%2F1e3f6d82-8235-43d1-a5b6-ebda84a1f6b7.png</url>
      <title>DEV Community: bestbee</title>
      <link>https://dev.to/bestbee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bestbee"/>
    <language>en</language>
    <item>
      <title>Before You Move a Workload to the Free AI Lane, Run the Flip Test</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Mon, 26 Oct 2026 11:08:20 +0000</pubDate>
      <link>https://dev.to/bestbee/before-you-move-a-workload-to-the-free-ai-lane-run-the-flip-test-699</link>
      <guid>https://dev.to/bestbee/before-you-move-a-workload-to-the-free-ai-lane-run-the-flip-test-699</guid>
      <description>&lt;p&gt;The question landed at minute forty of a planning call: "why don't we just put everything on the free lane and revisit next quarter?"&lt;/p&gt;

&lt;p&gt;It is a fair question, and it is usually answered badly — with a price comparison, or with a vibe about model quality. Both miss the thing that actually decides the outcome.&lt;/p&gt;

&lt;p&gt;The scene is a composite, assembled from conversations I keep having with platform leads. No client numbers below, and no measured benchmarks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lane you pick is a statement about what you can refuse
&lt;/h2&gt;

&lt;p&gt;There are three lanes most teams are actually choosing between:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hosted free allowance&lt;/strong&gt; — zero contract, zero ops, shared infrastructure, terms you don't control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosted paid&lt;/strong&gt; — a contract, per-unit billing, stronger retention and version guarantees.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosted&lt;/strong&gt; — your hardware, your patching, your pager.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every lane forces refusals. The free lane refuses some data classes, some concurrency, some model pinning, some audit trails — exactly which ones depends on terms you should have in writing. Self-hosting refuses the team that has no named ops owner.&lt;/p&gt;

&lt;p&gt;So the real question is not "which is cheapest?" It is: &lt;strong&gt;which refusals can this workload absorb for the next 90 days?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why price goes last
&lt;/h2&gt;

&lt;p&gt;Price is a continuous variable. Constraints are binary.&lt;/p&gt;

&lt;p&gt;A lane you are not permitted to use has an infinite unit cost, no matter how good the sticker looks. I've written before about computing crossovers; this post is about the step &lt;em&gt;before&lt;/em&gt; that math, where you decide which lanes are even admissible.&lt;/p&gt;

&lt;p&gt;Get the admissibility set wrong and the spreadsheet becomes a very precise answer to the wrong question. Sound familiar?&lt;/p&gt;

&lt;h2&gt;
  
  
  The worksheet: exclude first, tie-break second
&lt;/h2&gt;

&lt;p&gt;Here is the artifact. It is deliberately dumb, stdlib-only, and reproducible in one file.&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;lane_fit.py — exclude AI coding lanes by hard constraints, then break ties.

Python 3.10+. No dependencies.

    python lane_fit.py

Every number in LANE_ASSUMPTIONS is a PLACEHOLDER. Replace it with the
term you actually received in writing before trusting a line of output.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replace&lt;/span&gt;

&lt;span class="c1"&gt;# --- 1. assumptions you must replace -------------------------------------
&lt;/span&gt;&lt;span class="n"&gt;LANE_ASSUMPTIONS&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;hosted_free&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;allowed_data&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;public&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;internal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;max_parallel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# PLACEHOLDER: concurrency the shared lane tolerates
&lt;/span&gt;        &lt;span class="n"&gt;allows_pinning&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;# can you pin an exact model version?
&lt;/span&gt;        &lt;span class="n"&gt;keeps_audit_log&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# retained, exportable request logs?
&lt;/span&gt;        &lt;span class="n"&gt;commitments&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;# irreversible commitments you accept
&lt;/span&gt;    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hosted_paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;allowed_data&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;public&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;internal&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;regulated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;max_parallel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;allows_pinning&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;keeps_audit_log&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;commitments&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="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;self_hosted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;allowed_data&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;public&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;internal&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;regulated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;max_parallel&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="c1"&gt;# no hard cap, but you own p99
&lt;/span&gt;        &lt;span class="n"&gt;allows_pinning&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;keeps_audit_log&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;commitments&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;OPS_OWNER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;  &lt;span class="c1"&gt;# True only if a named human owns patching + on-call
&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&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;class&lt;/span&gt; &lt;span class="nc"&gt;Workload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;data_class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;              &lt;span class="c1"&gt;# public | internal | regulated
&lt;/span&gt;    &lt;span class="n"&gt;peak_parallel_agents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;pinned_model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;audit_log&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;reviewer_required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;hours_per_week&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;blockers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Workload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LANE_ASSUMPTIONS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data_class&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;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allowed_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data_class=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data_class&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; not allowed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_parallel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peak_parallel_agents&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_parallel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;peak_parallel_agents=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peak_parallel_agents&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;max_parallel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pinned_model&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allows_pinning&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;needs a pinned model version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;audit_log&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keeps_audit_log&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;needs retained, exportable logs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;self_hosted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data_class&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;regulated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;OPS_OWNER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;regulated data, no named ops owner for self-hosting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Workload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;LANE_ASSUMPTIONS&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;blockers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="c1"&gt;# price never enters here; fewest irreversible commitments wins the tie
&lt;/span&gt;    &lt;span class="k"&gt;return&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;ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LANE_ASSUMPTIONS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;commitments&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;flip_test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Workload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chosen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Which single-variable change would exclude the lane we just picked?&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;mutations&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;data one level stricter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;_stricter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data_class&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;peak parallelism x2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peak_parallel_agents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peak_parallel_agents&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pin an exact model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pinned_model&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;require exportable logs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;audit_log&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mutated&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mutations&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;mutated&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;blockers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mutated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chosen&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;hits&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;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;blockers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mutated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chosen&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_stricter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;order&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;public&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;internal&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;regulated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;min&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="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_class&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="p"&gt;,&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;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;


&lt;span class="n"&gt;WORKLOADS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nc"&gt;Workload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docs-and-tests&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;public&lt;/span&gt;&lt;span class="sh"&gt;"&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="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Workload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;internal-refactor&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;internal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;12.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Workload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;billing-migration&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;regulated&lt;/span&gt;&lt;span class="sh"&gt;"&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="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&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;WORKLOADS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;admissible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&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="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  (data=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data_class&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, parallel=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peak_parallel_agents&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
              &lt;span class="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;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hours_per_week&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;h/wk)&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;lane&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;LANE_ASSUMPTIONS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;why&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;blockers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OK  &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;why&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OUT &lt;/span&gt;&lt;span class="sh"&gt;'&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;lane&lt;/span&gt;&lt;span class="si"&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="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;why&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;admissible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  =&amp;gt; no admissible lane: split the workload or reduce scope&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;chosen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;admissible&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;fallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;admissible&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admissible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;none&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  =&amp;gt; pick &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chosen&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;; fallback &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;flips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;flip_test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chosen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;flips&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;     flip: none of the four single-variable changes break this lane&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;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;flips&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;     flip: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;Run it. Then argue with the output. That argument is the meeting you actually needed to have.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it prints (illustrative, from the placeholders above)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs-and-tests  (data=public, parallel=2, 6.0h/wk)
  OK   hosted_free
  OK   hosted_paid
  OK   self_hosted
  =&amp;gt; pick hosted_free; fallback hosted_paid
     flip: pin an exact model -&amp;gt; needs a pinned model version
     flip: require exportable logs -&amp;gt; needs retained, exportable logs

internal-refactor  (data=internal, parallel=3, 12.0h/wk)
  OK   hosted_free
  OK   hosted_paid
  OK   self_hosted
  =&amp;gt; pick hosted_free; fallback hosted_paid
     flip: peak parallelism x2 -&amp;gt; peak_parallel_agents=6 &amp;gt; 4
     flip: pin an exact model -&amp;gt; needs a pinned model version
     flip: require exportable logs -&amp;gt; needs retained, exportable logs

billing-migration  (data=regulated, parallel=2, 4.0h/wk)
  OUT  hosted_free    data_class=regulated not allowed
  OK   hosted_paid
  OUT  self_hosted    regulated data, no named ops owner for self-hosting
  =&amp;gt; pick hosted_paid; fallback none
     flip: none of the four single-variable changes break this lane
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are placeholder assumptions, not measurements. Feed it your own terms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the output like a lead, not like a spreadsheet
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;OUT&lt;/code&gt; rows are decisions, not preferences.&lt;/strong&gt; If the free lane is out on data class, stop negotiating with it and move on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"No admissible lane" is a finding, not a failure.&lt;/strong&gt; &lt;code&gt;billing-migration&lt;/code&gt; has no fallback because self-hosting without an ops owner is not a lane — it is a future incident with a start date.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A fallback is not a plan.&lt;/strong&gt; It is the name of the person you call when the primary breaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The flip list is the actual deliverable.&lt;/strong&gt; It tells you what you are one decision away from losing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where the free lane genuinely earns its place
&lt;/h2&gt;

&lt;p&gt;The free lane is not the "cheap lane." It is the lane for workloads whose refusals you can absorb: documentation, test scaffolding, mechanical refactors, anything that a human reviewer would catch anyway.&lt;/p&gt;

&lt;p&gt;The lane I am running this quarter on the free side is MonkeyCode — free model access plus a free server option, which the operator describes as an open-source project. &lt;strong&gt;Disclosure: This article was prepared as part of MonkeyCode's product outreach.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As of &lt;strong&gt;2026-10-26&lt;/strong&gt;, the operator's pitch is free model access (a ten-million-token allowance, per their own copy) plus a free server option. I have not independently verified the allowance, the model list, the server specifications, how long either offer lasts, or the license terms. Treat every one of those as an unverified input to the worksheet — a row you still have to fill in, not a number you get to budget against.&lt;/p&gt;

&lt;p&gt;What makes it a reasonable first lane for &lt;code&gt;docs-and-tests&lt;/code&gt; is structural, not promotional: it asks for the fewest commitments. No contract. No hardware. No pager. That is also exactly why it runs out of road for &lt;code&gt;billing-migration&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The flip test is the part people skip
&lt;/h2&gt;

&lt;p&gt;Anyone can list tradeoffs. The useful move is naming the single variable that would reverse your call, and assigning it an owner.&lt;/p&gt;

&lt;p&gt;For each flip line, write down three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Who watches that variable.&lt;/li&gt;
&lt;li&gt;What threshold triggers a re-run of the worksheet.&lt;/li&gt;
&lt;li&gt;What the team does in the first hour after the trigger.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If nobody owns "peak parallelism x2," then the free lane is not a decision — it is a coin flip with documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should not use this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Teams without a data classification scheme.&lt;/strong&gt; Fix that first; this script will happily launder your ambiguity into a tidy &lt;code&gt;OK&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regulated workloads with no ops owner.&lt;/strong&gt; Self-hosting is not available to you yet, and pretending otherwise wastes the meeting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anyone who needs a score to justify a decision already made.&lt;/strong&gt; This worksheet excludes lanes. It does not bless one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teams expecting measured numbers.&lt;/strong&gt; Every value above is a placeholder until you replace it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations I want on the record
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;commitments&lt;/code&gt; field is ordinal, not cardinal — it ranks lanes, it does not price them. The model ignores reviewer hours entirely, and reviewer hours are usually the largest real cost of a free lane. The sensitivity analysis mutates one variable at a time; two simultaneous changes can produce outcomes this script will never show you. And the whole thing is a conversation tool, not objective truth — two reasonable leads can fill in the assumptions differently and both be right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Owner, expiry, exit
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Owner:&lt;/strong&gt; platform lead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expires:&lt;/strong&gt; 2026-11-25. Re-run or archive, do not silently inherit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit criteria:&lt;/strong&gt; either every workload has a named lane plus an owned flip trigger, or the team writes down which workload it is deliberately parking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One soft ask: if you run this, bring back the flip list for the workload you were about to move to the free lane. That single list tells me more about your risk posture than any architecture diagram.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Two Free Offers, Two Failure Modes: Route AI Work by Blast Radius, Not by Lane</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Tue, 20 Oct 2026 09:09:58 +0000</pubDate>
      <link>https://dev.to/bestbee/two-free-offers-two-failure-modes-route-ai-work-by-blast-radius-not-by-lane-jo4</link>
      <guid>https://dev.to/bestbee/two-free-offers-two-failure-modes-route-ai-work-by-blast-radius-not-by-lane-jo4</guid>
      <description>&lt;p&gt;Two tabs open. Both say free. One is a token allowance on a hosted model endpoint; the other is a server you can run somewhere. My platform lead looked at them and asked the reasonable question: "So which one do we take?"&lt;/p&gt;

&lt;p&gt;It took me a week to notice that the question was malformed. They are not two versions of the same offer. They fail in completely different ways, on different timelines, against different budgets. Choosing between them like flavors is how teams end up with a free model quota nobody trusts and a box nobody patches.&lt;/p&gt;

&lt;p&gt;Here is the reframe that actually helped: stop picking a lane for the team. Route individual change sets, and let the two offers absorb the classes of work they are genuinely good at.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this keeps going wrong
&lt;/h2&gt;

&lt;p&gt;Look at what developers were writing on DEV last week. On 2026-10-13, a post titled "AI Fatigue? Yea I know." collected 164 reactions and 101 comments. Two days later, "I Vibe-Coded My Way Out of Angular Upgrades" picked up 88 reactions and 56 comments about shipping model-authored diffs into a real codebase. Different moods, same underlying constraint.&lt;/p&gt;

&lt;p&gt;Neither thread is about generation speed. Both are about the cost that lands &lt;em&gt;after&lt;/em&gt; generation — reading, verifying, and owning the diff. That cost does not care which lane produced the code. It only cares how big and how dangerous the change was.&lt;/p&gt;

&lt;p&gt;So ask yourself: if your reviewers are the bottleneck, does a faster or cheaper generator change your throughput at all?&lt;/p&gt;

&lt;h2&gt;
  
  
  The two offers fail differently
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Free model access&lt;/th&gt;
&lt;th&gt;Free server option&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Primary currency&lt;/td&gt;
&lt;td&gt;Tokens / requests&lt;/td&gt;
&lt;td&gt;CPU, memory, disk, egress&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure mode&lt;/td&gt;
&lt;td&gt;Review debt — output arrives faster than it can be verified&lt;/td&gt;
&lt;td&gt;Ops debt — patching, upgrades, restarts, who is on call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shows up as&lt;/td&gt;
&lt;td&gt;Rising review latency, rubber-stamped approvals&lt;/td&gt;
&lt;td&gt;Silent drift, surprise downtime, config archaeology&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Detected by&lt;/td&gt;
&lt;td&gt;Reviewer queue depth&lt;/td&gt;
&lt;td&gt;Uptime and patch-lag tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverses when&lt;/td&gt;
&lt;td&gt;Review latency exceeds one business day&lt;/td&gt;
&lt;td&gt;Nobody owns the box for two consecutive weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read that table again. The left column is a &lt;em&gt;people&lt;/em&gt; constraint. The right column is an &lt;em&gt;ownership&lt;/em&gt; constraint. A team can be perfectly staffed for one and completely unstaffed for the other, which is exactly why a single "free tier yes/no" decision keeps producing bad outcomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workload fission: route the change, not the team
&lt;/h2&gt;

&lt;p&gt;Borrow the idea from fault-tolerant systems. You do not ask "is this system safe?" You ask what a failure would cost, and you place controls accordingly. Do the same with AI-authored diffs.&lt;/p&gt;

&lt;p&gt;Two axes decide the route:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reversibility&lt;/strong&gt; — can this be reverted in one commit, with no data migration, no customer notification, no third-party side effect?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blast radius&lt;/strong&gt; — if it is wrong in production, how many users, how much money, how many hours of incident response?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That gives four buckets, and only three of them should ever touch a free lane:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Low blast, reversible&lt;/strong&gt; — docs, tests, fixtures, log messages, internal tooling. Free model lane. One reviewer, same day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low blast, hard to reverse&lt;/strong&gt; — schema tweaks, cache key formats, anything with a write path. Paid lane or free lane with an owner sign-off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High blast, reversible&lt;/strong&gt; — feature flags, config toggles behind an off switch. Paid lane, plus a kill-switch check.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High blast, hard to reverse&lt;/strong&gt; — auth, billing, migrations, public API contracts. Human-authored or human-rewritten. No exceptions older than 30 days.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is that last line too rigid? Maybe. But I have never regretted it, and I have definitely regretted the alternative.&lt;/p&gt;

&lt;h2&gt;
  
  
  A 60-line router you can run today
&lt;/h2&gt;

&lt;p&gt;Scores are a conversation tool, not objective truth. The point is to make the routing rule explicit and identical for everyone, instead of letting whoever is on triage that morning decide.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;route_ai_work.py - classify one change set into a review lane.

Stdlib only. No network calls. Feed it a JSON file.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="n"&gt;WEIGHTS&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;files_changed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lines_added&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lines_deleted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# deletion is riskier than addition
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;touch_migrations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;25.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;touch_auth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;25.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;touch_billing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;25.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;touch_public_api&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;15.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;touch_ci_config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;LANES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;free-model lane&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;one reviewer, same day&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid-model lane&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;one reviewer + owner sign-off&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inf&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;human-author lane&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;two reviewers, no model-authored diff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;files_changed&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;lines_added&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;lines_deleted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;WEIGHTS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flags&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;flag&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;WEIGHTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown flag &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt;; add it to WEIGHTS first&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;WEIGHTS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&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;low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;LANES&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;low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unrouted&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;escalate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&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;change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;unnamed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;score=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;review&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;h3&gt;
  
  
  A fixture, so results are comparable across teams
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ENG-4412"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"files_changed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"lines_added"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;210&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"lines_deleted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"flags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"touch_migrations"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python3 route_ai_work.py fixture_paid.json
ENG-4412    &lt;span class="nv"&gt;score&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;45.5  paid-model lane one reviewer + owner sign-off
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three fixtures I keep in the repo, with expected output, so anyone can sanity-check a weights change before it ships:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docs-only&lt;/code&gt;: 2 files, +30 / -5, no flags → &lt;code&gt;score=4.0&lt;/code&gt; → free-model lane.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;migration&lt;/code&gt;: above → &lt;code&gt;score=45.5&lt;/code&gt; → paid-model lane.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auth-plus-api&lt;/code&gt;: 12 files, +600 / -150, flags &lt;code&gt;touch_auth&lt;/code&gt;, &lt;code&gt;touch_public_api&lt;/code&gt; → &lt;code&gt;score=97.0&lt;/code&gt; → human-author lane.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Calibrate the weights before you trust them. Take 20 PRs you already merged, 10 that went clean and 10 that caused a follow-up fix, and check whether the router separates them. If it does not, your weights are wrong, not your reviewers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the two offers actually fit
&lt;/h2&gt;

&lt;p&gt;Here is where this stops being abstract for me. The offer I have been evaluating is MonkeyCode, an open-source project whose operator describes two things: free model access with a token allowance, and a free server option.&lt;/p&gt;

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

&lt;p&gt;I am deliberately not putting numbers on the allowance or the hardware in this post. Those are operator-supplied claims that I have not independently verified, and a quota you read from me is a quota you will argue about later with no source. Verify them yourself, on the date you verify them, and write the date in your own ledger.&lt;/p&gt;

&lt;p&gt;What I &lt;em&gt;will&lt;/em&gt; say is how the two options map onto the routing above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free model access&lt;/strong&gt; is the natural fuel for the low-blast, reversible bucket — the docs, tests, and internal-tooling work that would otherwise queue behind a human because it feels too small to schedule. It is a bad fit for the human-author bucket, and no amount of free tokens changes that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The free server option&lt;/strong&gt; is a different decision entirely. It helps when you have a workload that needs to sit somewhere you control — an internal proxy, a scheduled job, an eval harness. It only helps if you can answer "who patches it?" with a name, not a shrug.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note what is missing from that list: nothing about replacing your paid lane. Routing is about placement, not substitution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hard gates, an owner, and an expiry
&lt;/h2&gt;

&lt;p&gt;Write these down before the first free-lane PR merges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Gate:&lt;/strong&gt; no free-lane merge without a named reviewer in the same timezone, same day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate:&lt;/strong&gt; if review latency for the free lane exceeds one business day for five consecutive working days, the lane is paused until the queue clears.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Owner:&lt;/strong&gt; one person owns the server option, including patch lag. If the owner changes teams, the option stops — automatically, not by discussion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expiry:&lt;/strong&gt; every routing exception expires in 30 days and must be re-justified by a re-run of the router, not by memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit:&lt;/strong&gt; if two incidents in a quarter trace back to model-authored diffs in a bucket you classified as low blast, that bucket gets reclassified upward permanently.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Sensitivity: what would reverse this routing
&lt;/h2&gt;

&lt;p&gt;Run these three what-ifs. Any one of them can flip the plan.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your median PR review latency is already above one business day, the free-model lane's advantage mostly evaporates. You are review-bound, and adding generation capacity just deepens the queue.&lt;/li&gt;
&lt;li&gt;If migrations, auth, and public API changes are more than 40% of your change count, most work routes to the human bucket anyway and the free lane becomes a rounding error. Check the count, not the vibe.&lt;/li&gt;
&lt;li&gt;If your server option has no owner after two weeks, its true cost is unbounded — and no token allowance offsets an unpatched box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which of those three numbers is closest to flipping for you? That is the one to measure first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should not use this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Solo developers with no review queue.&lt;/strong&gt; Routing exists to protect reviewers. If you are the only reviewer, you already are the gate — just write the flags file and skip the ceremony.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teams under compliance regimes that require provenance on every diff.&lt;/strong&gt; Do the classification, but expect the free lane to be empty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anyone who wants the router to decide.&lt;/strong&gt; It ranks work. It does not own outcomes. If a human cannot defend the routing at postmortem time, the routing was wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to try the offers, try them against one bucket — the low-blast reversible one — for two weeks, with the gates above written down first. That is the whole experiment. Everything else is a lane decision you do not have to make yet.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Free Allowance or Self-Hosted Box? Compute the Crossover Before You Commit</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Mon, 19 Oct 2026 07:44:46 +0000</pubDate>
      <link>https://dev.to/bestbee/free-allowance-or-self-hosted-box-compute-the-crossover-before-you-commit-56kn</link>
      <guid>https://dev.to/bestbee/free-allowance-or-self-hosted-box-compute-the-crossover-before-you-commit-56kn</guid>
      <description>&lt;p&gt;A platform lead I'll call Dana pinged me mid-sprint with a one-line message: "our AI lane is free, so why does it feel expensive?"&lt;/p&gt;

&lt;p&gt;The lane wasn't the problem. The problem was that nobody had converted "free" into the only unit her org actually budgets in — merged pull requests. This scenario is a composite of conversations I've had with platform leads; the numbers below are illustrative, not audited results from any specific company.&lt;/p&gt;

&lt;p&gt;That conversion is the whole article. If you can't say how many merged PRs your allowance covers, you don't have a capacity plan. You have a vibe.&lt;/p&gt;

&lt;h2&gt;
  
  
  The claim, and what it is worth
&lt;/h2&gt;

&lt;p&gt;MonkeyCode's operators state two things that matter for this decision: free model access with 10 million free tokens, and a free server option. The project is also described as open source. I have not audited the quota mechanics, expiry, or fair-use rules, so treat all of that as a claim to verify inside your own account before you plan around it.&lt;/p&gt;

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

&lt;p&gt;A free allowance changes the shape of your cost curve, not the existence of one. Below the line, marginal cost is zero. Above it, you either pay overage or you own hardware. Those are different businesses, and they fail differently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: measure tokens per merged PR
&lt;/h2&gt;

&lt;p&gt;Not per seat. Not per developer-day. Per merged PR. Seats hide idle time; days hide rework.&lt;/p&gt;

&lt;p&gt;I keep a tiny script for this because the mean lies. Agentic sessions have a long tail — one runaway loop can double your average while the median barely moves.&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;# tokens_per_pr.py — run against your own usage export
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt;

&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;usage.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;   &lt;span class="c1"&gt;# columns: pr, tokens
&lt;/span&gt;&lt;span class="n"&gt;per_pr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;per_pr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;per_pr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;vals&lt;/span&gt; &lt;span class="o"&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;per_pr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;median&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;median&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;p90&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vals&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&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;vals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PRs=&lt;/span&gt;&lt;span class="si"&gt;{&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;vals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; median=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; p90=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p90&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; mean=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;//&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;vals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the median for planning and the p90 for your worst-case gate. If median and p90 differ by more than 3x, your workflow has an unbounded loop somewhere, and no pricing model will save you from it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: convert the allowance into PRs
&lt;/h2&gt;

&lt;p&gt;This is one division, and it is the most useful number in the whole exercise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;covered_prs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;allowance_tokens&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;tokens_per_pr_median&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At an illustrative 45,000 tokens per merged PR, 10 million tokens covers roughly 222 merged PRs. Whether that is generous or thin depends entirely on your team, and that is the point — the number is meaningless until it meets your sprint board.&lt;/p&gt;

&lt;p&gt;Ask the question that actually decides things: &lt;strong&gt;does my pilot need more than ~200 merged PRs to produce a defensible answer?&lt;/strong&gt; If yes, you are not testing the free lane. You are testing your overage path while calling it a pilot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: find the self-host crossover
&lt;/h2&gt;

&lt;p&gt;Here is the counterintuitive part. Self-hosting almost never wins on tokens alone. It wins on control. Let's show the arithmetic instead of asserting it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# crossover.py — a model, not a benchmark. Plug in measured inputs.
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cost_per_pr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens_per_pr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;overage_per_million&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tokens_per_pr&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;overage_per_million&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;break_even_prs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens_per_pr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hosted_overage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;box_month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ops_hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loaded_hourly&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;fixed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;box_month&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ops_hours&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;loaded_hourly&lt;/span&gt;
    &lt;span class="n"&gt;saving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cost_per_pr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens_per_pr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hosted_overage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;  &lt;span class="c1"&gt;# box marginal ~ 0
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fixed&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;saving&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;saving&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;break_even_prs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;tokens_per_pr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;45_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hosted_overage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;# $ per 1M tokens after allowance (illustrative)
&lt;/span&gt;    &lt;span class="n"&gt;box_month&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;192.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;# 160 h x $1.20/h (illustrative)
&lt;/span&gt;    &lt;span class="n"&gt;ops_hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;loaded_hourly&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;85.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# ~39,000 merged PRs/month to justify the box
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thirty-nine thousand merged PRs a month is not a team. It's a CI pipeline with aspirations. At low overage prices, the math says: stay hosted, keep the ops hours for something that compounds.&lt;/p&gt;

&lt;p&gt;Now push the overage price up and watch the answer move.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tokens/PR (median)&lt;/th&gt;
&lt;th&gt;Overage $/1M&lt;/th&gt;
&lt;th&gt;Self-host fixed $/mo&lt;/th&gt;
&lt;th&gt;Break-even PRs/mo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;45,000&lt;/td&gt;
&lt;td&gt;0.40&lt;/td&gt;
&lt;td&gt;702&lt;/td&gt;
&lt;td&gt;~39,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;45,000&lt;/td&gt;
&lt;td&gt;3.00&lt;/td&gt;
&lt;td&gt;702&lt;/td&gt;
&lt;td&gt;~5,200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15,000&lt;/td&gt;
&lt;td&gt;3.00&lt;/td&gt;
&lt;td&gt;702&lt;/td&gt;
&lt;td&gt;~15,600&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;45,000&lt;/td&gt;
&lt;td&gt;3.00&lt;/td&gt;
&lt;td&gt;2,400&lt;/td&gt;
&lt;td&gt;~17,800&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read the last two rows together. Shrinking tokens-per-PR by 3x raises the bar by 3x. Adding an SRE-grade box triples it again. &lt;strong&gt;Self-host crossover is a lagging indicator of operational discipline&lt;/strong&gt;, not a pricing event.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three gates
&lt;/h2&gt;

&lt;p&gt;A spreadsheet is a conversation tool, not objective truth. Use it to force three yes/no answers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Coverage gate.&lt;/strong&gt; &lt;code&gt;allowance / median_tokens_per_pr&lt;/code&gt; ≥ your pilot's required merged PRs, with 30% headroom for the p90 tail. Fail this and you are measuring overage, not the free lane.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ops gate.&lt;/strong&gt; Name one human who owns patching, upgrades, and on-call for the self-hosted path, with hours on a calendar. No named owner means your &lt;code&gt;ops_hours&lt;/code&gt; input is fiction, and the crossover number is fiction with it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reversibility gate.&lt;/strong&gt; What does leaving cost in each lane? Migrating prompts, evals, and CI hooks is the real bill. Open-source matters here far more than price does — you can read the code, fork it, and leave with it. Check the actual license yourself before counting on that.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Fit criteria
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Choose the free hosted lane when:&lt;/strong&gt; your pilot fits inside the coverage gate, you have no data-residency constraint, and your bottleneck is review time rather than token spend. Most teams land here, and pretending otherwise wastes a quarter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose self-hosted when:&lt;/strong&gt; you need airgapped or residency-bound execution, custom weights, or offline CI. Do it for those reasons and say so out loud — the crossover sheet will not back you up on cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose a paid seat when:&lt;/strong&gt; you have crossed the allowance in two consecutive sprints and your p90 is stable. Stable overage is a signal to buy predictability, not to build a data center.&lt;/p&gt;

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

&lt;p&gt;This model ignores latency, queueing, egress, storage, and quality differences between models. Tokens are not equal across providers, so never compare raw counts between lanes. Quota terms and prices move; re-run the sheet before each renewal.&lt;/p&gt;

&lt;p&gt;Skip this if you have no one who can own infrastructure, if you have a hard residency requirement (that decision is already made for you), or if your actual constraint is reviewer attention — in which case the crossover is the wrong sheet entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The question that should end the meeting
&lt;/h2&gt;

&lt;p&gt;Don't ask whether the free option is good. Ask: &lt;em&gt;which single input would flip my decision?&lt;/em&gt; For most teams it is &lt;code&gt;tokens_per_pr&lt;/code&gt;, not price. Measure it for two weeks and the argument dissolves.&lt;/p&gt;

&lt;p&gt;If you want a zero-cash place to collect your first real &lt;code&gt;tokens_per_pr&lt;/code&gt; number, MonkeyCode's free model access is a reasonable lane to start on — bring the spreadsheet, not the enthusiasm.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Should Your Platform Team Take the Free AI Tier? Use This 4-Part Ops-Absorption Test</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Sun, 18 Oct 2026 06:42:31 +0000</pubDate>
      <link>https://dev.to/bestbee/should-your-platform-team-take-the-free-ai-tier-use-this-4-part-ops-absorption-test-3fdj</link>
      <guid>https://dev.to/bestbee/should-your-platform-team-take-the-free-ai-tier-use-this-4-part-ops-absorption-test-3fdj</guid>
      <description>&lt;p&gt;Two posts sat near the top of DEV in the same week, and they were arguing with each other.&lt;/p&gt;

&lt;p&gt;"One Weekend: 3,000 Open-Source AI Projects" (2026-10-11) said the supply of free AI tooling is now effectively infinite. "AI Fatigue? Yea I know." (2026-10-13) said the appetite for running any of it is not.&lt;/p&gt;

&lt;p&gt;Both can be true. That is exactly the trap for a platform team. Free options multiply, and every one of them asks for the same thing you are shortest on: someone's attention.&lt;/p&gt;

&lt;p&gt;So here is the question I want you to answer before you accept any free tier. Not "is the model good?" Not "is the price zero?" But: &lt;strong&gt;how many ops hours per week does this lane quietly charge you?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below is the test I use, a script to measure the one number that drives it, and a worked example with real arithmetic. All numbers are labeled where they are modeled rather than measured. A scorecard like this is a conversation tool, not objective truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision is not "free vs paid". It is three lanes
&lt;/h2&gt;

&lt;p&gt;Most teams compare two things and miss the third.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lane&lt;/th&gt;
&lt;th&gt;Cash cost&lt;/th&gt;
&lt;th&gt;Ops hours&lt;/th&gt;
&lt;th&gt;Hard ceiling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A. Free hosted tier&lt;/td&gt;
&lt;td&gt;~0&lt;/td&gt;
&lt;td&gt;~0&lt;/td&gt;
&lt;td&gt;Token or rate allowance, set by the vendor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B. Paid hosted API&lt;/td&gt;
&lt;td&gt;Per 1M tokens&lt;/td&gt;
&lt;td&gt;~0&lt;/td&gt;
&lt;td&gt;Budget only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C. Self-hosted model server&lt;/td&gt;
&lt;td&gt;Hardware + power, amortized&lt;/td&gt;
&lt;td&gt;Yours, weekly, forever&lt;/td&gt;
&lt;td&gt;Your patience and your on-call&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Lane A and Lane B share a property that Lane C does not: nobody has to get paged. That property is the thing you are actually pricing.&lt;/p&gt;

&lt;p&gt;And Lane A has a second property people forget — a ceiling that is not measured in dollars. You cannot buy your way past it with a budget approval. You buy past it with a migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define five variables before you compare anything
&lt;/h2&gt;

&lt;p&gt;Write these on one line and put them in the doc. Undefined variables are how free-tier decisions get made by vibes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;N&lt;/strong&gt; — engineers using the assistant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;T&lt;/strong&gt; — tokens per engineer-week, including retries and rejected attempts. Measured, not estimated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;R&lt;/strong&gt; — your blended hosted price per 1M tokens, from your actual contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S&lt;/strong&gt; — monthly amortized cost of the self-hosted box (hardware over its useful life, plus power and rack).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C&lt;/strong&gt; — loaded engineer-hour cost. Use your real number; it is usually higher than the one people quote in meetings.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then two derived numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosted monthly = &lt;code&gt;N × T × 4.33 ÷ 1,000,000 × R&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Break-even ops hours per week = &lt;code&gt;(hosted monthly − S) ÷ (4.33 × C)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That second formula is the whole article. It tells you how many hours of your team's week the self-hosted lane may consume before it stops being the cheaper option. If the answer is smaller than the hours you already know you'll spend, the decision is made.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one number to measure first: tokens per accepted change
&lt;/h2&gt;

&lt;p&gt;Here is what I keep seeing. Teams measure token spend per &lt;em&gt;request&lt;/em&gt;. That number is useless for this decision, because requests are not the unit anyone cares about.&lt;/p&gt;

&lt;p&gt;The unit is the accepted change: a diff that merged and was not reverted within seven days.&lt;/p&gt;

&lt;p&gt;Why the seven-day revert window? Because a change that gets rolled back next Tuesday consumed tokens and produced nothing. Counting it as output flatters every lane, and flatters the free one most, since free tokens make failed attempts feel costless.&lt;/p&gt;

&lt;p&gt;So log this CSV for one week. Columns: &lt;code&gt;engineer,task,prompt_tokens,completion_tokens,accepted,rework_minutes&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;token_shape.py -- measure token shape, then price two lanes.

Input CSV: engineer,task,prompt_tokens,completion_tokens,accepted,rework_minutes
  accepted = 1 when the change merged and was not reverted within 7 days.

Usage:
  python3 token_shape.py tasks.csv
  python3 token_shape.py tasks.csv --team 8 --price 3.00 --server 600 --hour 95 --ops 4
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;

&lt;span class="n"&gt;MONTHS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;4.33&lt;/span&gt;  &lt;span class="c1"&gt;# average weeks per month
&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completion_tokens&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;accepted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accepted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1&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;rework&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rework_minutes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;accepted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accepted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;n_acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&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;accepted&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens&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;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tasks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&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;rows&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accepted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&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;accepted&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens_per_accepted_change&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n_acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rework_min_per_accepted_change&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rework&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;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;accepted&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_acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lanes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens_week_per_eng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price_per_mtok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server_month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loaded_hour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ops_hours_week&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;hosted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;team&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;tokens_week_per_eng&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;MONTHS&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;price_per_mtok&lt;/span&gt;
    &lt;span class="n"&gt;owned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ops_hours_week&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;MONTHS&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;loaded_hour&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;server_month&lt;/span&gt;
    &lt;span class="n"&gt;breakeven_ops&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hosted&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;server_month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MONTHS&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;loaded_hour&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hosted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;owned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;breakeven_ops&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--team&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3.00&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--server&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;600.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--hour&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;95.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--ops&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--changes-per-eng-week&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--allowance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;per_acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens_per_accepted_change&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tasks=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tasks&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; accepted=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accepted&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens_per_accepted_change=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;per_acc&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;0&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;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rework_min_per_accepted_change=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rework_min_per_accepted_change&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&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;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allowance_covers_accepted_changes=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowance&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;per_acc&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;0&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;span class="n"&gt;tokens_week&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;per_acc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;changes_per_eng_week&lt;/span&gt;
    &lt;span class="n"&gt;hosted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;owned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;breakeven&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lanes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens_week&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ops&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hosted_month=$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hosted&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;0&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;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;self_hosted_month=$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;owned&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;0&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;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;breakeven_ops_hours_per_week=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;breakeven&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&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;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it. Then look at &lt;code&gt;tokens_per_accepted_change&lt;/code&gt;. That single number decides whether you are in a light shape or a heavy one, and those two shapes lead to completely different conclusions about the same nominal free allowance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example: same allowance, two very different worlds
&lt;/h2&gt;

&lt;p&gt;Here is the arithmetic I get asked to do most often, done out loud. Assume an operator-supplied free allowance of up to 10,000,000 tokens (the figure given to me for this piece, verify it in-product before you rely on it).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shape&lt;/th&gt;
&lt;th&gt;Tokens per accepted change&lt;/th&gt;
&lt;th&gt;Accepted changes the allowance covers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Context-light edit loop&lt;/td&gt;
&lt;td&gt;~165,000&lt;/td&gt;
&lt;td&gt;~60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context-heavy agent loop (large repo, retries)&lt;/td&gt;
&lt;td&gt;~1,900,000&lt;/td&gt;
&lt;td&gt;~5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Same allowance. One is a usable month for a small team. The other is a measurement budget.&lt;/p&gt;

&lt;p&gt;That is not a knock on the free tier. It is a statement about your workload. If you don't know which row you are in, you don't know what you were offered, and neither does the person who approved it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The lane comparison, filled in
&lt;/h3&gt;

&lt;p&gt;Modeled example, not measured. N = 8, heavy shape at 6 accepted changes per engineer-week → T ≈ 11.4M tokens/engineer-week. R = $3.00/1M. S = $600/month. C = $95/hour.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosted monthly = 8 × 11.4M × 4.33 ÷ 1M × $3 ≈ &lt;strong&gt;$1,185&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Self-hosted at 4 ops h/week = 4 × 4.33 × $95 + $600 ≈ &lt;strong&gt;$2,245&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Break-even ops hours = (1,185 − 600) ÷ (4.33 × 95) ≈ &lt;strong&gt;1.4 h/week&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read that last line again. Self-hosting this workload wins on cash only if your team spends under roughly ninety minutes a week keeping the box alive. Not during migration. Every week, including the week after a driver upgrade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sensitivity: where the line moves
&lt;/h3&gt;

&lt;p&gt;Ops hour sensitivity, holding everything else fixed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ops h/week&lt;/th&gt;
&lt;th&gt;Self-hosted $/mo&lt;/th&gt;
&lt;th&gt;Hosted $/mo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$1,011&lt;/td&gt;
&lt;td&gt;$1,185&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;$1,423&lt;/td&gt;
&lt;td&gt;$1,185&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$1,834&lt;/td&gt;
&lt;td&gt;$1,185&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;$2,245&lt;/td&gt;
&lt;td&gt;$1,185&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;$3,068&lt;/td&gt;
&lt;td&gt;$1,185&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Price sensitivity at H = 4:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;R ($/1M)&lt;/th&gt;
&lt;th&gt;Hosted $/mo&lt;/th&gt;
&lt;th&gt;Break-even ops h/week&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$1&lt;/td&gt;
&lt;td&gt;$395&lt;/td&gt;
&lt;td&gt;never (negative)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$3&lt;/td&gt;
&lt;td&gt;$1,185&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$8&lt;/td&gt;
&lt;td&gt;$3,159&lt;/td&gt;
&lt;td&gt;6.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$15&lt;/td&gt;
&lt;td&gt;$5,924&lt;/td&gt;
&lt;td&gt;12.9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice the direction. Cheaper hosted tokens make self-hosting &lt;em&gt;harder&lt;/em&gt; to justify, not easier. That is the opposite of the intuition that sends teams shopping for GPUs.&lt;/p&gt;

&lt;h3&gt;
  
  
  One incident, priced
&lt;/h3&gt;

&lt;p&gt;An afternoon outage with 8 engineers, 6 hours, 30% blocked: &lt;code&gt;8 × 6 × 0.3 × 95 ≈ $1,368&lt;/code&gt;. That single afternoon is larger than the monthly hosted premium. Two such afternoons a year and the "free" server has cost more than the API line item — before you count the roadmap you didn't ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 4-part gate, with hard stops
&lt;/h2&gt;

&lt;p&gt;Run these in order. A fail is a stop, not a discussion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gate 1 — Shape.&lt;/strong&gt; Do you know &lt;code&gt;tokens_per_accepted_change&lt;/code&gt; from at least one week of logged tasks? No measurement, no decision. Stop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gate 2 — Ops budget.&lt;/strong&gt; Is there a named owner with &lt;code&gt;H&lt;/code&gt; hours blocked on a calendar, every week, not borrowed from feature work? "We'll find the time" is a fail. Stop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gate 3 — Data boundary.&lt;/strong&gt; Can your code leave the environment at all? If any repo in scope is under a contractual or regulatory restriction, the free hosted lane and the paid hosted lane are both out. Stop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gate 4 — Exit cost.&lt;/strong&gt; What does leaving cost, in engineer-days, including the prompt and config work you'll rebuild? Write the number down before you start. If it is unknown, it is unbounded.&lt;/p&gt;

&lt;p&gt;Owner: the platform lead, named. Expiry: 90 days from the first logged task — re-run the script and re-derive. Exit criteria, written up front: ops hours exceed break-even for three consecutive weeks; or acceptance rate drops below your recorded baseline; or exit cost exceeds the savings you projected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where a free hosted lane genuinely earns a place
&lt;/h2&gt;

&lt;p&gt;Not in production. In measurement.&lt;/p&gt;

&lt;p&gt;Gate 1 is the cheap gate and the one teams skip. Standing up a self-hosted box to measure your token shape is backwards — you buy the expensive lane to answer a question the cheap lane answers in a week.&lt;/p&gt;

&lt;p&gt;This is the honest case for something like MonkeyCode, an open-source AI coding project whose operator offers free model access (up to 10,000,000 tokens as described to me on 2026-10-18) and a free server option. As of that date, both are availability claims to verify in-product, not a contract. Use them for Gate 1: a week of real tasks, real rework minutes, real revert counts, no procurement.&lt;/p&gt;

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

&lt;p&gt;What you get out of that week is not a demo. It's the &lt;code&gt;per_acc&lt;/code&gt; number that tells you whether your light shape covers 60 accepted changes or your heavy shape covers 5 — and whether Lane C is even worth pricing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should not use this approach
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Teams with a hard latency or residency requirement.&lt;/strong&gt; Hosted lanes of any kind, free or paid, are out. Run Gate 3 and move on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teams without a named owner.&lt;/strong&gt; You will not log a week of data. Buy the paid hosted lane and revisit in two quarters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anyone who needs pinned model versions for reproducibility.&lt;/strong&gt; Free tiers change under you. Your evals will drift and you'll blame the model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teams treating the free server as a place to keep the only copy of anything.&lt;/strong&gt; It is a measurement sandbox. Mean it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anyone who thinks this scorecard produces a verdict.&lt;/strong&gt; It produces the numbers that make the meeting short.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The question that actually reverses this
&lt;/h2&gt;

&lt;p&gt;Don't ask whether the free tier is worth trying. Almost always, yes — for one week, for Gate 1.&lt;/p&gt;

&lt;p&gt;Ask instead: &lt;strong&gt;what is the highest &lt;code&gt;H&lt;/code&gt; your team would still accept for owning the box?&lt;/strong&gt; Get that number from your manager before you run the script. If the honest answer is "zero" and your break-even comes back at 1.4, you were never making a cost decision. You were making a staffing decision wearing a spreadsheet.&lt;/p&gt;

&lt;p&gt;Write down &lt;code&gt;per_acc&lt;/code&gt;, the break-even hours, the owner, and the expiry date. Then, in ninety days, ask which of those four moved first.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The Free Tier Is Not the Cheap Lane: Pricing Your AI Coding Options per Merged PR</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Sat, 17 Oct 2026 05:43:09 +0000</pubDate>
      <link>https://dev.to/bestbee/the-free-tier-is-not-the-cheap-lane-pricing-your-ai-coding-options-per-merged-pr-cb</link>
      <guid>https://dev.to/bestbee/the-free-tier-is-not-the-cheap-lane-pricing-your-ai-coding-options-per-merged-pr-cb</guid>
      <description>&lt;p&gt;Thursday, 4:40pm. A platform lead drops a screenshot in our channel: free tokens, a free server option, and one line of text — "why are we paying for anything?"&lt;/p&gt;

&lt;p&gt;Fair question. Also the wrong unit. We were never paying for tokens. We were paying for the parts tokens do not include: the retry that ate forty minutes, the review that caught a plausible-but-wrong migration, the maintenance window on a box nobody wanted to own.&lt;/p&gt;

&lt;p&gt;So let's answer it properly. Not with a feature grid, but with a number you can defend in a budget review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define the unit before you define the winner
&lt;/h2&gt;

&lt;p&gt;Price every lane in &lt;strong&gt;cost per merged PR&lt;/strong&gt;. Not cost per seat, not cost per token, not "free".&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
C_{lane} = \frac{\text{model spend} + \text{retry minutes} \times H + \text{review minutes} \times H + \text{blocked wait} \times H + \text{amortized ops}}{\text{merged PRs}}&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;Where &lt;code&gt;H&lt;/code&gt; is your loaded hourly engineer cost divided by 60. Yes, review minutes belong in the numerator. A free lane that doubles review time is not free; it moved the invoice to a person who does not see it.&lt;/p&gt;

&lt;p&gt;Two things to exclude on purpose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sunk setup cost.&lt;/strong&gt; Amortize it, do not argue about it. Past hours are not evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Developer happiness"&lt;/strong&gt; unless you have a proxy. A proxy is something like voluntary lane usage after week two.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;A scorecard like this is a conversation tool, not objective truth. It exists so two people can disagree about the same numbers instead of different vibes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  The ledger: twelve fields, one line per task
&lt;/h2&gt;

&lt;p&gt;You cannot compare lanes you did not measure. Append-only JSONL, committed to the repo, reviewed in a PR like any other artifact.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2026-10-15"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"lane"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"free"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"TICKET-412"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"tokens_in"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"tokens_out"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"wait_s"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;37&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"retries"&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="nl"&gt;"review_min"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"merged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logging one task without a spreadsheet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;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="c"&gt;# ... run your agent or assistant on the ticket ...&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;'{"date":"%s","lane":"%s","task":"%s","tokens_in":%s,"tokens_out":%s,"wait_s":%s,"retries":%s,"review_min":%s,"merged":%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;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"free"&lt;/span&gt; &lt;span class="s2"&gt;"TICKET-412"&lt;/span&gt; 8200 1900 &lt;span class="k"&gt;$((&lt;/span&gt;end-start&lt;span class="k"&gt;))&lt;/span&gt; 1 22 &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ledger.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your tool does not report token counts, write &lt;code&gt;null&lt;/code&gt; and record the proxy you used. A labelled proxy beats a fabricated integer every time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why JSONL and not a dashboard
&lt;/h3&gt;

&lt;p&gt;Because a dashboard someone else owns becomes a number nobody trusts. A file in the repo survives re-quotes, vendor changes, and the person who set it up leaving.&lt;/p&gt;

&lt;h2&gt;
  
  
  The script that ends the argument
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;

&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;85&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;          &lt;span class="c1"&gt;# loaded engineer cost per minute; replace with yours
&lt;/span&gt;&lt;span class="n"&gt;RETRY_MIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;       &lt;span class="c1"&gt;# your measured rework per failed attempt; replace
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;agg&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="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="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;continue&lt;/span&gt;
            &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lane&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;merged&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens_in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens_out&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wait&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wait_s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
            &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retries&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;review&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;review_min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;agg&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;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;review&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wait&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;RETRY_MIN&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prs&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prs&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;cost_per_pr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prs&lt;/span&gt;&lt;span class="sh"&gt;"&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;break_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free_per_pr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hosted_var_per_pr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fixed_month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maint_hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loaded_hourly&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;monthly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fixed_month&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;maint_hours&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;loaded_hourly&lt;/span&gt;
    &lt;span class="n"&gt;saving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;free_per_pr&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;hosted_var_per_pr&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;saving&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;monthly&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;saving&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it weekly. If a lane has fewer than twenty merged PRs, stop and collect more data — small-n comparisons in this space are mostly noise wearing a decimal point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Break-even: the only number that survives a re-quote
&lt;/h2&gt;

&lt;p&gt;A self-hosted or paid lane is worth it only above a volume threshold:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;N* = (fixed monthly + maintenance hours × loaded hourly) / (free cost per PR − hosted variable cost per PR)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Worked example. &lt;strong&gt;All figures below are illustrative inputs, not vendor quotes&lt;/strong&gt; — plug in your own.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixed monthly hosting/seat cost: $180&lt;/li&gt;
&lt;li&gt;Setup: 30 hours, amortized over 12 months → 2.5 h/month&lt;/li&gt;
&lt;li&gt;Ongoing maintenance: 6 h/month at $85/h&lt;/li&gt;
&lt;li&gt;Free lane: $4.10 per merged PR (review-heavy, retry-heavy)&lt;/li&gt;
&lt;li&gt;Hosted lane variable: $0.90 per merged PR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Monthly fixed-equivalent = 180 + (6 + 2.5) × 85 = &lt;strong&gt;$902.50&lt;/strong&gt;. Saving per PR = $3.20. So &lt;code&gt;N* = 282&lt;/code&gt; merged PRs per month.&lt;/p&gt;

&lt;p&gt;Sensitivity, same base except where noted:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;th&gt;N*&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Base&lt;/td&gt;
&lt;td&gt;282&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance drops to 2 h/month&lt;/td&gt;
&lt;td&gt;176&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance rises to 12 h/month&lt;/td&gt;
&lt;td&gt;441&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Free lane gets cheaper ($1.80/PR)&lt;/td&gt;
&lt;td&gt;1,003&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosted variable rises to $1.60/PR&lt;/td&gt;
&lt;td&gt;361&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read the second row, then the fourth. The decision is far more sensitive to your free-lane cost and your maintenance hours than to list price. That is the whole point of measuring before switching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Runway: how long a free allowance actually lasts
&lt;/h2&gt;

&lt;p&gt;An allowance is a pilot budget, not a P&amp;amp;L line. The project operator states a free allowance of &lt;strong&gt;10 million tokens&lt;/strong&gt; and a &lt;strong&gt;free server option&lt;/strong&gt;; verify the current terms yourself before you commit, because allowances move and screenshots go stale.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;months_of_runway = allowance / (median_tokens_per_task × tasks_per_month × people)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Illustrative arithmetic with your own median, not a promise: 9,000 tokens per task, 25 tasks per developer per week, 4 developers → 430 tasks/month → 3.87M tokens/month → about &lt;strong&gt;2.6 months&lt;/strong&gt;. That is enough to fill a ledger. It is not enough to skip the ledger.&lt;/p&gt;

&lt;p&gt;MonkeyCode is the open-source project in that screenshot. Disclosure: This article was prepared as part of MonkeyCode's product outreach. The free model access and free server option are what make it a usable zero-cost control arm in the experiment below — that is the honest role, and it is a real one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision table: fit, not features
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your constraint&lt;/th&gt;
&lt;th&gt;Free lane fits when…&lt;/th&gt;
&lt;th&gt;Self-hosted fits when…&lt;/th&gt;
&lt;th&gt;Paid seat fits when…&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Volume&lt;/td&gt;
&lt;td&gt;below &lt;code&gt;N*&lt;/code&gt;, i.e. you are still learning&lt;/td&gt;
&lt;td&gt;above &lt;code&gt;N*&lt;/code&gt; for two consecutive months&lt;/td&gt;
&lt;td&gt;unpredictable, spiky&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review capacity&lt;/td&gt;
&lt;td&gt;you have slack reviewers&lt;/td&gt;
&lt;td&gt;you have a platform owner&lt;/td&gt;
&lt;td&gt;vendor review tooling is the point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data sensitivity&lt;/td&gt;
&lt;td&gt;work is public or synthetic&lt;/td&gt;
&lt;td&gt;data cannot leave your network&lt;/td&gt;
&lt;td&gt;contract terms beat your own ops&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ops appetite&lt;/td&gt;
&lt;td&gt;nobody wants a pager&lt;/td&gt;
&lt;td&gt;you already run services&lt;/td&gt;
&lt;td&gt;you want no pager at all&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reproducibility&lt;/td&gt;
&lt;td&gt;you can tolerate drift&lt;/td&gt;
&lt;td&gt;you need pinned versions&lt;/td&gt;
&lt;td&gt;you need a paper trail, not control&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Three gates, one owner, one expiry
&lt;/h2&gt;

&lt;p&gt;Every pilot needs an end date or it becomes architecture by accident.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Gate 1 — Instrument (days 0–3).&lt;/strong&gt; Owner: the lead running the pilot. Exit: twenty merged PRs per lane in the ledger, or the comparison is void.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate 2 — Compare (day 14).&lt;/strong&gt; Exit: &lt;code&gt;N*&lt;/code&gt; computed and compared to your actual monthly volume. Decision rule: below 0.5 × &lt;code&gt;N*&lt;/code&gt;, stay free; above 2 × &lt;code&gt;N*&lt;/code&gt;, re-quote hosted; between, extend once, with a written reason.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate 3 — Re-verify and exit (day 30).&lt;/strong&gt; Re-check the allowance and server terms on the date you re-check them, then publish the ledger and pick a lane. Expiry: 30 days from Gate 1. No silent renewals.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want a zero-cost control arm while you run this, the free tier and free server option are a reasonable place to start logging — check the repo README for current terms first, then let the ledger argue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this model breaks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Thin data.&lt;/strong&gt; Under twenty PRs per lane, &lt;code&gt;N*&lt;/code&gt; is theatre.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unlogged review debt.&lt;/strong&gt; If reviewers do not record minutes, the free lane always looks cheaper than it is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allowance drift.&lt;/strong&gt; A quota change mid-pilot invalidates your runway line, not your cost-per-PR line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free server expectations you never wrote down.&lt;/strong&gt; Where the compute lives is not the same as who owns the outage. Ask before you depend on it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One team's numbers.&lt;/strong&gt; &lt;code&gt;N*&lt;/code&gt; does not transfer between teams with different review cultures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who should not use this approach
&lt;/h2&gt;

&lt;p&gt;Teams that cannot commit to logging for two weeks. Teams whose work is confidential and whose free-lane data path is unverified. Teams under roughly 50 merged PRs a month where a single bad week swings the average. And anyone hoping the ledger will confirm a decision they already made.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reversal question
&lt;/h2&gt;

&lt;p&gt;Before you sign anything, write down which single variable would flip your choice: maintenance hours, review minutes, volume, or the allowance itself. Then go measure that one first.&lt;/p&gt;

&lt;p&gt;Which number in your current setup have you never actually measured — and what would it cost you to find out this week?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Free Tokens Are a Claim. Publish a Claim-to-Test Ledger Before You Standardize</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Fri, 16 Oct 2026 04:40:49 +0000</pubDate>
      <link>https://dev.to/bestbee/free-tokens-are-a-claim-publish-a-claim-to-test-ledger-before-you-standardize-27do</link>
      <guid>https://dev.to/bestbee/free-tokens-are-a-claim-publish-a-claim-to-test-ledger-before-you-standardize-27do</guid>
      <description>&lt;p&gt;A message like this lands in an engineering lead's inbox about once a quarter:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"MonkeyCode is open source. Free model access, and a free server option. Give it a try."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two sentences. No workload, no data class, no expiry date. And still enough to start a standardization debate, because the alternative — self-hosting, or a paid seat — has an actual line item attached. Free is the only option in the room with a zero on the invoice.&lt;/p&gt;

&lt;p&gt;So I ask a different question: &lt;strong&gt;what would have to be false for your team to walk away?&lt;/strong&gt; If nobody can answer that, you don't have an evaluation. You have a mood.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The scenario below is a composite, and every number in it is illustrative. Vendor terms are dated and change. Re-verify them before you spend money or reputation on a decision.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "free tokens" is the wrong unit of analysis
&lt;/h2&gt;

&lt;p&gt;Free capacity is real value. It's also a terrible unit for a standardization decision, for three structural reasons.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tokens are an input; work is an outcome.&lt;/strong&gt; A lane that burns 2M tokens and closes 18 of 20 smoke tasks beats a lane that burns 800K tokens and closes 11. Token counts don't tell you which one you have.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A grant is a stock; your workload is a flow.&lt;/strong&gt; 10 million tokens sounds enormous until you know your team's monthly burn. A stock figure without a burn rate is a number with no denominator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The claim expires; the standard doesn't.&lt;/strong&gt; Free tiers change. If four engineers have already written their rules files and prompt libraries around a lane, the price of reversal isn't the invoice — it's the rewrite.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That third point is where most teams quietly lose two weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this specific lane makes a useful test case
&lt;/h2&gt;

&lt;p&gt;MonkeyCode's operator describes it as an open-source project with free model access and a free server option, and states a free grant of 10 million tokens as of 2026-10-16. Those are operator-supplied claims, not verified benchmarks: no public burn rate, no hardware spec, no permanence guarantee. That isn't a defect of the product — it's the normal state of a zero-price offer. And it's exactly why the offer is a good exercise. When the price is zero, the only variables left to test are the ones that actually decide your outcome.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The artifact: a claim-to-test ledger
&lt;/h2&gt;

&lt;p&gt;Stop writing evaluation docs. Write falsification docs. Every vendor sentence becomes one row with a test, an owner, and an expiry date.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;What goes in it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claim (verbatim)&lt;/td&gt;
&lt;td&gt;Quote it. Never paraphrase a promise.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Falsifying test&lt;/td&gt;
&lt;td&gt;The cheapest thing that could prove it false this sprint.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instrument&lt;/td&gt;
&lt;td&gt;Dashboard, CI job, task log, or a stopwatch.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minutes&lt;/td&gt;
&lt;td&gt;Real estimated cost of the test.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pass if&lt;/td&gt;
&lt;td&gt;A threshold you commit to &lt;em&gt;before&lt;/em&gt; you see the result.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse signal&lt;/td&gt;
&lt;td&gt;What failure would change your decision, not just your mood.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Owner&lt;/td&gt;
&lt;td&gt;One human, by name.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expiry&lt;/td&gt;
&lt;td&gt;The date the claim must be re-checked.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Define the variables first
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;T&lt;/code&gt; — number of claims under test&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;h&lt;/code&gt; — average minutes per falsification test&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;F = T × h / 60&lt;/code&gt; — falsification hours&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;p&lt;/code&gt; — your honest probability of reversing the decision within one quarter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;R&lt;/code&gt; — rework hours to undo the decision (rules files, prompt library, eval sets, CI wiring, docs)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;W&lt;/code&gt; — loaded hourly cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the ledger when &lt;code&gt;p × R &amp;gt; F&lt;/code&gt;. The break-even threshold is &lt;code&gt;p* = F / R&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;W&lt;/code&gt; cancels out of both sides. That's the useful part: you never have to defend your loaded hourly rate to anyone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Worked example (illustrative)
&lt;/h3&gt;

&lt;p&gt;A platform team of six evaluates the lane with nine claims. &lt;code&gt;F = 9 × 40 / 60 = 6&lt;/code&gt; hours. They measure &lt;code&gt;R = 60&lt;/code&gt; hours of context rewrites with the shell snippet below rather than guessing. Then &lt;code&gt;p* = 6 / 60 = 0.10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Translation: if you believe there's more than a 1-in-10 chance you'd reverse this decision inside a quarter, the ledger pays for itself. That is a much easier argument to win than "let's do a proper evaluation."&lt;/p&gt;

&lt;h3&gt;
  
  
  The ledger, filled in
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Claim (abbreviated)&lt;/th&gt;
&lt;th&gt;Falsifying test&lt;/th&gt;
&lt;th&gt;Min&lt;/th&gt;
&lt;th&gt;Reverse signal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C1&lt;/td&gt;
&lt;td&gt;free grant, operator-stated&lt;/td&gt;
&lt;td&gt;run the 20-task smoke set twice; log tokens and tasks closed&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;grant covers &amp;lt; 5 working days at observed burn&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C2&lt;/td&gt;
&lt;td&gt;free server option&lt;/td&gt;
&lt;td&gt;run the smoke set during a real PR window; record wall-clock queueing&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;queueing longer than your review window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C3&lt;/td&gt;
&lt;td&gt;open source&lt;/td&gt;
&lt;td&gt;clone it, build it, run the smoke set against your own copy&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;build path requires access you don't have&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C4&lt;/td&gt;
&lt;td&gt;context export&lt;/td&gt;
&lt;td&gt;export rules files and prompt library; diff against your repo&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;export is lossy or manual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C5&lt;/td&gt;
&lt;td&gt;CI latency&lt;/td&gt;
&lt;td&gt;wire one nightly job; compare p95 wall clock to baseline&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;p95 blows the nightly budget&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C6&lt;/td&gt;
&lt;td&gt;review latency&lt;/td&gt;
&lt;td&gt;count human review minutes on 20 lane-authored PRs&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;review minutes exceed authoring savings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C7&lt;/td&gt;
&lt;td&gt;data class&lt;/td&gt;
&lt;td&gt;ask policy whether your code class may be processed externally&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;policy answer is an absolute no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C8&lt;/td&gt;
&lt;td&gt;offboarding&lt;/td&gt;
&lt;td&gt;remove one engineer mid-week; confirm access and cost state&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;access or billing state becomes murky&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C9&lt;/td&gt;
&lt;td&gt;version pinning&lt;/td&gt;
&lt;td&gt;pin a known-good configuration; re-run C1 after a restart&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;behavior drifts with no changelog&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note that C7 costs fifteen minutes and can end the entire evaluation. Cheap tests first. Always.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sensitivity: when the ledger is not worth running
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;T&lt;/th&gt;
&lt;th&gt;h&lt;/th&gt;
&lt;th&gt;F&lt;/th&gt;
&lt;th&gt;p&lt;/th&gt;
&lt;th&gt;R&lt;/th&gt;
&lt;th&gt;p×R&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Beachhead: 2 engineers, 1 repo&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;2.0&lt;/td&gt;
&lt;td&gt;0.15&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;1.8&lt;/td&gt;
&lt;td&gt;Skip the ledger — just pilot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scale-up: 6 engineers, 3 repos&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;td&gt;0.30&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;18.0&lt;/td&gt;
&lt;td&gt;Run it this sprint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Regulated: 40 engineers, 2 BUs&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;14.0&lt;/td&gt;
&lt;td&gt;0.40&lt;/td&gt;
&lt;td&gt;240&lt;/td&gt;
&lt;td&gt;96.0&lt;/td&gt;
&lt;td&gt;Run it, then gate on C7 alone&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Look at row one. &lt;code&gt;p × R = 1.8&lt;/code&gt; beats &lt;code&gt;F = 2.0&lt;/code&gt; — barely. If your blast radius is one repo and two people, the correct decision is to skip the ceremony and use the lane for a week. Ledgers are for decisions that are expensive to reverse, not for curiosity.&lt;/p&gt;

&lt;p&gt;Break-even moves fast: at &lt;code&gt;R = 12&lt;/code&gt; hours, &lt;code&gt;p* = 17%&lt;/code&gt;. At &lt;code&gt;R = 60&lt;/code&gt;, &lt;code&gt;p* = 10%&lt;/code&gt;. At &lt;code&gt;R = 240&lt;/code&gt;, &lt;code&gt;p* = 6%&lt;/code&gt;. The more context you have to rewrite, the lower the bar for testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure &lt;code&gt;R&lt;/code&gt; instead of estimating it
&lt;/h2&gt;

&lt;p&gt;Rework hours are the one number teams routinely invent. Count your context assets 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;# context assets a reversal would force you to rewrite — count, don't guess&lt;/span&gt;
rg &lt;span class="nt"&gt;--files&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="s1"&gt;'AGENTS.md'&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="s1"&gt;'*.mdc'&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="s1"&gt;'prompts/**'&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="s1"&gt;'evals/**'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | xargs &lt;span class="nt"&gt;-r&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;tail&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then keep the ledger in a file so it survives the meeting where everyone agrees verbally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ledger.yaml — one row per claim you are willing to falsify&lt;/span&gt;
&lt;span class="c1"&gt;# Scaffold only; the operator's stated terms are dated 2026-10-16 and must be re-checked.&lt;/span&gt;
&lt;span class="na"&gt;decision&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;standardize-free-lane&lt;/span&gt;
&lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;platform-lead&lt;/span&gt;              &lt;span class="c1"&gt;# a person, not a team&lt;/span&gt;
&lt;span class="na"&gt;review_date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-11-13&lt;/span&gt;           &lt;span class="c1"&gt;# claims expire; so does the decision&lt;/span&gt;
&lt;span class="na"&gt;loaded_hourly_cost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;85&lt;/span&gt;
&lt;span class="na"&gt;reverse_rework_hours&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;          &lt;span class="c1"&gt;# measured above, not estimated&lt;/span&gt;
&lt;span class="na"&gt;claims&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;C1&lt;/span&gt;
    &lt;span class="na"&gt;claim&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;free&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;grant&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;stated&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;by&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;operator&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(2026-10-16)"&lt;/span&gt;
    &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;20-task&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;smoke&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;set&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;twice;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;log&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tokens&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;completed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tasks"&lt;/span&gt;
    &lt;span class="na"&gt;pass_if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;=18/20&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tasks&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;complete,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;twice"&lt;/span&gt;
    &lt;span class="na"&gt;reverse_signal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grant&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;covers&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;working&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;days&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;at&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;observed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;burn"&lt;/span&gt;
    &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;platform-lead&lt;/span&gt;
    &lt;span class="na"&gt;expiry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-11-13&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;C7&lt;/span&gt;
    &lt;span class="na"&gt;claim&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;we&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;may&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;process&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;this&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;class&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;externally"&lt;/span&gt;
    &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ask&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;policy;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;get&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;answer&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;writing"&lt;/span&gt;
    &lt;span class="na"&gt;pass_if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;written&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;yes,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;scope"&lt;/span&gt;
    &lt;span class="na"&gt;reverse_signal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;any&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;conditional&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;verbal&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;answer"&lt;/span&gt;
    &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;em&lt;/span&gt;
    &lt;span class="na"&gt;expiry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-11-13&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ledger.py — scaffold I wrote for this article; no tests, only PyYAML required
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;

&lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safe_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;span class="n"&gt;claims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claims&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;minutes&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;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&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;claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&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;claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
&lt;span class="n"&gt;p_star&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reverse_rework_hours&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;T=&lt;/span&gt;&lt;span class="si"&gt;{&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;claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; h=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;min F=&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="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;h break-even p*=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p_star&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run the ledger only if your reversal probability beats that number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;today&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;today&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;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;claims&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;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expiry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EXPIRED &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; — owner &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;owner&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: re-check or drop the standard&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;Run that on your own file before your next architecture sync, not after.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free lane, self-host, or paid seat: fit criteria, not vibes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criterion&lt;/th&gt;
&lt;th&gt;Free hosted lane&lt;/th&gt;
&lt;th&gt;Self-host&lt;/th&gt;
&lt;th&gt;Paid alternative&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cash price&lt;/td&gt;
&lt;td&gt;zero (operator-stated)&lt;/td&gt;
&lt;td&gt;infra + ops hours&lt;/td&gt;
&lt;td&gt;per seat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Whose machine processes the work&lt;/td&gt;
&lt;td&gt;vendor — test C7&lt;/td&gt;
&lt;td&gt;yours&lt;/td&gt;
&lt;td&gt;vendor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reversal cost &lt;code&gt;R&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;context rewrites&lt;/td&gt;
&lt;td&gt;near zero if the repo is yours&lt;/td&gt;
&lt;td&gt;seat migration + retraining&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ops hours you own&lt;/td&gt;
&lt;td&gt;lowest&lt;/td&gt;
&lt;td&gt;highest&lt;/td&gt;
&lt;td&gt;middle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure mode&lt;/td&gt;
&lt;td&gt;terms change under you&lt;/td&gt;
&lt;td&gt;nobody maintains it&lt;/td&gt;
&lt;td&gt;renewal becomes the default&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Fit rules I'd actually apply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Take the free hosted lane&lt;/strong&gt; when &lt;code&gt;F &amp;lt; 8&lt;/code&gt; hours, one team, two repos or fewer, and someone owns a recurring re-check. Free buys you falsification time; it doesn't buy you a standard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-host&lt;/strong&gt; when the code class can't leave, you already run the ops capacity, and the workload is steady enough to justify it. If self-hosting is a weekend project for one person, you've just created a bus factor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pay per seat&lt;/strong&gt; when administration, procurement, and offboarding consistency matter more than unit price. That's a governance purchase, not an engineering one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hard gates, owner, expiry, exit
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gate 1 — owner.&lt;/strong&gt; No named owner for the C1–C3 re-check, no standardization. The ledger decays the moment nobody owns it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate 2 — spend.&lt;/strong&gt; No paid commitment before C1, C2, and C7 have a recorded pass or fail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate 3 — data class.&lt;/strong&gt; If C7 comes back as an absolute no, this was never a ledger question. It's a stop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit criteria.&lt;/strong&gt; At expiry: standardize if 7 or more of 9 claims pass. Extend one cycle if 5–6 pass with a named owner. Stop if fewer than 5 pass, or if C7 fails.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Every number above is illustrative. A ledger is a conversation tool, not objective truth, and it will not settle a disagreement between people who want different answers.&lt;/li&gt;
&lt;li&gt;Operator-stated terms — free model access, the free server option, the stated free grant, the open-source description — are dated 2026-10-16 and may change. The ledger's value is that it forces you to re-test rather than re-cite.&lt;/li&gt;
&lt;li&gt;It does not price the human cost of a bad lane: review fatigue, morale, the senior engineer who quietly stops reviewing.&lt;/li&gt;
&lt;li&gt;It assumes you can name &lt;code&gt;R&lt;/code&gt; with some honesty. If your context assets live in one person's head, measure that problem first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skip this approach entirely if&lt;/strong&gt; you're a solo developer with no shared context to rewrite (just use the thing for a week), if your data policy is already an absolute no, or if you want a benchmark verdict rather than a decision framework. Benchmarks tell you what a lane can do. Ledgers tell you what it would cost to leave.&lt;/p&gt;

&lt;p&gt;If you want a lane that's cheap enough to falsify, MonkeyCode's repository is a reasonable place to run C1 and C2 against your own smoke set — the whole exercise costs about forty minutes, and that is the point of a zero-price offer.&lt;/p&gt;

&lt;p&gt;One last question, and it's the only one that matters: &lt;strong&gt;which single claim in your ledger would flip your decision if it failed — and who is re-checking it on 2026-11-13?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Should Your Team Commit to a Free AI Lane? Use This Exit Amortization Sheet</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Thu, 15 Oct 2026 11:05:03 +0000</pubDate>
      <link>https://dev.to/bestbee/should-your-team-commit-to-a-free-ai-lane-use-this-exit-amortization-sheet-2413</link>
      <guid>https://dev.to/bestbee/should-your-team-commit-to-a-free-ai-lane-use-this-exit-amortization-sheet-2413</guid>
      <description>&lt;p&gt;Last Thursday a platform lead asked me a question I get about once a month: "We're running on free AI capacity. When do we have to decide whether to stay?"&lt;/p&gt;

&lt;p&gt;I asked him one thing back. What does leaving cost you, in engineer-hours? Silence for a few seconds. Then: "We'd have to rewrite the CI wrapper and port the prompt library. Maybe two weeks?"&lt;/p&gt;

&lt;p&gt;That's the number that decides. Not the token count. Not the seats. The exit.&lt;/p&gt;

&lt;p&gt;Free capacity gets priced at zero, so most teams quietly treat it as infinite. It isn't. It's a loan, and the balloon payment is called migration — the work you do the day the terms change, the allowance runs out, or your security review catches up with you.&lt;/p&gt;

&lt;p&gt;Quick context on why this is showing up now: DEV's front page over the past week carried a lot of AI fatigue discussion (a "AI Fatigue? Yea I know." post picked up 106 reactions on Oct 13) and a piece arguing AI tools improved while the software around them didn't (96 reactions, Oct 9). &lt;a href="https://dev.to/francistrdev/ai-fatigue-yea-i-know-f9"&gt;Community signal&lt;/a&gt; is not evidence, but it's a decent hint that teams are consolidating lanes instead of adding them. Consolidation decisions need a number.&lt;/p&gt;

&lt;p&gt;Here's the number, and here's how to compute it yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Name the three columns
&lt;/h2&gt;

&lt;p&gt;This sheet only makes sense if you're comparing real alternatives. I use three:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Free hosted lane.&lt;/strong&gt; Concretely, for this walkthrough: MonkeyCode's free model access plus its free server option. The operator describes both as available at no cost, with a stated free allowance of 10 million tokens. Verify current terms on the project page before you build a budget on them — that is true of every free tier, including this one.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Paid hosted lane.&lt;/strong&gt; Any per-seat or per-token plan with a contract, an SLA, and a billing line you can point at during a renewal conversation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-host.&lt;/strong&gt; You run it. This only exists as a column if the project is open source and the repository's current docs actually support the deployment you need — MonkeyCode is an open-source project, so check its repo before assuming this path is available to you.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The mistake I see most often is comparing column 1 against column 2 by sticker price and comparing column 1 against column 3 by nothing at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Measure your own burn, not someone else's
&lt;/h2&gt;

&lt;p&gt;A stated allowance is meaningless until it's divided by &lt;em&gt;your&lt;/em&gt; consumption. So measure it. Ten merged PRs is enough to get a usable median.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick 10 merged PRs from the last month that used the lane.&lt;/li&gt;
&lt;li&gt;Log the usage number your client reports for each one, plus whether the PR needed a rewrite after review.&lt;/li&gt;
&lt;li&gt;Take the median of the clean ones. Keep the messy ones as a separate "rework" bucket.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not use a vendor's tokens-per-task figure. It's measured on someone else's code, at someone else's review standard. If you can't measure 10 PRs, you can't run this sheet yet — that's a real answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Convert the allowance into runway months
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# exit_ledger.py — free-lane runway and exit break-even
# Inputs below are ILLUSTRATIVE. Replace with your measured values.
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replace&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;free_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;         &lt;span class="c1"&gt;# operator-stated allowance; re-verify before budgeting
&lt;/span&gt;    &lt;span class="n"&gt;tokens_per_pr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;       &lt;span class="c1"&gt;# YOUR measured median, tokens per merged PR
&lt;/span&gt;    &lt;span class="n"&gt;prs_per_month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;       &lt;span class="c1"&gt;# YOUR merged PRs per month on this lane
&lt;/span&gt;    &lt;span class="n"&gt;saved_hours_month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;   &lt;span class="c1"&gt;# engineer-hours saved per month vs next-best option
&lt;/span&gt;    &lt;span class="n"&gt;hourly_cost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;         &lt;span class="c1"&gt;# fully loaded $ per engineer-hour
&lt;/span&gt;    &lt;span class="n"&gt;exit_hours&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;          &lt;span class="c1"&gt;# one-time hours to leave or migrate the lane
&lt;/span&gt;    &lt;span class="n"&gt;residual_hours&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;      &lt;span class="c1"&gt;# monthly overhead the free lane adds (rework, governance)
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;runway_months&lt;/span&gt;&lt;span class="p"&gt;(&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;Inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;burn&lt;/span&gt; &lt;span class="o"&gt;=&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;tokens_per_pr&lt;/span&gt; &lt;span class="o"&gt;*&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;prs_per_month&lt;/span&gt;
    &lt;span class="k"&gt;return&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;free_tokens&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;burn&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;burn&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;net_savings_month&lt;/span&gt;&lt;span class="p"&gt;(&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;Inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&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;saved_hours_month&lt;/span&gt; &lt;span class="o"&gt;-&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;residual_hours&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&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;hourly_cost&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;break_even_month&lt;/span&gt;&lt;span class="p"&gt;(&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;Inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;net_savings_month&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&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;net&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# the free lane costs more than it saves
&lt;/span&gt;    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&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;exit_hours&lt;/span&gt; &lt;span class="o"&gt;*&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;hourly_cost&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reversal_exit_hours&lt;/span&gt;&lt;span class="p"&gt;(&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;Inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Exit hours at which savings never amortize inside the runway.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;net_savings_month&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;runway_months&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&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;hourly_cost&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sensitivity&lt;/span&gt;&lt;span class="p"&gt;(&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;Inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exits&lt;/span&gt;&lt;span class="o"&gt;=&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="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;savings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;24&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;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;savings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;exits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&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;exit_hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;saved_hours_month&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;break_even_month&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&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;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Filled with illustrative numbers — &lt;strong&gt;my example, not a benchmark&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;free_tokens&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10,000,000 (stated allowance, 2026-10-15)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tokens_per_pr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;45,000 (illustrative median)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;prs_per_month&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;saved_hours_month&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hourly_cost&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;exit_hours&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;residual_hours&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Run it and you get: burn 1.8M tokens/month, &lt;strong&gt;runway ≈ 5.6 months&lt;/strong&gt;, net savings ≈ $1,190/month, &lt;strong&gt;break-even ≈ 4.3 months&lt;/strong&gt;, and a reversal threshold of &lt;strong&gt;≈ 78 exit hours&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Read that last one out loud, because it's the whole point. If porting the CI wrapper and the prompt library takes more than roughly 78 engineer-hours, the free lane's savings never pay back inside its own runway. You would have saved money by starting on the paid column.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Sensitize, then set a hard gate
&lt;/h2&gt;

&lt;p&gt;Single-point answers are how teams get burned. Run the grid.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;break-even month ↓ / exit hours →&lt;/th&gt;
&lt;th&gt;20&lt;/th&gt;
&lt;th&gt;40&lt;/th&gt;
&lt;th&gt;80&lt;/th&gt;
&lt;th&gt;160&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;net $850/mo&lt;/td&gt;
&lt;td&gt;2.0&lt;/td&gt;
&lt;td&gt;4.0&lt;/td&gt;
&lt;td&gt;8.0&lt;/td&gt;
&lt;td&gt;16.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net $1,190/mo&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;2.9&lt;/td&gt;
&lt;td&gt;5.7&lt;/td&gt;
&lt;td&gt;11.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net $2,040/mo&lt;/td&gt;
&lt;td&gt;0.8&lt;/td&gt;
&lt;td&gt;1.7&lt;/td&gt;
&lt;td&gt;3.3&lt;/td&gt;
&lt;td&gt;6.7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And sensitize the runway, because burn is the variable you control least:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;PRs/month&lt;/th&gt;
&lt;th&gt;Burn&lt;/th&gt;
&lt;th&gt;Runway on 10M&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;0.9M&lt;/td&gt;
&lt;td&gt;11.1 months&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;1.8M&lt;/td&gt;
&lt;td&gt;5.6 months&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;3.6M&lt;/td&gt;
&lt;td&gt;2.8 months&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now the gate. I use &lt;strong&gt;break-even ≤ 60% of runway&lt;/strong&gt;, because free terms move and my measurements are median-based, not precise. At 5.6 months of runway that's a 3.4-month ceiling, which at $1,190/month of net savings caps your exit at about &lt;strong&gt;48 engineer-hours&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Write that cap on the ticket before the pilot ends. Gates that aren't written down before you're attached to the outcome are not gates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who owns it, when it expires, when you leave
&lt;/h2&gt;

&lt;p&gt;A ledger without an owner is a spreadsheet. So attach three fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Owner:&lt;/strong&gt; one named person, not a team. This is usually the EM or platform lead who can actually stop the PRs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expiry:&lt;/strong&gt; a date, not "when the allowance runs out." I default to the runway month minus one, so you decide with a month of margin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit criteria:&lt;/strong&gt; the measured condition that sends you to column 2, written as a number. Example: "if measured burn exceeds 2.5M tokens/month for two consecutive months, move to the paid lane and re-run the sheet."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the expiry date, do one of three things: renew the free lane with fresh terms, move to paid, or migrate to self-host. Doing nothing is also a choice, and it's the expensive one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should &lt;em&gt;not&lt;/em&gt; use this sheet
&lt;/h2&gt;

&lt;p&gt;Be honest about the fit criteria, including the ones that disqualify you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You have no single owner.&lt;/strong&gt; Without one person able to kill the lane, the exit cost grows silently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your data path isn't cleared.&lt;/strong&gt; Cost math does not override a security review. Resolve the review first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You expect less than about two months of use.&lt;/strong&gt; Then the free lane is the right answer and the ledger is overkill — just use it and don't build tooling around it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can't measure tokens per PR yet.&lt;/strong&gt; Measurement is step 1 for a reason.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And a fairness caveat in the other direction: for a solo developer or a two-person side project, exit cost is near zero and none of this matters. Free is free. This sheet is for teams where migration is a project, not an afternoon.&lt;/p&gt;

&lt;h2&gt;
  
  
  The question that reverses you
&lt;/h2&gt;

&lt;p&gt;My example lands on "commit, with a 48-hour exit cap." Yours will land somewhere else, and that's fine. A sheet like this is a conversation tool, not objective truth — it makes the disagreement legible, it doesn't settle it.&lt;/p&gt;

&lt;p&gt;So here's what I'd actually want to know from you: which single input flips your answer? The exit hours, the burn per merged PR, or the residual overhead? If it's the burn, you can only find out by measuring, and a free lane is the cheapest place to get that measurement.&lt;/p&gt;

&lt;p&gt;That's the honest role MonkeyCode plays in this method: it's the column you use to collect a real month of &lt;code&gt;tokens_per_pr&lt;/code&gt; before you sign anything. Its free model access and free server option are what make the measurement phase cheap; the ledger does the deciding.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Price the Assistant Path in Disagree-Minutes, Not a Free Sticker</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Mon, 12 Oct 2026 22:41:53 +0000</pubDate>
      <link>https://dev.to/bestbee/price-the-assistant-path-in-disagree-minutes-not-a-free-sticker-274p</link>
      <guid>https://dev.to/bestbee/price-the-assistant-path-in-disagree-minutes-not-a-free-sticker-274p</guid>
      <description>&lt;p&gt;Picture a Thursday release desk that I am using as a composite, not as a customer story. Three engineers share one assistant path because the sticker says free. The suggestion looks tidy. Nobody pushes back.&lt;/p&gt;

&lt;p&gt;Twenty minutes later the same function is in review again. The assistant nodded at a null check the service has never had. Sound familiar?&lt;/p&gt;

&lt;p&gt;Here is the rude question I ask before anyone opens a pricing page. How many minutes did you spend throwing that suggestion away and trying again?&lt;/p&gt;

&lt;p&gt;If that number is fat, a free sticker can be the expensive path. If it is thin, buying a second path is theater. Which one is on your board this week?&lt;/p&gt;

&lt;h2&gt;
  
  
  What I am pricing, and what I refuse to fake
&lt;/h2&gt;

&lt;p&gt;I am not pricing tokens. I am not pricing rollback hours. I am not scoring how "incident-adjacent" the work felt. Those are other decisions, and mixing them is how a review becomes a slogan contest.&lt;/p&gt;

&lt;p&gt;This ledger prices disagree-minutes. A disagree event is a suggestion an engineer discards, re-prompts, or rewrites before merge. Clock time. Not vibes.&lt;/p&gt;

&lt;p&gt;It is a conversation tool. It is not objective truth, and it is not a benchmark of any vendor. If your inputs are guesses, the output is a guess with cleaner handwriting.&lt;/p&gt;

&lt;p&gt;Public developer threads this week kept circling the same bruise: retry decisions, and assistants that agree too fast. I am not treating those posts as evidence about any product. I am treating the bruise as a buying question. When the assistant stops arguing, do you stay, pay, or take the ops bill yourselves?&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 operator supplied two availability claims for that project, and described it as open source: free model access, and a free server option. I am not asserting a quota, a hardware shape, a duration, a model name, a license text, or permanence. Those are facts you confirm on the current project page the day you decide. If the page and this paragraph disagree, believe the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four paths, one unit
&lt;/h2&gt;

&lt;p&gt;You are not choosing "free versus real." You are choosing among four paths.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stay on hosted free model access, if that offer still exists when you look.&lt;/li&gt;
&lt;li&gt;Use the free server option, if the current offer actually changes who holds the queue and the prompts.&lt;/li&gt;
&lt;li&gt;Buy a paid path from a vendor who will invoice you.&lt;/li&gt;
&lt;li&gt;Self-host a stack your platform team will still operate in week six.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Define the variables before anyone types a number. Otherwise the meeting will invent a winner.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;N&lt;/code&gt; — engineers on this path this week&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;R&lt;/code&gt; — discarded suggestions per engineer per week&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;M&lt;/code&gt; — minutes to discard, re-prompt, and re-check one discard&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;H&lt;/code&gt; — loaded hourly cost for those engineers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Q&lt;/code&gt; — minutes lost when access stops mid-task, times how often it happened, times &lt;code&gt;H&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;P&lt;/code&gt; — paid invoice for the same week, in money you already spend&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;S&lt;/code&gt; — platform hours for self-host or for running the free server option, times platform hourly cost, plus any hosting you actually pay&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;D&lt;/code&gt; — custody hard-gate, yes or no. Not a made-up dollar figure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Weekly disagree cost is &lt;code&gt;N * R * M / 60 * H&lt;/code&gt;. Add &lt;code&gt;Q&lt;/code&gt;. Compare that sum with &lt;code&gt;P&lt;/code&gt;, and with &lt;code&gt;S&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A score without an owner and an expiry is a poster. Name the engineering manager. Expire the choice in 14 days. Exit if measured &lt;code&gt;R&lt;/code&gt; does not move, or if &lt;code&gt;D&lt;/code&gt; flips to yes.&lt;/p&gt;

&lt;h2&gt;
  
  
  A filled example, labeled as fiction
&lt;/h2&gt;

&lt;p&gt;Do not copy these inputs into a slide and call them a pilot. They are a worksheet illustration. They are not a MonkeyCode measurement, not a market study, and not your ROI.&lt;/p&gt;

&lt;p&gt;Suppose &lt;code&gt;N = 8&lt;/code&gt;, &lt;code&gt;R = 6&lt;/code&gt;, &lt;code&gt;M = 12&lt;/code&gt;, &lt;code&gt;H = 80&lt;/code&gt;. Disagree cost is &lt;code&gt;8 * 6 * 12 / 60 * 80 = 768&lt;/code&gt; per week. That 768 is the number that can reverse "free is free."&lt;/p&gt;

&lt;p&gt;Now a hypothetical paid pilot cuts &lt;code&gt;R&lt;/code&gt; from 6 to 2, and &lt;code&gt;P&lt;/code&gt; is 400. New disagree cost is &lt;code&gt;8 * 2 * 12 / 60 * 80 = 256&lt;/code&gt;. Savings against the old path: &lt;code&gt;768 - 256 = 512&lt;/code&gt;. Net of the invoice: &lt;code&gt;512 - 400 = 112&lt;/code&gt;. Thin. One stubborn week and the paid path loses.&lt;/p&gt;

&lt;p&gt;Sensitivity, same fake inputs. If &lt;code&gt;M&lt;/code&gt; is 5, not 12, the original disagree cost falls to &lt;code&gt;8 * 6 * 5 / 60 * 80 = 320&lt;/code&gt;. Paying 400 to chase 320 is a no, unless custody already forced you off hosted free. If the paid path keeps &lt;code&gt;R&lt;/code&gt; at 6, you bought a more expensive nod. Why would you renew that?&lt;/p&gt;

&lt;p&gt;Self-host uses the same math and a different bill. Six platform hours at 90 is 540, before any model hosting you actually pay. The free server option might shrink &lt;code&gt;S&lt;/code&gt;. It might not. I will not pretend I timed it. Put real ops hours into &lt;code&gt;S&lt;/code&gt; after a week of running the option, or do not claim a saving.&lt;/p&gt;

&lt;p&gt;What reverses the illustration even when 768 looks scary? &lt;code&gt;D = yes&lt;/code&gt;. If prompts, diffs, or customer code cannot sit on a hosted free path, the sticker is irrelevant. You leave. Then disagree-minutes only break the tie between a paid contract and self-host, including whether the free server option changes custody or merely changes the login screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incentives, not applause
&lt;/h3&gt;

&lt;p&gt;A free path trains a quiet habit. People stop arguing with the suggestion because arguing feels like wasting a gift. Paid paths train a different quiet habit. People defend the invoice. Self-host trains a third one. Platform defends the cluster they stayed up to build.&lt;/p&gt;

&lt;p&gt;Ask who gets praised. The engineer who merges fast, or the engineer who discards a fluent wrong diff? If the first one gets the praise, your &lt;code&gt;R&lt;/code&gt; is under-counted, and every path will look smarter than it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Log discards like bugs
&lt;/h2&gt;

&lt;p&gt;I want a row each time someone throws a suggestion away. This format is a proposal. I have not run it in your repo, and it does not call a vendor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# retry-log.tsv
# ts    engineer    lane    minutes reason  page_risk
2026-10-13T15:04:00Z    eng-a   hosted-free 11  agreed-with-missing-null    no
2026-10-13T15:22:00Z    eng-b   hosted-free 18  retried-same-bug    no
2026-10-13T16:01:00Z    eng-c   paid-pilot  4   style-only  no
2026-10-13T16:40:00Z    eng-a   free-server 9   queue-stall-then-rewrite    no
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read it before anyone builds a dashboard:&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;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt;&lt;span class="s1"&gt;'\t'&lt;/span&gt; &lt;span class="s1"&gt;'NR&amp;gt;2 {n[$3]++; mins[$3]+=$4} END {for (l in n) printf "%s rows=%d minutes=%d\n", l, n[l], mins[l]}'&lt;/span&gt; retry-log.tsv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rows and minutes by path. That will not prove quality. It will stop the argument from living in Slack memory. If &lt;code&gt;page_risk&lt;/code&gt; is ever &lt;code&gt;yes&lt;/code&gt;, stop the ledger and use your incident review. This sheet is the wrong tool while a pager is hot.&lt;/p&gt;

&lt;p&gt;Then a tiny gate. Unexecuted proposal. Swap the constants. The &lt;code&gt;+ 50&lt;/code&gt; is a friction buffer I picked so a 10-currency "win" cannot flip a squad. Change it in the review, out loud.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# proposal_retry_gate.py — illustration, not a measured benchmark
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;weekly_cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;60.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hosted_cost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hosted_r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paid_invoice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paid_r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;custody_blocked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&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;custody_blocked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exit-hosted-free&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;paid_total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;weekly_cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paid_r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;paid_invoice&lt;/span&gt;
    &lt;span class="c1"&gt;# Recompute paid_total with YOUR n, m, h. The 8/12/80 above match the fiction only.
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;paid_total&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;hosted_cost&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;paid_r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;hosted_r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pilot-paid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self_host&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;hosted_cost&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;self_host&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;paid_total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price-self-host-or-free-server&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stay-and-remeasure&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;hosted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;weekly_cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&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="n"&gt;hosted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hosted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;540&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On these fake inputs the print is &lt;code&gt;768&lt;/code&gt; and &lt;code&gt;pilot-paid&lt;/code&gt;, because &lt;code&gt;256 + 400 + 50&lt;/code&gt; is still under 768 and &lt;code&gt;R&lt;/code&gt; fell. Drop &lt;code&gt;paid_r&lt;/code&gt; back to 6 and the same function should refuse the upgrade. A green demo that never disagrees is not a win. It is an unmeasured nod.&lt;/p&gt;

&lt;p&gt;Fix the script before you trust it: pass &lt;code&gt;n&lt;/code&gt;, &lt;code&gt;m&lt;/code&gt;, and &lt;code&gt;h&lt;/code&gt; into &lt;code&gt;gate&lt;/code&gt; instead of leaving the illustration constants inside &lt;code&gt;paid_total&lt;/code&gt;. I left that smell on purpose. If nobody notices, you are not ready to let a worksheet pick a vendor.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 4-part gate
&lt;/h2&gt;

&lt;p&gt;Run these in order. Skipping to price is how free stickers win arguments they should lose.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hard stop.&lt;/strong&gt; If the change can page a human, the path does not merge it. Hosted free, paid, free server, self-host — same rule. A fluent yes is not a review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custody.&lt;/strong&gt; Can this repo's prompts and diffs live on the hosted free path under current policy? If no, exit today. Then ask whether the free server option changes who holds the data, or only where the process runs. If the docs do not say, the answer is no.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disagree-minutes versus invoice.&lt;/strong&gt; Only after the first two. Run a 14-day paid pilot with the same log. If &lt;code&gt;R&lt;/code&gt; does not fall enough to beat &lt;code&gt;P&lt;/code&gt; plus your buffer, stop. Do not "give it a quarter" because the demo felt sharp.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ops reality.&lt;/strong&gt; If self-host, or the free server option, needs a platform owner you do not have, it is not the cheap path. Blank name means &lt;code&gt;S&lt;/code&gt; is infinite for this decision.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Owner: the engineering manager for that squad. Expiry: 14 days from the first logged row, dated on the doc, not in someone's head. Exit criteria: &lt;code&gt;R&lt;/code&gt; unchanged, custody unclear, or free access interrupted often enough that &lt;code&gt;Q&lt;/code&gt; alone exceeds &lt;code&gt;P&lt;/code&gt;. Archive the choice in the same doc. No silent renewals.&lt;/p&gt;

&lt;p&gt;Re-open the doc if headcount, repo sensitivity, or the vendor's terms change before day 14. A gate that cannot expire is a loyalty program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should walk away
&lt;/h2&gt;

&lt;p&gt;Skip this ledger if any of these are true.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have no human reviewer. The hole is the merge policy, not the sticker.&lt;/li&gt;
&lt;li&gt;You need a quota, an SLA, or a box size. This article is not a spec sheet. Read the current offer.&lt;/li&gt;
&lt;li&gt;Your week is incident response. Disagree-minutes are a planning unit, not a pager unit.&lt;/li&gt;
&lt;li&gt;You wanted a cluster tutorial. A decision gate will not install one, and I am not going to pretend it will.&lt;/li&gt;
&lt;li&gt;You cannot name the variable that would reverse you. Then you are shopping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also skip it if the squad will not log discards. An empty TSV makes every path look free, which is the bias we came here to kill.&lt;/p&gt;

&lt;h2&gt;
  
  
  The only question I want back
&lt;/h2&gt;

&lt;p&gt;Would a drop in &lt;code&gt;M&lt;/code&gt; from 12 to 4, with &lt;code&gt;R&lt;/code&gt; unchanged, keep you on hosted free model access? Or does custody already force the exit, so the minutes are a footnote?&lt;/p&gt;

&lt;p&gt;If you are actually choosing, check the current MonkeyCode terms for free model access and the free server option, confirm the license yourself, log one week of discards, and put your own &lt;code&gt;N&lt;/code&gt;, &lt;code&gt;R&lt;/code&gt;, &lt;code&gt;M&lt;/code&gt;, &lt;code&gt;P&lt;/code&gt;, and &lt;code&gt;S&lt;/code&gt; into the gate. Then say which input flipped the call. I will trust that over a sticker.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>devops</category>
      <category>programming</category>
    </item>
    <item>
      <title>Should Your EM Stay on a Free Coding Lane After the Pilot? Use This Term-Drift Sheet</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Sun, 11 Oct 2026 19:57:42 +0000</pubDate>
      <link>https://dev.to/bestbee/should-your-em-stay-on-a-free-coding-lane-after-the-pilot-use-this-term-drift-sheet-2lf3</link>
      <guid>https://dev.to/bestbee/should-your-em-stay-on-a-free-coding-lane-after-the-pilot-use-this-term-drift-sheet-2lf3</guid>
      <description>&lt;p&gt;Picture a Thursday standup. Six engineers. One engineering manager. Three sticky notes on the board: free lane, paid seats, self-host.&lt;/p&gt;

&lt;p&gt;Nobody is fighting about which demo felt smart. They are fighting about a clock. The pilot felt cheap. The next planning window is ninety days. If the free terms move, who pays the exit?&lt;/p&gt;

&lt;p&gt;I use that scene as a composite, not a named customer. I keep the same argument when I write the stay-or-leave call down. So which sticky note still matters if the sticker you liked last month is gone?&lt;/p&gt;

&lt;h2&gt;
  
  
  The call that can reverse
&lt;/h2&gt;

&lt;p&gt;I am not asking whether AI coding "works." That question is too wide, and it lets everyone win the meeting.&lt;/p&gt;

&lt;p&gt;I am asking something an engineering manager can actually own. Should this cohort stay on a free coding lane, buy a paid hosted lane, or self-host, once you price term drift?&lt;/p&gt;

&lt;p&gt;Term drift is just this: quota, model set, server option, or data terms can change inside your planning window. You do not need a rumor to model it. You need a weight you will defend, a person who owns the row, and a date when the exception dies.&lt;/p&gt;

&lt;p&gt;A scorecard is a conversation tool. It is not objective truth. If finance hates one input, change it and rerun. Why else keep a sheet?&lt;/p&gt;

&lt;h2&gt;
  
  
  What I will treat as fact
&lt;/h2&gt;

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

&lt;p&gt;The operator describes MonkeyCode as an open-source project with free model access and a free server option. Those two availability claims are the only product facts I will put in column one.&lt;/p&gt;

&lt;p&gt;I am not naming models. I am not stating a token quota, a box size, an uptime number, or a duration. A round figure on a slide, including any "millions of tokens" sticker, stays out until someone opens the live terms and writes today's date beside it.&lt;/p&gt;

&lt;p&gt;I drafted this on 2026-10-12. If you read it later, re-check the repo and the terms before you reuse my blanks. Would you want a planning sheet that froze a quota I cannot cite from this desk?&lt;/p&gt;

&lt;h2&gt;
  
  
  Name the inputs before the debate
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The numbers that enter the fight
&lt;/h3&gt;

&lt;p&gt;Fill these from your logs and your own quotes. Do not borrow mine past the example, and delete the example when you are done.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;N&lt;/code&gt; — engineers in the cohort. Useful context. Not the price.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Rw&lt;/code&gt; — hours per month on a second human pass you can tie to lane output. Not all review. Only rework you would skip if the lane were absent.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;C&lt;/code&gt; — fully loaded hourly cost your finance partner already uses. A local number. Not a market average.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;I&lt;/code&gt; — monthly invoice for the paid hosted alternative, same cohort, quote dated this week.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;M&lt;/code&gt; — monthly self-host cost: people slice plus infra you would actually pay. Include on-call. Leave sunk laptops out.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;E&lt;/code&gt; — engineer-hours to leave the free lane. IDE config, CI remote, prompt files, and the habit of pasting into one box.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;W&lt;/code&gt; — planning window in months. Start at 3 unless your cycle is shorter.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;p&lt;/code&gt; — a planning weight from 0 to 1 for terms, or the free server option, moving inside &lt;code&gt;W&lt;/code&gt;. Your risk appetite. Not a vendor forecast.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;N&lt;/code&gt; does not enter the formula. I keep it so nobody proves the cost with headcount and walks out early. Seen that move before? I bet you have.&lt;/p&gt;

&lt;h3&gt;
  
  
  The three monthly costs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Free: &lt;code&gt;F = Rw * C + (p * E * C) / W&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Paid: &lt;code&gt;P = I + (p_paid * E_paid * C) / W&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Host: &lt;code&gt;H = M&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay on the free lane only if &lt;code&gt;F&lt;/code&gt; is lowest and every hard gate is still true. Otherwise buy or host. A low &lt;code&gt;F&lt;/code&gt; never overrides a failed gate. Got that?&lt;/p&gt;

&lt;p&gt;Paid can win on a higher sticker if exit load and rework make free worse. Self-host can win while looking expensive, if custody fails for both hosted paths. The unit is planning dollars per month, not a token sticker and not a seat count.&lt;/p&gt;

&lt;h2&gt;
  
  
  A filled example you should throw away
&lt;/h2&gt;

&lt;p&gt;These numbers are a worksheet. I did not run them on a production org. They are not a product benchmark. Replace each one.&lt;/p&gt;

&lt;p&gt;Suppose &lt;code&gt;N = 6&lt;/code&gt;. Over 14 days the team labeled 9 pull requests &lt;code&gt;lane-rework&lt;/code&gt;. Each second pass took about 25 minutes. That is &lt;code&gt;9 * 25 / 60 = 3.75&lt;/code&gt; hours in two weeks, about 8 hours in a month. Set &lt;code&gt;Rw = 8&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finance says &lt;code&gt;C = 110&lt;/code&gt;. Friction is &lt;code&gt;8 * 110 = 880&lt;/code&gt; dollars a month. Small. Maybe too small. We will poke it in a minute.&lt;/p&gt;

&lt;p&gt;A paid quote pasted into the doc this week says &lt;code&gt;I = 1800&lt;/code&gt;. You think a contracted lane needs less exit work, so you set &lt;code&gt;E_paid = 6&lt;/code&gt; and &lt;code&gt;p_paid = 0.2&lt;/code&gt;. Self-host is a quarter of a platform engineer plus a small box. You wrote &lt;code&gt;M = 4600&lt;/code&gt;. Leaving the free lane looks like &lt;code&gt;E = 16&lt;/code&gt; hours. You set &lt;code&gt;W = 3&lt;/code&gt; and &lt;code&gt;p = 0.5&lt;/code&gt;, because you will not bet a release train on an uncontracted server option.&lt;/p&gt;

&lt;p&gt;Then the arithmetic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free exit load: &lt;code&gt;(0.5 * 16 * 110) / 3 ≈ 293&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;F ≈ 880 + 293 = 1173&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Paid exit load: &lt;code&gt;(0.2 * 6 * 110) / 3 ≈ 44&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;P ≈ 1844&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;H = 4600&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On this sheet, free wins the cost line. Does the team stay? Only if the gates pass. A cheap lane that cannot hold secrets, or that nobody can leave, is not cheap. It is an unowned outage with a friendly price.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three flips I want said out loud
&lt;/h2&gt;

&lt;p&gt;Which single input, moved by a believable amount, reverses the call? If you cannot answer, you do not understand your own sheet.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rework. If &lt;code&gt;Rw&lt;/code&gt; rises from 8 to 22, friction becomes &lt;code&gt;2420&lt;/code&gt;. Free planning cost becomes about &lt;code&gt;2713&lt;/code&gt;, above paid. Buy wins on cost. I would not wait for a prettier demo to notice that. The label log would have screamed first.&lt;/li&gt;
&lt;li&gt;Term weight. If &lt;code&gt;p&lt;/code&gt; goes from 0.5 to 1.0, free exit load doubles to about &lt;code&gt;587&lt;/code&gt;. &lt;code&gt;F&lt;/code&gt; becomes about &lt;code&gt;1467&lt;/code&gt;. Still under paid in this example. So term fear alone does not flip this particular sheet. Rework does. That tells the EM to instrument labels, not to collect hallway rumors.&lt;/li&gt;
&lt;li&gt;Custody. If any repo in the cohort is secret-adjacent, and you have not read this week's data terms for the free lane and the free server option, both hosted paths fail the gate. Self-host wins even at &lt;code&gt;4600&lt;/code&gt;. Cost is no longer the argument. Stop quoting it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The sheet is allowed to say stay. It is also allowed to embarrass the stay. Which outcome are you hoping gets buried in the appendix?&lt;/p&gt;

&lt;h2&gt;
  
  
  Hard gates, one owner, one expiry
&lt;/h2&gt;

&lt;p&gt;I will not let a low &lt;code&gt;F&lt;/code&gt; override these.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Data terms for the free model lane and the free server option were read by a named person in the last 7 days. Link the page. Write the date. A memory from onboarding does not count.&lt;/li&gt;
&lt;li&gt;No production secret, customer payload, or unreleased vulnerability note goes through a lane whose retention you cannot describe in one sentence.&lt;/li&gt;
&lt;li&gt;The free server option is not the only remote for a release-train job. A second path exists, even if it is slower and annoying.&lt;/li&gt;
&lt;li&gt;One owner. Not a chat channel. A person who can pause the lane on a weekday without a committee.&lt;/li&gt;
&lt;li&gt;Expiry. The exception dies on a calendar date inside &lt;code&gt;W&lt;/code&gt;. Use 30 days, then a rerun. No silent renew.&lt;/li&gt;
&lt;li&gt;Exit drill. The owner has run the leave-steps once on a scratch repo. If they have not, &lt;code&gt;E&lt;/code&gt; is a fantasy. You may not use it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Who owns the row? The engineering manager owns the decision. A platform lead owns the exit drill. Finance owns &lt;code&gt;C&lt;/code&gt; and &lt;code&gt;I&lt;/code&gt;. If those three names are blank, you do not have a decision. You have a vibe with arithmetic on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  Log the rework, then run the math
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The label, before the feelings
&lt;/h3&gt;

&lt;p&gt;Agree on &lt;code&gt;lane-rework&lt;/code&gt; before the two-week log. A pull request gets the label only when someone redid work because the lane's output was wrong for this repo. Spec changes do not count. Taste arguments without a redo do not count. Be strict, or &lt;code&gt;Rw&lt;/code&gt; becomes a junk drawer.&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 commands. They do nothing until the label exists in your repo.&lt;/span&gt;
&lt;span class="c"&gt;# Window start is 14 days before the draft date, 2026-10-12.&lt;/span&gt;
gh &lt;span class="nb"&gt;pr &lt;/span&gt;list &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--search&lt;/span&gt; &lt;span class="s2"&gt;"label:lane-rework updated:&amp;gt;=2026-09-28"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--state&lt;/span&gt; all &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--limit&lt;/span&gt; 200 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--json&lt;/span&gt; number,title,updatedAt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/lane-rework.json

jq &lt;span class="s1"&gt;'length'&lt;/span&gt; /tmp/lane-rework.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put minutes in the PR body as a trailer line: &lt;code&gt;rework-min: 25&lt;/code&gt;. Crude. Still better than a memory from standup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;list &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--search&lt;/span&gt; &lt;span class="s2"&gt;"label:lane-rework updated:&amp;gt;=2026-09-28"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--state&lt;/span&gt; all &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--limit&lt;/span&gt; 200 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--json&lt;/span&gt; number,body &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/lane-rework.json

python3 - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;PY&lt;/span&gt;&lt;span class="sh"&gt;'
import json, re
rows = json.load(open('/tmp/lane-rework.json'))
mins = []
for row in rows:
    found = re.search(r'rework-min:&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sh"&gt;*(&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sh"&gt;+)', row.get('body') or '')
    if found:
        mins.append(int(found.group(1)))
print('prs', len(rows))
print('with_minutes', len(mins))
print('hours', round(sum(mins) / 60, 2))
&lt;/span&gt;&lt;span class="no"&gt;PY
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Double the two-week hours if you want a rough month. Do not pretend that extrapolation is a forecast. It is a stand-in until you have four weeks. If the two weeks included a holiday, say so in the notes. Why hide the weird week?&lt;/p&gt;

&lt;h3&gt;
  
  
  The calculator
&lt;/h3&gt;

&lt;p&gt;This script is a proposal. I have not executed it against a real organization, and it does not call a vendor API. It will not tell you that a product is safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;Term-drift sheet. Replace every number. Not a benchmark.&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&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="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;free&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;W must be &amp;gt; 0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;exit_load&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&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;mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;free&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rw&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;exit_load&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;exit_load&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;unknown mode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;110.0&lt;/span&gt;
    &lt;span class="n"&gt;free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;16.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;free&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;paid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&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;e&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3.0&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="mf"&gt;1800.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;4600.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;costs&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;free&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paid&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&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="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;costs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;costs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&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="n"&gt;costs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cost_winner&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;winner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gates_still_required&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&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;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 term_drift.py
&lt;span class="c"&gt;# Edit rw from 8 to 22 and run again. Did the winner move?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The flip point is the only number I want on the whiteboard. Everything else is scaffolding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should not use this
&lt;/h2&gt;

&lt;p&gt;Skip the sheet if you cannot label rework for two weeks. A blank &lt;code&gt;Rw&lt;/code&gt; makes free look free. That is how a zero becomes a strategy.&lt;/p&gt;

&lt;p&gt;Skip it if the cohort handles regulated data and nobody has read the current terms. Do not pilot first and ask legal later. Later is how an unreviewed server option becomes a finding.&lt;/p&gt;

&lt;p&gt;Skip it if you wanted a model bake-off. This does not score answer quality. It scores whether a cheap lane still fits after drift, rework, and exit. A green toy prompt will not save the meeting.&lt;/p&gt;

&lt;p&gt;Skip it if you need a procurement signature tonight. The sheet is not a contract review, a security assessment, or a capacity test of anyone's free server.&lt;/p&gt;

&lt;p&gt;Skip it if the owner will not put an expiry on the calendar. An exception without a death date becomes the architecture. You do not need a brand name on that pattern to recognize it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits I want in the notes
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;p&lt;/code&gt; is not a probability I measured. It is a weight. Write that next to the cell, or a later reader will quote it as science.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;E&lt;/code&gt; is usually too low the first time. People forget prompt files, CI secrets, and the junior who only knows one remote. Add a second pass after the scratch-repo drill, then trust the number.&lt;/p&gt;

&lt;p&gt;The paid quote goes stale. Date it. A quote older than &lt;code&gt;W&lt;/code&gt; does not count, even if the PDF still looks official.&lt;/p&gt;

&lt;p&gt;Self-host &lt;code&gt;M&lt;/code&gt; hides on-call until the first weekend page. If your platform team is already saturated, add a delay cost or stop pretending &lt;code&gt;M&lt;/code&gt; is complete.&lt;/p&gt;

&lt;p&gt;I also did not compare features, latency, or model quality. I cannot, not from this desk, and I will not invent a leaderboard to decorate the post. If quality is the real fight, review your own repos. Then come back and put the rework hours here.&lt;/p&gt;

&lt;p&gt;Open-source does not, by itself, answer custody or exit. A repo you can read is not the same as a server option you can leave on a Tuesday. Treat those as separate rows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where column one can come from
&lt;/h2&gt;

&lt;p&gt;If a free model lane and a free server option are the hosted pair you want in the free column, read MonkeyCode's current repository and terms, write the date on the sheet, and only then drop in numbers you can defend. I would rather you delete my example than inherit it.&lt;/p&gt;

&lt;p&gt;So which input flips your call: rework hours, the term weight, or a custody gate you have been skipping?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>Your Green Toy Eval Cannot Pick the Lane. Use This Review-Debt Gate</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Sat, 10 Oct 2026 16:03:03 +0000</pubDate>
      <link>https://dev.to/bestbee/your-green-toy-eval-cannot-pick-the-lane-use-this-review-debt-gate-49ee</link>
      <guid>https://dev.to/bestbee/your-green-toy-eval-cannot-pick-the-lane-use-this-review-debt-gate-49ee</guid>
      <description>&lt;p&gt;Here is the meeting I reconstruct when a platform lead says the demo already decided the vendor.&lt;/p&gt;

&lt;p&gt;An engineering manager has a free coding lane. It drafts a small internal page. A toy eval written before lunch comes back green. Someone asks the question that sounds frugal and is actually reckless. If this lane is clean, why are we still pricing a paid seat or a box in our own network?&lt;/p&gt;

&lt;p&gt;I would ask a different question. What did that eval refuse to look at?&lt;/p&gt;

&lt;p&gt;The quiet usually answers it. Happy-path JSON passed. Auth did not run. Migration order did not run. The files that page on-call never opened. A green toy eval is a mood. It is not a lane decision.&lt;/p&gt;

&lt;p&gt;That is the tradeoff that can reverse the call. Not market excitement. Not a token sticker. Review debt, custody, and the week the free option changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Name the choice before you name a product
&lt;/h2&gt;

&lt;p&gt;Three options sit on the table. Keep generating on free model access plus a free server. Move the same workflow to a paid hosted lane. Or self-host.&lt;/p&gt;

&lt;p&gt;Which one survives the next month of real diffs? If you cannot say what would flip you, you are not deciding. You are shopping.&lt;/p&gt;

&lt;p&gt;I am using MonkeyCode as the free-lane column in this comparison. Disclosure: This article was prepared as part of MonkeyCode's product outreach. The outreach describes free model access and a free server option, and it positions the project as open source.&lt;/p&gt;

&lt;p&gt;I have not verified the license, the repo contents, quotas, model names, hardware, uptime, or how long either offer lasts. If a chat brief waved a round token figure at you, do not paste it into a budget. Copy the live number, and the date you read it, from the project page. A sticker is not capacity you own.&lt;/p&gt;

&lt;p&gt;If the page and this article disagree, the page wins. Open source is not a support plan. Read the license before you fork, and confirm what "open" does not include.&lt;/p&gt;

&lt;h2&gt;
  
  
  The unit I will actually price
&lt;/h2&gt;

&lt;p&gt;I will not price this on seats. I will not price it on a token pool. I will not price it on one green run.&lt;/p&gt;

&lt;p&gt;I price reviewer-minutes on defects a human still has to catch. Call that review debt. If the lane saves drafting time and then spends it back in review, you do not have free capacity. You have a queue with a costume.&lt;/p&gt;

&lt;p&gt;Does your toy eval even see the files your reviewer rewrites? If it does not, your escape rate is a guess wearing a checkmark.&lt;/p&gt;

&lt;h3&gt;
  
  
  Variables, defined before the argument
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;D&lt;/code&gt; — drafts per week a human must review. Diffs, not chat turns.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;M&lt;/code&gt; — reviewer minutes per draft, including rewrites. Time it. Do not recall it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;E&lt;/code&gt; — escape rate. Share of drafts where review finds a defect the toy eval missed. From 0 to 1.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;C&lt;/code&gt; — loaded cost of one reviewer minute, in your currency.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;S&lt;/code&gt; — drafting minutes the lane actually saves per draft, on your work.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;K&lt;/code&gt; — extra minutes per draft if you self-host. Patching, babysitting, key rotation. Measured, or marked unknown.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;P&lt;/code&gt; — paid hosted cost per draft, fully loaded. Seats spread across &lt;code&gt;D&lt;/code&gt;, plus overage you have already seen.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; — custody block. &lt;code&gt;1&lt;/code&gt; if the diff may not leave your boundary. &lt;code&gt;0&lt;/code&gt; if it may.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Weekly review debt is &lt;code&gt;RD = D * M * E * C&lt;/code&gt;. Weekly drafting value is &lt;code&gt;DV = D * S * C&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Free-lane net, ignoring the chance the offer vanishes, is &lt;code&gt;NF = DV - RD&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Paid net uses its own escape rate, not a hoped-for one: &lt;code&gt;NP = D * S * C - D * M * E_paid * C - D * P&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Self-host net is &lt;code&gt;NS = D * S * C - D * M * E_self * C - D * K * C&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You do not get to assume &lt;code&gt;E&lt;/code&gt; falls because you paid, or because you rented a box. If you have not sampled those lanes, set &lt;code&gt;E_paid&lt;/code&gt; and &lt;code&gt;E_self&lt;/code&gt; equal to &lt;code&gt;E&lt;/code&gt;. Then paid and self-host must win on custody, support, or continuity. Not on a fantasy quality jump.&lt;/p&gt;

&lt;h2&gt;
  
  
  A filled sheet that is not a customer
&lt;/h2&gt;

&lt;p&gt;These numbers are hypothetical. I made them up so the arithmetic is visible. They are not a benchmark. They are not MonkeyCode results. They are not your team.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;D = 30&lt;/code&gt;. &lt;code&gt;M = 18&lt;/code&gt;. &lt;code&gt;E = 0.25&lt;/code&gt;. &lt;code&gt;C = 1.4&lt;/code&gt;. &lt;code&gt;S = 12&lt;/code&gt;. &lt;code&gt;P = 6&lt;/code&gt;. &lt;code&gt;K = 8&lt;/code&gt;. &lt;code&gt;B = 0&lt;/code&gt; only while the sample stays off customer data.&lt;/p&gt;

&lt;p&gt;Free lane: &lt;code&gt;RD = 30 * 18 * 0.25 * 1.4 = 189&lt;/code&gt;. &lt;code&gt;DV = 30 * 12 * 1.4 = 504&lt;/code&gt;. &lt;code&gt;NF = 315&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Paid, same escape rate: &lt;code&gt;NP = 504 - 189 - 180 = 135&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Self-host, same escape rate: &lt;code&gt;NS = 504 - 189 - 336 = -21&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On this invented board, the free lane wins the week, and self-host loses. Thin win. Do not laminate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sensitivity, the part that should make you nervous
&lt;/h3&gt;

&lt;p&gt;Move only &lt;code&gt;E&lt;/code&gt; on the free lane to &lt;code&gt;0.55&lt;/code&gt;. That is what I expect when the eval never opened auth or migrations.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RD = 30 * 18 * 0.55 * 1.4 = 415.8&lt;/code&gt;. &lt;code&gt;NF = 88.2&lt;/code&gt;. Still positive. Barely.&lt;/p&gt;

&lt;p&gt;Now the reviewer is rewriting, so &lt;code&gt;S&lt;/code&gt; drops to &lt;code&gt;6&lt;/code&gt;. &lt;code&gt;DV = 252&lt;/code&gt;. &lt;code&gt;NF = 252 - 415.8 = -163.8&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The free lane just went negative. No sticker caused that. Reviewer minutes did. Would your lead still call it free?&lt;/p&gt;

&lt;p&gt;Flip &lt;code&gt;B&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; and stop. A pretty &lt;code&gt;NF&lt;/code&gt; does not outrank a custody rule. Free model access that sends code off-boundary is a no, even when the weekly math looks kind.&lt;/p&gt;

&lt;p&gt;What about the week the free server changes? I will not invent an uptime number to decorate this. Price a stuck week as &lt;code&gt;D * M * C&lt;/code&gt; of drafts with nowhere to land, and ask if you can absorb it. If you cannot, the free column was never a default. It was a pilot with a calendar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hard gates I will not let you average away
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Custody. &lt;code&gt;B = 1&lt;/code&gt; means the free hosted lane is out. Compare a contracted paid lane with self-host. Read the contract. Do not guess the data terms.&lt;/li&gt;
&lt;li&gt;Owner. One named person. Not a channel reaction.&lt;/li&gt;
&lt;li&gt;Expiry. This sheet dies in 14 days, or on the day the project page changes the free terms. Whichever comes first.&lt;/li&gt;
&lt;li&gt;Toy-eval scope. If the eval skips one failure path from last month's incident review, it cannot justify "stay."&lt;/li&gt;
&lt;li&gt;Exit. Leave the free lane when &lt;code&gt;NF&lt;/code&gt; is negative on two weekly samples, or when one escaped defect touches a paging path.&lt;/li&gt;
&lt;li&gt;No silent default. The free lane is not the only editor for new hires until the owner re-signs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A scorecard is a conversation tool. It is not objective truth. If two leads disagree on &lt;code&gt;E&lt;/code&gt;, argue about the sample. Do not argue about the logo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Questions I ask out loud
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Who gets paged if this diff is wrong?&lt;/li&gt;
&lt;li&gt;Which file did the toy eval never open?&lt;/li&gt;
&lt;li&gt;If the free server is gone on Thursday, where do these drafts land?&lt;/li&gt;
&lt;li&gt;Are you about to treat a smooth surface as a reviewed change?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the room cannot answer, you do not have a pilot. You have a demo that escaped.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fit, in one glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Free model access + free server&lt;/th&gt;
&lt;th&gt;Paid hosted&lt;/th&gt;
&lt;th&gt;Self-host&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;When it fits&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;B = 0&lt;/code&gt;, &lt;code&gt;NF &amp;gt; 0&lt;/code&gt;, owner named, expiry written&lt;/td&gt;
&lt;td&gt;You need support or terms you can cite&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;B = 1&lt;/code&gt;, or you already run the stack and &lt;code&gt;K&lt;/code&gt; is measured&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;When it fails&lt;/td&gt;
&lt;td&gt;Terms can move and you have no exit week&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;D * P&lt;/code&gt; eats the review-debt gap&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;K&lt;/code&gt; is a guess you are treating as a fact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What you owe&lt;/td&gt;
&lt;td&gt;A 10-draft sample and a boundary check&lt;/td&gt;
&lt;td&gt;A premium you have seen, not a list price you liked&lt;/td&gt;
&lt;td&gt;Patch owner, key owner, and a rollback path&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This gate also ignores prompt retention, output license, and whatever counsel already forbade. If legal has a written no, the spreadsheet does not get a vote.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the arithmetic before the meeting
&lt;/h2&gt;

&lt;p&gt;This script is a proposal. I have not executed it against a live product. Change every input. If you paste my hypotheticals into a slide, you are the problem.&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;# review_debt_gate.py
# Proposal only. Hypothetical inputs. Not a benchmark.
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;weekly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;review_debt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
    &lt;span class="n"&gt;draft_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;review_debt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;draft_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;draft_value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;review_debt&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;extra&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;
    &lt;span class="n"&gt;e_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e_paid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e_self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;
    &lt;span class="n"&gt;paid_premium&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self_host_minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;8.0&lt;/span&gt;
    &lt;span class="n"&gt;custody_block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="n"&gt;rows&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;free&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;weekly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e_free&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;weekly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e_paid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;paid_premium&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;self_host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;weekly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e_self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;self_host_minutes&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&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="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;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: debt=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rd&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; value=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dv&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; net=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&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;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;custody_block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GATE: free hosted is blocked. Compare paid vs self-host only.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="n"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Arithmetic pick: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;winner&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. Re-check gates before you tell the squad.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 review_debt_gate.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then break the free lane on purpose. This is the sensitivity I want on a whiteboard, not in a keynote.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;PY&lt;/span&gt;&lt;span class="sh"&gt;'
d, m, c, s = 30, 18, 1.4, 12
for step in range(1, 8):
    e = step / 10
    net = d * s * c - d * m * e * c
    print(f'E={e:.1f} free_net={net:.1f}')
&lt;/span&gt;&lt;span class="no"&gt;PY
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;free_net&lt;/code&gt; crosses zero, stop debating vendors. Pull ten real diffs. A half hour of notes beats another slide.&lt;/p&gt;

&lt;p&gt;Record the decision so it can expire:&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;date&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; +%F &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; lane-decision-date.txt
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'owner=%s\nexpiry_days=14\ncustody_block=%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OWNER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$B&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; lane-decision-date.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sample ten drafts, skip the pretty one
&lt;/h2&gt;

&lt;p&gt;For each draft, four lines. Did a human touch auth, data, or migrations? Minutes spent, rewrite included. Would the toy eval have failed it? Could the diff have left the boundary?&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;# drafts.tsv columns: minutes, escaped(0/1), boundary(0/1)&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;'\t'&lt;/span&gt; &lt;span class="s1"&gt;'NR&amp;gt;1 {n++; mins+=$1; esc+=$2; b+=$3} END {
  printf "n=%d avg_min=%.1f escape=%.2f boundary_share=%.2f\n", n, mins/n, esc/n, b/n
}'&lt;/span&gt; drafts.tsv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is an average, not a median. I know. It is still enough to stop a meeting that wants to standardize a demo. If &lt;code&gt;boundary_share&lt;/code&gt; is not zero, the free hosted option is already on probation.&lt;/p&gt;

&lt;p&gt;Who should not use this gate? A solo maintainer with no reviewer. The formula assumes a human queue. A team that already has one contracted lane and no appetite for a second path. Anyone who wants a blessing for a number they have not timed. And anyone about to point a free server at production CI.&lt;/p&gt;

&lt;p&gt;A free server option is a pilot host, not your build farm, until you have an exit you have rehearsed. Would you bet a Thursday incident on a host you do not control? Then it is not the default.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I am not claiming
&lt;/h2&gt;

&lt;p&gt;I am not claiming MonkeyCode is faster, cheaper in outcome, or more accurate than a paid lane or a self-hosted stack. I did not run that test. I am not naming models, because I will not invent them. I am not locking a token allowance into this article, because an allowance I have not re-read today is already stale.&lt;/p&gt;

&lt;p&gt;Use the free column when the work is non-production, the boundary check is clean, you have an owner, and you have an expiry. That is a sane way to learn whether drafting time is real before you buy seats or stand up hardware.&lt;/p&gt;

&lt;p&gt;Do not use it for customer data, paging paths, or a hiring exercise you will later pretend was production code. A surface that looks finished is how review debt hides. Your on-call does not grade the demo. It grades the diff.&lt;/p&gt;

&lt;p&gt;Which input flips your call: escape rate, reviewer minutes, or the custody bit? If none of them move, you are shopping. Date the sheet, name the owner, and throw it out when it expires. If you try a free model lane or a free server before that date, copy the live terms that morning instead of trusting this page, and keep the lane off paging paths until the second weekly sample.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Should Your Platform Lead Trust a $0 Coding Lane? Use This Page-Owner Gate</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Fri, 09 Oct 2026 11:29:07 +0000</pubDate>
      <link>https://dev.to/bestbee/should-your-platform-lead-trust-a-0-coding-lane-use-this-page-owner-gate-30k4</link>
      <guid>https://dev.to/bestbee/should-your-platform-lead-trust-a-0-coding-lane-use-this-page-owner-gate-30k4</guid>
      <description>&lt;p&gt;I use a composite scene for this call, because the real company names are not mine to publish. The invoice says $0. The pilot is fourteen days old. A generated pull request touches a billing path at 23:10, and the on-call column for agent mistakes is blank.&lt;/p&gt;

&lt;p&gt;Would you keep that lane because the vendor bill was quiet?&lt;/p&gt;

&lt;p&gt;I would not. Not while the page owner is an empty cell. A free hosted lane can still be the right four-week probe. It is a bad default the morning you need a human.&lt;/p&gt;

&lt;p&gt;Every figure below is a placeholder you replace. This scorecard is a conversation tool, not objective truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The unit that can flip the decision
&lt;/h2&gt;

&lt;p&gt;Token stickers and seat counts will not save you in that 23:10 review. I have priced other units in other write-ups. This one is the pager.&lt;/p&gt;

&lt;p&gt;Who gets the page when the agent is wrong, and what does that hour cost? If you cannot name the person, you do not have a pilot. You have a login and a hope.&lt;/p&gt;

&lt;p&gt;Three columns usually show up on the same slide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A free hosted lane, sometimes with free model access and a free server option.&lt;/li&gt;
&lt;li&gt;Self-hosting an agent you are actually allowed to run, patch, and shut down.&lt;/li&gt;
&lt;li&gt;A paid lane with a contract, a support path, and a renewal date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cash is one row. Page ownership is the row that changes a founder's mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the free column in its place
&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 belongs in this worksheet as a free-column candidate: free model access, plus a free server option, as supplied for this draft. I am not stating a model name, a token quota, a hardware shape, a duration, or an uptime number. Those were not attached as dated primary facts, and a decision guide should not invent them. Read the live terms on the day you decide. A post is not your contract.&lt;/p&gt;

&lt;p&gt;Does that make the free column useless? No. It makes it a probe with an owner, not a permanent architecture.&lt;/p&gt;

&lt;p&gt;I would use a free hosted lane only when all four lines are true:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The repos in scope have no customer data, secrets, or production credentials.&lt;/li&gt;
&lt;li&gt;A human already owns review, and that human knows they own the page.&lt;/li&gt;
&lt;li&gt;You can exit in weeks. "After the next planning cycle" is not an exit.&lt;/li&gt;
&lt;li&gt;You are testing workflow fit, not crowning a model.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Miss one line, and self-host or paid can be the honest column even when the invoice looks worse. If the project is described as open source, that still does not fill the self-host column for you. Read the license. Name the person who will patch it. A free server does not answer either question.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Page-Owner Gate
&lt;/h2&gt;

&lt;p&gt;Define the variables before anyone says "AI ROI."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;E&lt;/code&gt; — bad changes per week that need a page, a rollback, or a revert. You measure this. Do not borrow mine.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;H&lt;/code&gt; — reviewer or on-call hours per bad change.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;R&lt;/code&gt; — loaded hourly cost of the person who owns the page.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;W&lt;/code&gt; — decision window in weeks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cash&lt;/code&gt; — invoice plus unavoidable ops cash for that window.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Boundary&lt;/code&gt; — security or legal hours, priced once, if code or prompts cross a boundary you care about.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Page cost is &lt;code&gt;E * H * R * W&lt;/code&gt;. Option total is &lt;code&gt;Cash + page cost + Boundary&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This script is a local worksheet. It does not call a vendor, and it cannot apply a data gate. Label it as a proposal, then replace every input.&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;# page_owner_gate.py
# Illustrative inputs only. Not a measured result for any product.
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;option_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weeks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;hours&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;weeks&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cash&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;boundary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;break_even_events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weeks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;free_boundary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other_total&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;page_per_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hours&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;weeks&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other_total&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;free_boundary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;page_per_event&lt;/span&gt;

&lt;span class="n"&gt;weeks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="n"&gt;hours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;
&lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;120.0&lt;/span&gt;

&lt;span class="c1"&gt;# Placeholders for a conversation, not quotes.
&lt;/span&gt;&lt;span class="n"&gt;options&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;free_hosted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;events&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;boundary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;self_host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;events&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;boundary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid_lane&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;events&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;boundary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;scored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;options&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;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;option_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;events&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weeks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;boundary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;scored&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total&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;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: total=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; page=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&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;span class="n"&gt;be&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;break_even_events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weeks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scored&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paid_lane&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;free_vs_paid break-even E=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; bad changes/week&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;Run it locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 page_owner_gate.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On these placeholders the sheet looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Cash&lt;/th&gt;
&lt;th&gt;E / week&lt;/th&gt;
&lt;th&gt;Boundary&lt;/th&gt;
&lt;th&gt;Page cost&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free hosted&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;td&gt;900&lt;/td&gt;
&lt;td&gt;1,440&lt;/td&gt;
&lt;td&gt;2,340&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-host&lt;/td&gt;
&lt;td&gt;2,400&lt;/td&gt;
&lt;td&gt;1.2&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;1,152&lt;/td&gt;
&lt;td&gt;3,852&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paid lane&lt;/td&gt;
&lt;td&gt;1,600&lt;/td&gt;
&lt;td&gt;0.8&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;td&gt;2,568&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Arithmetic likes the free column. So what? Arithmetic does not own the pager.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sensitivity, because E is the number people sand down
&lt;/h3&gt;

&lt;p&gt;Hold &lt;code&gt;H&lt;/code&gt;, &lt;code&gt;R&lt;/code&gt;, and &lt;code&gt;W&lt;/code&gt; fixed. Free total is &lt;code&gt;960 * E + 900&lt;/code&gt;. Paid total on this sheet is &lt;code&gt;2,568&lt;/code&gt;. Set them equal and &lt;code&gt;E&lt;/code&gt; is about &lt;code&gt;1.74&lt;/code&gt; bad changes per week. The script prints that break-even. Do not trust my sentence if your run disagrees.&lt;/p&gt;

&lt;p&gt;Cross &lt;code&gt;1.74&lt;/code&gt; and the free column loses on cost alone, before any data rule. Drop free-lane &lt;code&gt;E&lt;/code&gt; to &lt;code&gt;0.4&lt;/code&gt; and page cost falls to &lt;code&gt;$384&lt;/code&gt;. Then the free column wins by a wide gap. It wins only if the hard gates also pass.&lt;/p&gt;

&lt;p&gt;Self-host loses this particular sheet because I priced operator time instead of hiding it in "someone will maintain it." Will they? If your real self-host cash is &lt;code&gt;$400&lt;/code&gt;, rerun the script. Do not argue with a cell you refused to fill.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gates that override the cheap winner
&lt;/h3&gt;

&lt;p&gt;Print the low total. Then apply the gates. A failed gate means stop, even when the spreadsheet smiles.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Data boundary.&lt;/strong&gt; Customer data, secrets, or production credentials on a free hosted lane need a written exception. No exception, no invite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Named page owner.&lt;/strong&gt; One person, not a channel. If the name is "the team," you failed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit date.&lt;/strong&gt; A date on a calendar. "When we see value" is not a date.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measured E.&lt;/strong&gt; If week one has no count of bad changes, you are collecting anecdotes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operate rights, for self-host.&lt;/strong&gt; If you cannot confirm you may run, patch, and shut the agent down, it does not belong in that column. A free server option is not a cluster you control.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Log the call without secrets or customer identifiers:&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;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\t%s\t%s\t%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;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; +%Y-%m-%d&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"free_hosted"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"HOLD"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"page-owner=alex; exit=2026-11-06; gate=data-ok"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; page-owner-log.tsv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The platform lead owns the card. A named engineer or EM owns the page. Security owns the data exception, and that exception expires. In this example the window ends on 2026-11-06. Then you re-score, or you archive the lane.&lt;/p&gt;

&lt;p&gt;Any one of these is an exit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Measured &lt;code&gt;E&lt;/code&gt; crosses your break-even against the next-best column.&lt;/li&gt;
&lt;li&gt;The page owner misses a revert window you wrote down in advance.&lt;/li&gt;
&lt;li&gt;The data exception expires.&lt;/li&gt;
&lt;li&gt;The terms you actually read no longer match the boundary you approved.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Four weeks, then a real choice
&lt;/h2&gt;

&lt;p&gt;Week 0 is the gate, not the install party. I would block the invite until the log line exists. No owner, no date, no pilot.&lt;/p&gt;

&lt;p&gt;Week 1, count bad changes. A revert is only a floor. Review rejects never hit &lt;code&gt;main&lt;/code&gt;, so git will undercount. Still, write the floor down where finance can see 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;&lt;span class="c"&gt;# Floor for E, not the definition. Caught-in-review misses are invisible here.&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="s1"&gt;'7 days ago'&lt;/span&gt; &lt;span class="nt"&gt;--grep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Revert'&lt;/span&gt; &lt;span class="nt"&gt;--oneline&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Week 2, ask the page owner one question. If this lane vanished on Friday, what breaks? "Nothing we cannot do by hand" means you still have an exit. "The team's whole flow" means you standardized by accident. That is how a free lane becomes unowned infrastructure.&lt;/p&gt;

&lt;p&gt;Week 4, rerun the script with measured &lt;code&gt;E&lt;/code&gt;. Keep, move to a lane you operate, or buy. Do not extend a HOLD because the invoice is still zero.&lt;/p&gt;

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

&lt;p&gt;Skip it if you have no pager and no reviewer. A solo sketch does not need a page-owner card.&lt;/p&gt;

&lt;p&gt;Skip it if the real question is which model wins a benchmark. I am not supplying scores, and a cost gate will not invent them.&lt;/p&gt;

&lt;p&gt;Skip it if the repo is incident-adjacent production and you wanted a lighter change process. A &lt;code&gt;$0&lt;/code&gt; lane is not lighter change management. It is a missing owner with a friendlier invoice.&lt;/p&gt;

&lt;p&gt;Skip it if you need a quota, a GPU shape, or a permanence promise before you will even pilot. I do not have those facts. Waiting for a primary source is cheaper than publishing a fake one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the sheet will not prove
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;H&lt;/code&gt; ignores the rest of the context switch. The sheet ignores morale. It also ignores a paid support desk that replies slower than your own on-call. Cheap support is not the same thing as fast support.&lt;/p&gt;

&lt;p&gt;Founders sand down self-host cash. Champions sand down free-lane &lt;code&gt;E&lt;/code&gt;. If both arrive with heroic inputs, the meeting is theater. Send them back to measure.&lt;/p&gt;

&lt;p&gt;The feed this week is loud about vibe-coded demos, and about agents that notice something sensitive and stay quiet. I am not treating those posts as audited studies. I am treating them as a reminder. The agent does not own the outcome. You do.&lt;/p&gt;

&lt;p&gt;If a free model lane and a free server are already on your shortlist, fill this card with your own &lt;code&gt;E&lt;/code&gt;, &lt;code&gt;H&lt;/code&gt;, and &lt;code&gt;R&lt;/code&gt; before you send the invite. Confirm the live terms that day. Then keep, move, or stop.&lt;/p&gt;

&lt;p&gt;Which single input, measured next week, would flip your column — &lt;code&gt;E&lt;/code&gt;, the boundary hours, or the empty page-owner field?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Free Hosted, Paid, or Self-Host: A Custody Worksheet for PR Spikes</title>
      <dc:creator>bestbee</dc:creator>
      <pubDate>Thu, 08 Oct 2026 08:58:21 +0000</pubDate>
      <link>https://dev.to/bestbee/free-hosted-paid-or-self-host-a-custody-worksheet-for-pr-spikes-bd4</link>
      <guid>https://dev.to/bestbee/free-hosted-paid-or-self-host-a-custody-worksheet-for-pr-spikes-bd4</guid>
      <description>&lt;p&gt;I start October routing reviews with one rude question. If the private monorepo vanished from the queue, would you still be arguing about tokens?&lt;/p&gt;

&lt;p&gt;Most weeks the answer is no. The fight was never about the pool. It was about who is allowed to see the diff.&lt;/p&gt;

&lt;p&gt;Picture a Thursday in early October. Two senior maintainers. A public repo that suddenly has a crowd. A private monorepo that cannot leak. Someone posts, 'We already have a free lane. Why are the seniors still reading every patch by hand?'&lt;/p&gt;

&lt;p&gt;Good instinct. Bad unit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three lanes, one job
&lt;/h2&gt;

&lt;p&gt;The job is narrow. Draft a review note. Suggest a small patch. A human still merges.&lt;/p&gt;

&lt;p&gt;The lanes are not narrow. They fail for different reasons.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A free hosted lane, sometimes paired with a free server you do not pay for yet.&lt;/li&gt;
&lt;li&gt;A paid vendor lane, where the invoice is really a contract.&lt;/li&gt;
&lt;li&gt;A self-hosted lane, where you own the process and the pager.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Which one should hold a contribution spike? I do not start from the sticker. I start from custody.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the brief actually states
&lt;/h3&gt;

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

&lt;p&gt;The brief for this piece describes MonkeyCode as an open-source project, with free model access and a free server option. It also states a free-token pool of 10 million tokens. That is the claim I was given, dated against 8 October 2026. It is not a screenshot from last quarter, and it is not an SLA I measured.&lt;/p&gt;

&lt;p&gt;Read the license file and the allowance page on the day you decide. A wiki paste of a token number is how teams budget a sprint on a stale page.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I refuse to infer
&lt;/h3&gt;

&lt;p&gt;I am not adding model names, hardware sizes, uptime, latency, or a quality score. I am not saying the pool is permanent. I am not saying the free server has a duration.&lt;/p&gt;

&lt;p&gt;A large pool can still be the wrong lane. Have you watched a team miss that?&lt;/p&gt;

&lt;p&gt;Open source does not mean 'fine for customer code.' It means you can read the license. If you have not opened that file, you do not have a lane yet. You have a rumor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Name the variables, or the meeting is theater
&lt;/h2&gt;

&lt;p&gt;I will not score a lane until these symbols are written down. If a symbol has no owner, it does not enter the decision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;V&lt;/code&gt; — share of assisted tasks that touch private code, secrets, or customer data. From 0 to 1.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;C&lt;/code&gt; — custody bar. &lt;code&gt;0&lt;/code&gt; means public code only. &lt;code&gt;1&lt;/code&gt; means prompts and diffs stay in a tenant you control.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; — assisted diffs you expect per week.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;H&lt;/code&gt; — minutes a named reviewer will actually spend on each assisted diff. Not the minutes you wish they had.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;R&lt;/code&gt; — reviewer hours available per week for this lane.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;S&lt;/code&gt; — spike length in weeks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;T&lt;/code&gt; — tokens per assisted diff, measured on your repos. Not borrowed from a launch post.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;F&lt;/code&gt; — stated free-token pool. The brief says 10,000,000. Re-read it. Do not hard-code a blog.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;U&lt;/code&gt; — paid price per million tokens, from a quote you hold. I will not invent one.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;O&lt;/code&gt; — self-host ops hours per week, times loaded hourly cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Review load is &lt;code&gt;A * H / 60&lt;/code&gt;. If that exceeds &lt;code&gt;R&lt;/code&gt;, stop. You do not have a model problem. You have a calendar problem.&lt;/p&gt;

&lt;p&gt;Spike burn is &lt;code&gt;A * S * T&lt;/code&gt;. Headroom is &lt;code&gt;F / burn - 1&lt;/code&gt;. I want at least 0.20 before a free pool carries a public spike. That 0.20 is a policy choice. Say so in the ticket.&lt;/p&gt;

&lt;p&gt;A scorecard is a conversation tool. It is not objective truth. Change the threshold and you can change the winner. Pretending otherwise is how a worksheet becomes a slogan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fill last year's spike before you guess &lt;code&gt;A&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Do not borrow my sketch as your forecast. Count your own default branch. Last October is a baseline, not a destiny.&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;# Merges in last October. Swap the branch and the dates.&lt;/span&gt;
git log origin/main &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"2025-10-01"&lt;/span&gt; &lt;span class="nt"&gt;--until&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"2025-10-28"&lt;/span&gt; &lt;span class="nt"&gt;--merges&lt;/span&gt; &lt;span class="nt"&gt;--oneline&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Who actually merged? If two names dominate, R is smaller than the org chart.&lt;/span&gt;
git log origin/main &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"2025-10-01"&lt;/span&gt; &lt;span class="nt"&gt;--until&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"2025-10-28"&lt;/span&gt; &lt;span class="nt"&gt;--merges&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;'%an'&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;sort&lt;/span&gt; &lt;span class="nt"&gt;-nr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Public-event calendars make October loud. Hacktoberfest is the obvious one. I am not quoting this year's rules, prizes, or dates. If badges matter to your contributors, read the current event page. Your merge log matters more than the badge.&lt;/p&gt;

&lt;p&gt;Why pull last year at all? Because a spike you did not count will be replaced by a round number someone likes. Round numbers are where free pools go to die.&lt;/p&gt;

&lt;h2&gt;
  
  
  A sketch, so the arithmetic is visible
&lt;/h2&gt;

&lt;p&gt;Not a customer. Not a benchmark. Replace every number before you forward this to finance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public assisted diffs: 40 per week. Private: 8 per week.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;H&lt;/code&gt; = 12 minutes. Two reviewers, 5 hours each, so &lt;code&gt;R&lt;/code&gt; = 10.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;S&lt;/code&gt; = 4. &lt;code&gt;T&lt;/code&gt; = 8,000. Illustrative until you measure 20 real diffs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;U&lt;/code&gt; = 3 currency units per million tokens. Placeholder. Throw it out when the quote arrives.&lt;/li&gt;
&lt;li&gt;Self-host: 4 ops hours per week at 80 per hour, so weekly &lt;code&gt;O&lt;/code&gt; = 320.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Public review load is &lt;code&gt;40 * 12 / 60 = 8&lt;/code&gt; hours. Private adds &lt;code&gt;1.6&lt;/code&gt;. Total &lt;code&gt;9.6&lt;/code&gt; against &lt;code&gt;10&lt;/code&gt;. One sick day and the lane is fiction.&lt;/p&gt;

&lt;p&gt;Public burn is &lt;code&gt;40 * 4 * 8000 = 1,280,000&lt;/code&gt; tokens. Private adds &lt;code&gt;256,000&lt;/code&gt;. Combined &lt;code&gt;1,536,000&lt;/code&gt;. Against a stated pool of 10,000,000, headroom looks luxurious. Only if that pool is still the number on the page. And only if private diffs are allowed to leave your tenant.&lt;/p&gt;

&lt;p&gt;They are not, in this sketch. So the free hosted column dies on the private slice even while the pool looks fat. See how fast the sticker stopped mattering?&lt;/p&gt;

&lt;p&gt;Paid token bill at the placeholder rate is about &lt;code&gt;1.536 * 3 = 4.6&lt;/code&gt; currency units for the month. Tiny next to reviewer time. If your real quote looks like this, do not pretend price is the decision. If your quote is a hundred times higher, rerun the line. Still compare it to ops cost and to &lt;code&gt;R&lt;/code&gt;, not to a vibe.&lt;/p&gt;

&lt;p&gt;Self-host for four weeks is &lt;code&gt;320 * 4 = 1,280&lt;/code&gt; before any machine you already rack. You are buying control. You are also buying a ceiling you have to measure yourself. I am not going to invent that ceiling here.&lt;/p&gt;

&lt;h2&gt;
  
  
  What flips the call
&lt;/h2&gt;

&lt;p&gt;Would you still send those 8 private diffs if the free pool doubled? I would not. Custody does not scale with tokens.&lt;/p&gt;

&lt;p&gt;Would you still self-host if every assisted diff stayed on public repos whose license you already understand? Maybe not. Ops cost is a tax on control you may not need for a four-week crowd.&lt;/p&gt;

&lt;p&gt;Would you still buy the paid lane if counsel says the free hosted terms already clear your bar for public code? Then buy only the private slice. A blend rate for work that never needed it is how budgets get muddy.&lt;/p&gt;

&lt;p&gt;Three sensitivities. Then stop debating adjectives.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;T&lt;/code&gt; is 5x the sketch, public burn alone is 6.4 million. Add the private slice and you are leaning on a pool you have not re-read. Measure &lt;code&gt;T&lt;/code&gt; before you argue.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;H&lt;/code&gt; moves from 12 to 20 minutes, public review load is 13.3 hours. Over &lt;code&gt;R&lt;/code&gt;. The lane is a no at every price, including free.&lt;/li&gt;
&lt;li&gt;If private work becomes half the queue, free hosted is out. Do not negotiate with that gate.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lane&lt;/th&gt;
&lt;th&gt;Fits when&lt;/th&gt;
&lt;th&gt;Fails when&lt;/th&gt;
&lt;th&gt;What you actually pay&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free hosted, plus the stated free server option&lt;/td&gt;
&lt;td&gt;Public repos, license read, allowance re-checked today, no unnamed tool grant&lt;/td&gt;
&lt;td&gt;Any private or secret path, unread terms, pool you cannot point to&lt;/td&gt;
&lt;td&gt;Reviewer hours, and the chance the allowance moves&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;td&gt;Counsel accepts the terms and the private slice is real&lt;/td&gt;
&lt;td&gt;The quote is standing in for a custody rule you never wrote&lt;/td&gt;
&lt;td&gt;Quote, switching cost, reviewer hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-host&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;C = 1&lt;/code&gt; and someone owns the pager through expiry&lt;/td&gt;
&lt;td&gt;No pager owner, or you only needed public notes&lt;/td&gt;
&lt;td&gt;Ops hours, plus a ceiling you measure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Gates, owner, expiry, exit
&lt;/h2&gt;

&lt;p&gt;Five gates. Fail one, and that workload leaves the free hosted column. I do not average them into a green score.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Custody.&lt;/strong&gt; A secret, a production credential, a customer payload, or a private repo sits in the prompt path. Free hosted is a no.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review capacity.&lt;/strong&gt; &lt;code&gt;A * H / 60 &amp;gt; R&lt;/code&gt;. Cut scope or add a human. Do not add a model and call it a plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pool headroom.&lt;/strong&gt; Spike burn exceeds 80% of the stated pool, or you cannot open the allowance page today. Do not plan on it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License.&lt;/strong&gt; You have not read the project license and the output terms against the repo you merge into. Stop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool reach.&lt;/strong&gt; The assistant can call tools outside the repo. That is a grant. No named owner, no grant.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Owner: one engineering manager, named on the ticket. A Slack channel is not an owner.&lt;/p&gt;

&lt;p&gt;Expiry: the last day of the spike, or 30 days from the decision, whichever comes first. An allowance you have not re-checked is an expired assumption.&lt;/p&gt;

&lt;p&gt;Exit: archive the routing note when private share crosses your line, when the allowance page changes, or when reviewers miss &lt;code&gt;H&lt;/code&gt; for two weeks. A stale 'free is fine' wiki page is how the next incident gets a head start.&lt;/p&gt;

&lt;p&gt;Who writes the archive line? The same named owner. If they have left the team, the note expires that day. Do not inherit a dead assumption with the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run both cases before the meeting
&lt;/h2&gt;

&lt;p&gt;This script is a worksheet. It does not call a model. It does not time a server. I am not publishing it as a benchmark. Paste your numbers. Read the fails.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Custody gate worksheet. Sketch math only. Not a product test.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;review_h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assisted_per_week&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;minutes_per_diff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
    &lt;span class="n"&gt;burn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assisted_per_week&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weeks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens_per_diff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;headroom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stated_free_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;burn&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;if&lt;/span&gt; &lt;span class="n"&gt;burn&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;reasons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;private_or_secret&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAIL custody: private or secret path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;review_h&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reviewer_hours&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAIL review capacity: %.1fh &amp;gt; %.1fh&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;review_h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reviewer_hours&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;headroom&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAIL pool headroom: %.0f%%&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headroom&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="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;license_read&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAIL license: unread&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tools_enabled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grant_owner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAIL tool grant: no owner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;review_hours&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;review_h&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token_burn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;burn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headroom&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headroom&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;free_hosted_ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasons&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reasons&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PASS for this public slice only&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &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;' | python3 custody_gate.py
{
  "assisted_per_week": 40,
  "minutes_per_diff": 12,
  "weeks": 4,
  "tokens_per_diff": 8000,
  "stated_free_tokens": 10000000,
  "reviewer_hours": 10,
  "private_or_secret": false,
  "license_read": true,
  "tools_enabled": false,
  "grant_owner": ""
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On that public sketch the worksheet returns &lt;code&gt;review_hours&lt;/code&gt; 8.0, &lt;code&gt;token_burn&lt;/code&gt; 1280000, &lt;code&gt;headroom&lt;/code&gt; about 6.81, and a pass that applies to the public slice only. Flip &lt;code&gt;private_or_secret&lt;/code&gt; to true and the same pool fails. If you only run the flattering case, you do not have a decision. You have a wish.&lt;/p&gt;

&lt;p&gt;After the free column fails, compare the other two with your quote, not with mine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;paid_month = (burn / 1000000) * U
self_month = ops_hours_per_week * loaded_hourly * weeks
pick paid  if counsel accepts vendor terms AND paid_month + switching_cost &amp;lt; self_month
pick self  if C == 1 AND a named person owns the pager until expiry
pick neither if review_hours &amp;gt; R
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Who should walk away
&lt;/h2&gt;

&lt;p&gt;Skip this if you need a model bake-off. I did not run one. I will not invent quality scores to fill the gap.&lt;/p&gt;

&lt;p&gt;Skip it if counsel has not opened the data-processing terms. A table is not a DPA.&lt;/p&gt;

&lt;p&gt;Skip it if you want the free server as a permanent production dependency. The brief states an option. It does not state a duration, a machine size, or an SLA. I will not decorate that silence.&lt;/p&gt;

&lt;p&gt;Skip it if you are about to point an agent at a third-party system 'just to see.' Early October chatter included writeups about agents and real-company targets. I am not repeating those experiments, and I am not treating a DEV headline as a measured rate. The useful bit is boring. Tool reach is a grant. Unowned grants do not belong in a contribution pilot.&lt;/p&gt;

&lt;p&gt;And skip it if you already know review hours are the bottleneck. Tokens will not hide that. Not at 10 million. Not at 10 times that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then decide
&lt;/h2&gt;

&lt;p&gt;If you are weighing hosted free capacity against a server you would run yourself, read the current license and the allowance page, then run the worksheet twice. I would rather you close the tab than route a private diff because a pool looked large.&lt;/p&gt;

&lt;p&gt;Which variable, if it moved, would reverse your call — custody, review hours, or the allowance you re-read today?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
