fix(dashboard): dual y-axis for losses+alpha panel

This commit is contained in:
2026-08-24 09:21:43 +02:00
parent 4a6e3347c6
commit 55d69a9352
2 changed files with 319 additions and 314 deletions
+272 -260
View File
@@ -1,7 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1400" height="2520" viewBox="0 0 1400 2520" font-family="sans-serif"> <svg xmlns="http://www.w3.org/2000/svg" width="1400" height="1720" viewBox="0 0 1400 1720" font-family="sans-serif">
<rect width="1400" height="2520" fill="white"/> <rect width="1400" height="1720" fill="white"/>
<text x="700" y="32" text-anchor="middle" font-size="21" font-weight="bold">SAC-LSTM campaign dashboard - live run (current only)</text> <text x="700" y="32" text-anchor="middle" font-size="21" font-weight="bold">SAC-LSTM campaign dashboard - live run (current only)</text>
<text x="700" y="56" text-anchor="middle" font-size="12" fill="#555">generated 2026-08-24 09:14:55 - auto-reloads every 60 s (open this file in Chrome)</text> <text x="700" y="56" text-anchor="middle" font-size="12" fill="#555">generated 2026-08-24 09:21:32 - auto-reloads every 60 s (open this file in Chrome)</text>
<text x="70" y="100" font-size="15" font-weight="bold">Test matches - win % vs opponents</text> <text x="70" y="100" font-size="15" font-weight="bold">Test matches - win % vs opponents</text>
<text x="70" y="115" font-size="11" fill="#555">raw dots = single test matches, thick = rolling-mean-10</text> <text x="70" y="115" font-size="11" fill="#555">raw dots = single test matches, thick = rolling-mean-10</text>
<line x1="70" y1="720.0" x2="697" y2="720.0" stroke="#dddddd"/> <line x1="70" y1="720.0" x2="697" y2="720.0" stroke="#dddddd"/>
@@ -14,28 +14,32 @@
<line x1="70" y1="720" x2="70" y2="120" stroke="black"/> <line x1="70" y1="720" x2="70" y2="120" stroke="black"/>
<line x1="70.0" y1="720" x2="70.0" y2="724" stroke="black"/> <line x1="70.0" y1="720" x2="70.0" y2="724" stroke="black"/>
<text x="70.0" y="737" text-anchor="middle" font-size="11">1</text> <text x="70.0" y="737" text-anchor="middle" font-size="11">1</text>
<line x1="127.0" y1="720" x2="127.0" y2="724" stroke="black"/> <line x1="118.2" y1="720" x2="118.2" y2="724" stroke="black"/>
<text x="127.0" y="737" text-anchor="middle" font-size="11">2</text> <text x="118.2" y="737" text-anchor="middle" font-size="11">2</text>
<line x1="184.0" y1="720" x2="184.0" y2="724" stroke="black"/> <line x1="166.5" y1="720" x2="166.5" y2="724" stroke="black"/>
<text x="184.0" y="737" text-anchor="middle" font-size="11">3</text> <text x="166.5" y="737" text-anchor="middle" font-size="11">3</text>
<line x1="241.0" y1="720" x2="241.0" y2="724" stroke="black"/> <line x1="214.7" y1="720" x2="214.7" y2="724" stroke="black"/>
<text x="241.0" y="737" text-anchor="middle" font-size="11">4</text> <text x="214.7" y="737" text-anchor="middle" font-size="11">4</text>
<line x1="298.0" y1="720" x2="298.0" y2="724" stroke="black"/> <line x1="262.9" y1="720" x2="262.9" y2="724" stroke="black"/>
<text x="298.0" y="737" text-anchor="middle" font-size="11">5</text> <text x="262.9" y="737" text-anchor="middle" font-size="11">5</text>
<line x1="355.0" y1="720" x2="355.0" y2="724" stroke="black"/> <line x1="311.2" y1="720" x2="311.2" y2="724" stroke="black"/>
<text x="355.0" y="737" text-anchor="middle" font-size="11">6</text> <text x="311.2" y="737" text-anchor="middle" font-size="11">6</text>
<line x1="412.0" y1="720" x2="412.0" y2="724" stroke="black"/> <line x1="359.4" y1="720" x2="359.4" y2="724" stroke="black"/>
<text x="412.0" y="737" text-anchor="middle" font-size="11">7</text> <text x="359.4" y="737" text-anchor="middle" font-size="11">7</text>
<line x1="469.0" y1="720" x2="469.0" y2="724" stroke="black"/> <line x1="407.6" y1="720" x2="407.6" y2="724" stroke="black"/>
<text x="469.0" y="737" text-anchor="middle" font-size="11">8</text> <text x="407.6" y="737" text-anchor="middle" font-size="11">8</text>
<line x1="526.0" y1="720" x2="526.0" y2="724" stroke="black"/> <line x1="455.8" y1="720" x2="455.8" y2="724" stroke="black"/>
<text x="526.0" y="737" text-anchor="middle" font-size="11">9</text> <text x="455.8" y="737" text-anchor="middle" font-size="11">9</text>
<line x1="583.0" y1="720" x2="583.0" y2="724" stroke="black"/> <line x1="504.1" y1="720" x2="504.1" y2="724" stroke="black"/>
<text x="583.0" y="737" text-anchor="middle" font-size="11">10</text> <text x="504.1" y="737" text-anchor="middle" font-size="11">10</text>
<line x1="640.0" y1="720" x2="640.0" y2="724" stroke="black"/> <line x1="552.3" y1="720" x2="552.3" y2="724" stroke="black"/>
<text x="640.0" y="737" text-anchor="middle" font-size="11">11</text> <text x="552.3" y="737" text-anchor="middle" font-size="11">11</text>
<line x1="600.5" y1="720" x2="600.5" y2="724" stroke="black"/>
<text x="600.5" y="737" text-anchor="middle" font-size="11">12</text>
<line x1="648.8" y1="720" x2="648.8" y2="724" stroke="black"/>
<text x="648.8" y="737" text-anchor="middle" font-size="11">13</text>
<line x1="697.0" y1="720" x2="697.0" y2="724" stroke="black"/> <line x1="697.0" y1="720" x2="697.0" y2="724" stroke="black"/>
<text x="697.0" y="737" text-anchor="middle" font-size="11">12</text> <text x="697.0" y="737" text-anchor="middle" font-size="11">14</text>
<line x1="66" y1="720.0" x2="70" y2="720.0" stroke="black"/> <line x1="66" y1="720.0" x2="70" y2="720.0" stroke="black"/>
<text x="63" y="724.0" text-anchor="end" font-size="11">0</text> <text x="63" y="724.0" text-anchor="end" font-size="11">0</text>
<line x1="66" y1="600.0" x2="70" y2="600.0" stroke="black"/> <line x1="66" y1="600.0" x2="70" y2="600.0" stroke="black"/>
@@ -51,69 +55,75 @@
<text x="383" y="753" text-anchor="middle" font-size="12">test match number (each opponent)</text> <text x="383" y="753" text-anchor="middle" font-size="12">test match number (each opponent)</text>
<text x="16" y="420" text-anchor="middle" font-size="12" transform="rotate(-90 16 420)">win rate (%)</text> <text x="16" y="420" text-anchor="middle" font-size="12" transform="rotate(-90 16 420)">win rate (%)</text>
<circle cx="70.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="70.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="127.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="118.2" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="184.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="166.5" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="241.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="214.7" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="298.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="262.9" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="355.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="311.2" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="412.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="359.4" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="469.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="407.6" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="526.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="455.8" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="583.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="504.1" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="640.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="552.3" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="697.0" cy="660.0" r="2" fill="#d62728" opacity="0.25"/> <circle cx="600.5" cy="660.0" r="2" fill="#d62728" opacity="0.25"/>
<polyline points="70.0,720.0 127.0,720.0 184.0,720.0 241.0,720.0 298.0,720.0 355.0,720.0 412.0,720.0 469.0,720.0 526.0,720.0 583.0,720.0 640.0,720.0 697.0,714.0" fill="none" stroke="#d62728" stroke-width="3.5" opacity="1.0"/> <circle cx="648.8" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="697.0" cy="720.0" r="2" fill="#d62728" opacity="0.25"/>
<polyline points="70.0,720.0 118.2,720.0 166.5,720.0 214.7,720.0 262.9,720.0 311.2,720.0 359.4,720.0 407.6,720.0 455.8,720.0 504.1,720.0 552.3,720.0 600.5,714.0 648.8,714.0 697.0,714.0" fill="none" stroke="#d62728" stroke-width="3.5" opacity="1.0"/>
<circle cx="70.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="70.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="127.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="118.2" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="184.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="166.5" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="241.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="214.7" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="298.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="262.9" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="355.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="311.2" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="412.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="359.4" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="469.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="407.6" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="526.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="455.8" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="583.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="504.1" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="640.0" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="552.3" cy="720.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="697.0" cy="480.0" r="2" fill="#1f77b4" opacity="0.25"/> <circle cx="600.5" cy="480.0" r="2" fill="#1f77b4" opacity="0.25"/>
<polyline points="70.0,720.0 127.0,720.0 184.0,720.0 241.0,720.0 298.0,720.0 355.0,720.0 412.0,720.0 469.0,720.0 526.0,720.0 583.0,720.0 640.0,720.0 697.0,696.0" fill="none" stroke="#1f77b4" stroke-width="3.5" opacity="1.0"/> <circle cx="648.8" cy="240.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="697.0" cy="660.0" r="2" fill="#1f77b4" opacity="0.25"/>
<polyline points="70.0,720.0 118.2,720.0 166.5,720.0 214.7,720.0 262.9,720.0 311.2,720.0 359.4,720.0 407.6,720.0 455.8,720.0 504.1,720.0 552.3,720.0 600.5,696.0 648.8,648.0 697.0,642.0" fill="none" stroke="#1f77b4" stroke-width="3.5" opacity="1.0"/>
<circle cx="70.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="70.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="127.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="118.2" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="184.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="166.5" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="241.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="214.7" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="298.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="262.9" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="355.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="311.2" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="412.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="359.4" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="469.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="407.6" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="526.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="455.8" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="583.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="504.1" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="640.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="552.3" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="697.0" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/> <circle cx="600.5" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<polyline points="70.0,720.0 127.0,720.0 184.0,720.0 241.0,720.0 298.0,720.0 355.0,720.0 412.0,720.0 469.0,720.0 526.0,720.0 583.0,720.0 640.0,720.0 697.0,720.0" fill="none" stroke="#2ca02c" stroke-width="3.5" opacity="1.0"/> <circle cx="648.8" cy="720.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="697.0" cy="660.0" r="2" fill="#2ca02c" opacity="0.25"/>
<polyline points="70.0,720.0 118.2,720.0 166.5,720.0 214.7,720.0 262.9,720.0 311.2,720.0 359.4,720.0 407.6,720.0 455.8,720.0 504.1,720.0 552.3,720.0 600.5,720.0 648.8,720.0 697.0,714.0" fill="none" stroke="#2ca02c" stroke-width="3.5" opacity="1.0"/>
<line x1="82" y1="772" x2="110" y2="772" stroke="#d62728" stroke-width="3"/> <line x1="82" y1="772" x2="110" y2="772" stroke="#d62728" stroke-width="3"/>
<text x="116" y="776" font-size="12">Corners - 12 evals</text> <text x="116" y="776" font-size="12">Corners - 14 evals</text>
<line x1="82" y1="790" x2="110" y2="790" stroke="#1f77b4" stroke-width="3"/> <line x1="82" y1="790" x2="110" y2="790" stroke="#1f77b4" stroke-width="3"/>
<text x="116" y="794" font-size="12">Crazy - 12 evals</text> <text x="116" y="794" font-size="12">Crazy - 14 evals</text>
<line x1="82" y1="808" x2="110" y2="808" stroke="#2ca02c" stroke-width="3"/> <line x1="82" y1="808" x2="110" y2="808" stroke="#2ca02c" stroke-width="3"/>
<text x="116" y="812" font-size="12">Target - 12 evals</text> <text x="116" y="812" font-size="12">Target - 14 evals</text>
<text x="747" y="100" font-size="15" font-weight="bold">Training losses &amp; alpha (log scale)</text> <text x="747" y="100" font-size="15" font-weight="bold">Training losses (log) &amp; alpha (linear)</text>
<text x="747" y="115" font-size="11" fill="#555">training_metrics.jsonl - big early spikes are normal</text> <text x="747" y="115" font-size="11" fill="#555">training_metrics.jsonl - big early spikes are normal</text>
<line x1="747" y1="720.0" x2="1375" y2="720.0" stroke="#dddddd"/> <line x1="747" y1="720.0" x2="1329" y2="720.0" stroke="#dddddd"/>
<line x1="747" y1="570.0" x2="1375" y2="570.0" stroke="#dddddd"/> <line x1="747" y1="570.0" x2="1329" y2="570.0" stroke="#dddddd"/>
<line x1="747" y1="420.0" x2="1375" y2="420.0" stroke="#dddddd"/> <line x1="747" y1="420.0" x2="1329" y2="420.0" stroke="#dddddd"/>
<line x1="747" y1="270.0" x2="1375" y2="270.0" stroke="#dddddd"/> <line x1="747" y1="270.0" x2="1329" y2="270.0" stroke="#dddddd"/>
<line x1="747" y1="120.0" x2="1375" y2="120.0" stroke="#dddddd"/> <line x1="747" y1="120.0" x2="1329" y2="120.0" stroke="#dddddd"/>
<line x1="747" y1="720" x2="1375" y2="720" stroke="black"/> <line x1="747" y1="720" x2="1329" y2="720" stroke="black"/>
<line x1="747" y1="720" x2="747" y2="120" stroke="black"/> <line x1="747" y1="720" x2="747" y2="120" stroke="black"/>
<line x1="747.0" y1="720" x2="747.0" y2="724" stroke="black"/> <line x1="747.0" y1="720" x2="747.0" y2="724" stroke="black"/>
<text x="747.0" y="737" text-anchor="middle" font-size="11">1</text> <text x="747.0" y="737" text-anchor="middle" font-size="11">1</text>
<line x1="904.0" y1="720" x2="904.0" y2="724" stroke="black"/> <line x1="892.5" y1="720" x2="892.5" y2="724" stroke="black"/>
<text x="904.0" y="737" text-anchor="middle" font-size="11">7</text> <text x="892.5" y="737" text-anchor="middle" font-size="11">8</text>
<line x1="1061.0" y1="720" x2="1061.0" y2="724" stroke="black"/> <line x1="1038.0" y1="720" x2="1038.0" y2="724" stroke="black"/>
<text x="1061.0" y="737" text-anchor="middle" font-size="11">14</text> <text x="1038.0" y="737" text-anchor="middle" font-size="11">16</text>
<line x1="1218.0" y1="720" x2="1218.0" y2="724" stroke="black"/> <line x1="1183.5" y1="720" x2="1183.5" y2="724" stroke="black"/>
<text x="1218.0" y="737" text-anchor="middle" font-size="11">20</text> <text x="1183.5" y="737" text-anchor="middle" font-size="11">23</text>
<line x1="1375.0" y1="720" x2="1375.0" y2="724" stroke="black"/> <line x1="1329.0" y1="720" x2="1329.0" y2="724" stroke="black"/>
<text x="1375.0" y="737" text-anchor="middle" font-size="11">26</text> <text x="1329.0" y="737" text-anchor="middle" font-size="11">30</text>
<line x1="743" y1="720.0" x2="747" y2="720.0" stroke="black"/> <line x1="743" y1="720.0" x2="747" y2="720.0" stroke="black"/>
<text x="740" y="724.0" text-anchor="end" font-size="11">0.01</text> <text x="740" y="724.0" text-anchor="end" font-size="11">0.01</text>
<line x1="743" y1="570.0" x2="747" y2="570.0" stroke="black"/> <line x1="743" y1="570.0" x2="747" y2="570.0" stroke="black"/>
@@ -124,19 +134,36 @@
<text x="740" y="274.0" text-anchor="end" font-size="11">10</text> <text x="740" y="274.0" text-anchor="end" font-size="11">10</text>
<line x1="743" y1="120.0" x2="747" y2="120.0" stroke="black"/> <line x1="743" y1="120.0" x2="747" y2="120.0" stroke="black"/>
<text x="740" y="124.0" text-anchor="end" font-size="11">100</text> <text x="740" y="124.0" text-anchor="end" font-size="11">100</text>
<text x="1061" y="753" text-anchor="middle" font-size="12">metric line number</text> <text x="1038" y="753" text-anchor="middle" font-size="12">metric line number</text>
<text x="16" y="420" text-anchor="middle" font-size="12" transform="rotate(-90 16 420)">loss (log)</text> <text x="16" y="420" text-anchor="middle" font-size="12" transform="rotate(-90 16 420)">loss (log)</text>
<polyline points="747.0,281.9 772.1,253.6 797.2,243.9 822.4,213.5 847.5,207.6 872.6,386.8 897.7,424.4 922.8,307.1 948.0,293.6 973.1,282.6 998.2,242.7 1023.3,171.4 1048.4,158.6 1073.6,169.7 1098.7,191.2 1123.8,253.6 1148.9,327.8 1174.0,625.2 1199.2,506.4 1224.3,374.2 1249.4,425.9 1274.5,351.1 1299.6,357.9 1324.8,330.0 1349.9,251.4 1375.0,339.4" fill="none" stroke="#1f77b4" stroke-width="1.8" opacity="1.0"/> <polyline points="747.0,281.9 767.1,253.6 787.1,243.9 807.2,213.5 827.3,207.6 847.3,386.8 867.4,424.4 887.5,307.1 907.6,293.6 927.6,282.6 947.7,242.7 967.8,171.4 987.8,158.6 1007.9,169.7 1028.0,191.2 1048.0,253.6 1068.1,327.8 1088.2,625.2 1108.2,506.4 1128.3,374.2 1148.4,425.9 1168.4,351.1 1188.5,357.9 1208.6,330.0 1228.7,251.4 1248.7,339.4 1268.8,331.4 1288.9,283.3 1308.9,320.4 1329.0,339.4" fill="none" stroke="#1f77b4" stroke-width="1.8" opacity="1.0"/>
<polyline points="747.0,348.9 772.1,307.9 797.2,284.5 822.4,261.3 847.5,244.2 872.6,235.2 897.7,236.5 922.8,241.4 948.0,270.7 973.1,292.4 998.2,378.9 1023.3,302.9 1048.4,277.7 1073.6,264.4 1098.7,254.8 1123.8,246.5 1148.9,242.0 1174.0,251.8 1199.2,262.0 1224.3,273.4 1249.4,295.3 1274.5,327.5 1299.6,335.9 1324.8,438.0 1349.9,400.5 1375.0,500.9" fill="none" stroke="#ff7f0e" stroke-width="1.8" opacity="1.0"/> <polyline points="747.0,348.9 767.1,307.9 787.1,284.5 807.2,261.3 827.3,244.2 847.3,235.2 867.4,236.5 887.5,241.4 907.6,270.7 927.6,292.4 947.7,378.9 967.8,302.9 987.8,277.7 1007.9,264.4 1028.0,254.8 1048.0,246.5 1068.1,242.0 1088.2,251.8 1108.2,262.0 1128.3,273.4 1148.4,295.3 1168.4,327.5 1188.5,335.9 1208.6,438.0 1228.7,400.5 1248.7,500.9 1268.8,390.5 1288.9,329.2 1308.9,316.2 1329.0,311.3" fill="none" stroke="#ff7f0e" stroke-width="1.8" opacity="1.0"/>
<polyline points="747.0,420.0 772.1,420.1 797.2,420.2 822.4,420.3 847.5,420.3 872.6,420.4 897.7,420.5 922.8,420.5 948.0,420.6 973.1,420.6 998.2,420.7 1023.3,420.7 1048.4,420.7 1073.6,420.6 1098.7,420.5 1123.8,420.4 1148.9,420.4 1174.0,420.3 1199.2,420.2 1224.3,420.1 1249.4,420.2 1274.5,420.3 1299.6,420.3 1324.8,420.4 1349.9,420.5 1375.0,420.7" fill="none" stroke="#9467bd" stroke-width="1.8" opacity="1.0"/> <line x1="747" y1="720.0" x2="1329" y2="720.0" stroke="#e9dcf5"/>
<line x1="747" y1="570.0" x2="1329" y2="570.0" stroke="#e9dcf5"/>
<line x1="747" y1="420.0" x2="1329" y2="420.0" stroke="#e9dcf5"/>
<line x1="747" y1="270.0" x2="1329" y2="270.0" stroke="#e9dcf5"/>
<line x1="747" y1="120.0" x2="1329" y2="120.0" stroke="#e9dcf5"/>
<line x1="1329" y1="720" x2="1329" y2="120" stroke="#9467bd"/>
<line x1="1329" y1="720.0" x2="1333" y2="720.0" stroke="#9467bd"/>
<text x="1336" y="724.0" font-size="11" fill="#9467bd">0</text>
<line x1="1329" y1="570.0" x2="1333" y2="570.0" stroke="#9467bd"/>
<text x="1336" y="574.0" font-size="11" fill="#9467bd">0.25</text>
<line x1="1329" y1="420.0" x2="1333" y2="420.0" stroke="#9467bd"/>
<text x="1336" y="424.0" font-size="11" fill="#9467bd">0.5</text>
<line x1="1329" y1="270.0" x2="1333" y2="270.0" stroke="#9467bd"/>
<text x="1336" y="274.0" font-size="11" fill="#9467bd">0.75</text>
<line x1="1329" y1="120.0" x2="1333" y2="120.0" stroke="#9467bd"/>
<text x="1336" y="124.0" font-size="11" fill="#9467bd">1</text>
<text x="1346" y="420" text-anchor="middle" font-size="12" fill="#9467bd" transform="rotate(90 1346 420)">alpha</text>
<polyline points="747.0,120.2 767.1,120.9 787.1,121.6 807.2,122.3 827.3,123.1 847.3,123.8 867.4,124.1 887.5,124.5 907.6,125.2 927.6,125.6 947.7,126.3 967.8,126.9 987.8,126.1 1007.9,125.4 1028.0,124.7 1048.0,124.0 1068.1,123.3 1088.2,122.6 1108.2,121.9 1128.3,121.2 1148.4,121.7 1168.4,122.4 1188.5,123.2 1208.6,123.9 1228.7,124.6 1248.7,126.0 1268.8,126.7 1288.9,127.4 1308.9,128.1 1329.0,128.5" fill="none" stroke="#9467bd" stroke-width="1.8" opacity="1.0"/>
<line x1="759" y1="772" x2="787" y2="772" stroke="#1f77b4" stroke-width="3"/> <line x1="759" y1="772" x2="787" y2="772" stroke="#1f77b4" stroke-width="3"/>
<text x="793" y="776" font-size="12">critic_loss</text> <text x="793" y="776" font-size="12">critic_loss</text>
<line x1="759" y1="790" x2="787" y2="790" stroke="#ff7f0e" stroke-width="3"/> <line x1="759" y1="790" x2="787" y2="790" stroke="#ff7f0e" stroke-width="3"/>
<text x="793" y="794" font-size="12">|actor_loss|</text> <text x="793" y="794" font-size="12">|actor_loss|</text>
<line x1="759" y1="808" x2="787" y2="808" stroke="#9467bd" stroke-width="3"/> <line x1="759" y1="808" x2="787" y2="808" stroke="#9467bd" stroke-width="3"/>
<text x="793" y="812" font-size="12">alpha</text> <text x="793" y="812" font-size="12">alpha</text>
<text x="70" y="940" font-size="15" font-weight="bold">Alpha temperature</text> <text x="70" y="940" font-size="15" font-weight="bold">Throughput - games per hour</text>
<text x="70" y="955" font-size="11" fill="#555">training_metrics.jsonl - high = exploring, low = exploiting</text> <text x="70" y="955" font-size="11" fill="#555">method: training_metrics.jsonl 'epoch' deltas; 1 row = one 10-game chunk</text>
<line x1="70" y1="1428.0" x2="697" y2="1428.0" stroke="#dddddd"/> <line x1="70" y1="1428.0" x2="697" y2="1428.0" stroke="#dddddd"/>
<line x1="70" y1="1310.5" x2="697" y2="1310.5" stroke="#dddddd"/> <line x1="70" y1="1310.5" x2="697" y2="1310.5" stroke="#dddddd"/>
<line x1="70" y1="1193.0" x2="697" y2="1193.0" stroke="#dddddd"/> <line x1="70" y1="1193.0" x2="697" y2="1193.0" stroke="#dddddd"/>
@@ -144,31 +171,78 @@
<line x1="70" y1="958.0" x2="697" y2="958.0" stroke="#dddddd"/> <line x1="70" y1="958.0" x2="697" y2="958.0" stroke="#dddddd"/>
<line x1="70" y1="1428" x2="697" y2="1428" stroke="black"/> <line x1="70" y1="1428" x2="697" y2="1428" stroke="black"/>
<line x1="70" y1="1428" x2="70" y2="958" stroke="black"/> <line x1="70" y1="1428" x2="70" y2="958" stroke="black"/>
<line x1="70.0" y1="1428" x2="70.0" y2="1432" stroke="black"/> <line x1="92.4" y1="1428" x2="92.4" y2="1432" stroke="black"/>
<text x="70.0" y="1445" text-anchor="middle" font-size="11">1</text> <text x="92.4" y="1445" text-anchor="middle" font-size="11">2</text>
<line x1="137.2" y1="1428" x2="137.2" y2="1432" stroke="black"/>
<text x="137.2" y="1445" text-anchor="middle" font-size="11">4</text>
<line x1="182.0" y1="1428" x2="182.0" y2="1432" stroke="black"/>
<text x="182.0" y="1445" text-anchor="middle" font-size="11">6</text>
<line x1="226.8" y1="1428" x2="226.8" y2="1432" stroke="black"/> <line x1="226.8" y1="1428" x2="226.8" y2="1432" stroke="black"/>
<text x="226.8" y="1445" text-anchor="middle" font-size="11">7</text> <text x="226.8" y="1445" text-anchor="middle" font-size="11">8</text>
<line x1="383.5" y1="1428" x2="383.5" y2="1432" stroke="black"/> <line x1="271.5" y1="1428" x2="271.5" y2="1432" stroke="black"/>
<text x="383.5" y="1445" text-anchor="middle" font-size="11">14</text> <text x="271.5" y="1445" text-anchor="middle" font-size="11">10</text>
<line x1="316.3" y1="1428" x2="316.3" y2="1432" stroke="black"/>
<text x="316.3" y="1445" text-anchor="middle" font-size="11">12</text>
<line x1="361.1" y1="1428" x2="361.1" y2="1432" stroke="black"/>
<text x="361.1" y="1445" text-anchor="middle" font-size="11">14</text>
<line x1="405.9" y1="1428" x2="405.9" y2="1432" stroke="black"/>
<text x="405.9" y="1445" text-anchor="middle" font-size="11">16</text>
<line x1="450.7" y1="1428" x2="450.7" y2="1432" stroke="black"/>
<text x="450.7" y="1445" text-anchor="middle" font-size="11">18</text>
<line x1="495.5" y1="1428" x2="495.5" y2="1432" stroke="black"/>
<text x="495.5" y="1445" text-anchor="middle" font-size="11">20</text>
<line x1="540.2" y1="1428" x2="540.2" y2="1432" stroke="black"/> <line x1="540.2" y1="1428" x2="540.2" y2="1432" stroke="black"/>
<text x="540.2" y="1445" text-anchor="middle" font-size="11">20</text> <text x="540.2" y="1445" text-anchor="middle" font-size="11">22</text>
<line x1="697.0" y1="1428" x2="697.0" y2="1432" stroke="black"/> <line x1="585.0" y1="1428" x2="585.0" y2="1432" stroke="black"/>
<text x="697.0" y="1445" text-anchor="middle" font-size="11">26</text> <text x="585.0" y="1445" text-anchor="middle" font-size="11">24</text>
<line x1="629.8" y1="1428" x2="629.8" y2="1432" stroke="black"/>
<text x="629.8" y="1445" text-anchor="middle" font-size="11">26</text>
<line x1="674.6" y1="1428" x2="674.6" y2="1432" stroke="black"/>
<text x="674.6" y="1445" text-anchor="middle" font-size="11">28</text>
<line x1="66" y1="1428.0" x2="70" y2="1428.0" stroke="black"/> <line x1="66" y1="1428.0" x2="70" y2="1428.0" stroke="black"/>
<text x="63" y="1432.0" text-anchor="end" font-size="11">0</text> <text x="63" y="1432.0" text-anchor="end" font-size="11">0</text>
<line x1="66" y1="1310.5" x2="70" y2="1310.5" stroke="black"/> <line x1="66" y1="1310.5" x2="70" y2="1310.5" stroke="black"/>
<text x="63" y="1314.5" text-anchor="end" font-size="11">0.25</text> <text x="63" y="1314.5" text-anchor="end" font-size="11">1653</text>
<line x1="66" y1="1193.0" x2="70" y2="1193.0" stroke="black"/> <line x1="66" y1="1193.0" x2="70" y2="1193.0" stroke="black"/>
<text x="63" y="1197.0" text-anchor="end" font-size="11">0.5</text> <text x="63" y="1197.0" text-anchor="end" font-size="11">3305</text>
<line x1="66" y1="1075.5" x2="70" y2="1075.5" stroke="black"/> <line x1="66" y1="1075.5" x2="70" y2="1075.5" stroke="black"/>
<text x="63" y="1079.5" text-anchor="end" font-size="11">0.75</text> <text x="63" y="1079.5" text-anchor="end" font-size="11">4958</text>
<line x1="66" y1="958.0" x2="70" y2="958.0" stroke="black"/> <line x1="66" y1="958.0" x2="70" y2="958.0" stroke="black"/>
<text x="63" y="962.0" text-anchor="end" font-size="11">1</text> <text x="63" y="962.0" text-anchor="end" font-size="11">6611</text>
<text x="383" y="1461" text-anchor="middle" font-size="12">metric line number</text> <text x="383" y="1461" text-anchor="middle" font-size="12">chunk interval (10-game chunks)</text>
<text x="16" y="1193" text-anchor="middle" font-size="12" transform="rotate(-90 16 1193)">alpha</text> <text x="16" y="1193" text-anchor="middle" font-size="12" transform="rotate(-90 16 1193)">games / hour</text>
<polyline points="70.0,958.1 95.1,958.7 120.2,959.3 145.2,959.8 170.3,960.4 195.4,961.0 220.5,961.2 245.6,961.5 270.6,962.1 295.7,962.4 320.8,962.9 345.9,963.4 371.0,962.8 396.0,962.3 421.1,961.7 446.2,961.1 471.3,960.6 496.4,960.0 521.4,959.5 546.5,958.9 571.6,959.3 596.7,959.9 621.8,960.5 646.8,961.0 671.9,961.6 697.0,962.7" fill="none" stroke="#9467bd" stroke-width="1.8" opacity="1.0"/> <circle cx="70.0" cy="1159.8" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<text x="747" y="940" font-size="15" font-weight="bold">Throughput - games per hour</text> <circle cx="92.4" cy="1413.4" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<text x="747" y="955" font-size="11" fill="#555">method: training_metrics.jsonl 'epoch' deltas; 1 row = one 10-game chunk</text> <circle cx="114.8" cy="1148.0" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="137.2" cy="1404.7" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="159.6" cy="1153.6" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="182.0" cy="1399.6" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="204.4" cy="1000.7" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="226.8" cy="1399.5" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="249.1" cy="1021.4" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="271.5" cy="1394.8" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="293.9" cy="1376.2" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="316.3" cy="1394.4" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="338.7" cy="1130.1" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="361.1" cy="1399.7" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="383.5" cy="1176.5" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="405.9" cy="1402.0" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="428.3" cy="1158.0" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="450.7" cy="1400.0" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="473.1" cy="1149.2" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="495.5" cy="1400.6" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="517.9" cy="1171.7" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="540.2" cy="1405.2" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="562.6" cy="1162.2" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="585.0" cy="1416.5" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="607.4" cy="1375.5" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="629.8" cy="1415.7" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="652.2" cy="1162.0" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="674.6" cy="1415.1" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<circle cx="697.0" cy="1075.1" r="1.6" fill="#7f7f7f" opacity="0.25"/>
<polyline points="70.0,1286.6 92.4,1276.3 137.2,1276.6 159.6,1200.1 204.4,1208.1 226.8,1385.3 249.1,1264.9 293.9,1289.2 316.3,1279.0 361.1,1149.2 383.5,1400.6 428.3,1171.7 450.7,1405.2 495.5,1162.2 517.9,1416.5 540.2,1375.5 585.0,1415.7 607.4,1162.0 652.2,1415.1 674.6,1075.1" fill="none" stroke="#2ca02c" stroke-width="3.5" opacity="1.0"/>
<text x="747" y="940" font-size="15" font-weight="bold">Max score per eval cycle</text>
<text x="747" y="955" font-size="11" fill="#555">campaign_v4_stdout.log - max of the 10 deterministic round scores per eval</text>
<line x1="747" y1="1428.0" x2="1375" y2="1428.0" stroke="#dddddd"/> <line x1="747" y1="1428.0" x2="1375" y2="1428.0" stroke="#dddddd"/>
<line x1="747" y1="1310.5" x2="1375" y2="1310.5" stroke="#dddddd"/> <line x1="747" y1="1310.5" x2="1375" y2="1310.5" stroke="#dddddd"/>
<line x1="747" y1="1193.0" x2="1375" y2="1193.0" stroke="#dddddd"/> <line x1="747" y1="1193.0" x2="1375" y2="1193.0" stroke="#dddddd"/>
@@ -176,170 +250,108 @@
<line x1="747" y1="958.0" x2="1375" y2="958.0" stroke="#dddddd"/> <line x1="747" y1="958.0" x2="1375" y2="958.0" stroke="#dddddd"/>
<line x1="747" y1="1428" x2="1375" y2="1428" stroke="black"/> <line x1="747" y1="1428" x2="1375" y2="1428" stroke="black"/>
<line x1="747" y1="1428" x2="747" y2="958" stroke="black"/> <line x1="747" y1="1428" x2="747" y2="958" stroke="black"/>
<line x1="773.2" y1="1428" x2="773.2" y2="1432" stroke="black"/> <line x1="747.0" y1="1428" x2="747.0" y2="1432" stroke="black"/>
<text x="773.2" y="1445" text-anchor="middle" font-size="11">2</text> <text x="747.0" y="1445" text-anchor="middle" font-size="11">1</text>
<line x1="825.5" y1="1428" x2="825.5" y2="1432" stroke="black"/> <line x1="795.3" y1="1428" x2="795.3" y2="1432" stroke="black"/>
<text x="825.5" y="1445" text-anchor="middle" font-size="11">4</text> <text x="795.3" y="1445" text-anchor="middle" font-size="11">2</text>
<line x1="877.8" y1="1428" x2="877.8" y2="1432" stroke="black"/> <line x1="843.6" y1="1428" x2="843.6" y2="1432" stroke="black"/>
<text x="877.8" y="1445" text-anchor="middle" font-size="11">6</text> <text x="843.6" y="1445" text-anchor="middle" font-size="11">3</text>
<line x1="930.2" y1="1428" x2="930.2" y2="1432" stroke="black"/> <line x1="891.9" y1="1428" x2="891.9" y2="1432" stroke="black"/>
<text x="930.2" y="1445" text-anchor="middle" font-size="11">8</text> <text x="891.9" y="1445" text-anchor="middle" font-size="11">4</text>
<line x1="982.5" y1="1428" x2="982.5" y2="1432" stroke="black"/> <line x1="940.2" y1="1428" x2="940.2" y2="1432" stroke="black"/>
<text x="982.5" y="1445" text-anchor="middle" font-size="11">10</text> <text x="940.2" y="1445" text-anchor="middle" font-size="11">5</text>
<line x1="1034.8" y1="1428" x2="1034.8" y2="1432" stroke="black"/> <line x1="988.5" y1="1428" x2="988.5" y2="1432" stroke="black"/>
<text x="1034.8" y="1445" text-anchor="middle" font-size="11">12</text> <text x="988.5" y="1445" text-anchor="middle" font-size="11">6</text>
<line x1="1087.2" y1="1428" x2="1087.2" y2="1432" stroke="black"/> <line x1="1036.8" y1="1428" x2="1036.8" y2="1432" stroke="black"/>
<text x="1087.2" y="1445" text-anchor="middle" font-size="11">14</text> <text x="1036.8" y="1445" text-anchor="middle" font-size="11">7</text>
<line x1="1139.5" y1="1428" x2="1139.5" y2="1432" stroke="black"/> <line x1="1085.2" y1="1428" x2="1085.2" y2="1432" stroke="black"/>
<text x="1139.5" y="1445" text-anchor="middle" font-size="11">16</text> <text x="1085.2" y="1445" text-anchor="middle" font-size="11">8</text>
<line x1="1191.8" y1="1428" x2="1191.8" y2="1432" stroke="black"/> <line x1="1133.5" y1="1428" x2="1133.5" y2="1432" stroke="black"/>
<text x="1191.8" y="1445" text-anchor="middle" font-size="11">18</text> <text x="1133.5" y="1445" text-anchor="middle" font-size="11">9</text>
<line x1="1244.2" y1="1428" x2="1244.2" y2="1432" stroke="black"/> <line x1="1181.8" y1="1428" x2="1181.8" y2="1432" stroke="black"/>
<text x="1244.2" y="1445" text-anchor="middle" font-size="11">20</text> <text x="1181.8" y="1445" text-anchor="middle" font-size="11">10</text>
<line x1="1296.5" y1="1428" x2="1296.5" y2="1432" stroke="black"/> <line x1="1230.1" y1="1428" x2="1230.1" y2="1432" stroke="black"/>
<text x="1296.5" y="1445" text-anchor="middle" font-size="11">22</text> <text x="1230.1" y="1445" text-anchor="middle" font-size="11">11</text>
<line x1="1348.8" y1="1428" x2="1348.8" y2="1432" stroke="black"/> <line x1="1278.4" y1="1428" x2="1278.4" y2="1432" stroke="black"/>
<text x="1348.8" y="1445" text-anchor="middle" font-size="11">24</text> <text x="1278.4" y="1445" text-anchor="middle" font-size="11">12</text>
<line x1="1326.7" y1="1428" x2="1326.7" y2="1432" stroke="black"/>
<text x="1326.7" y="1445" text-anchor="middle" font-size="11">13</text>
<line x1="1375.0" y1="1428" x2="1375.0" y2="1432" stroke="black"/>
<text x="1375.0" y="1445" text-anchor="middle" font-size="11">14</text>
<line x1="743" y1="1428.0" x2="747" y2="1428.0" stroke="black"/> <line x1="743" y1="1428.0" x2="747" y2="1428.0" stroke="black"/>
<text x="740" y="1432.0" text-anchor="end" font-size="11">0</text> <text x="740" y="1432.0" text-anchor="end" font-size="11">0</text>
<line x1="743" y1="1310.5" x2="747" y2="1310.5" stroke="black"/> <line x1="743" y1="1310.5" x2="747" y2="1310.5" stroke="black"/>
<text x="740" y="1314.5" text-anchor="end" font-size="11">1653</text> <text x="740" y="1314.5" text-anchor="end" font-size="11">52</text>
<line x1="743" y1="1193.0" x2="747" y2="1193.0" stroke="black"/> <line x1="743" y1="1193.0" x2="747" y2="1193.0" stroke="black"/>
<text x="740" y="1197.0" text-anchor="end" font-size="11">3305</text> <text x="740" y="1197.0" text-anchor="end" font-size="11">103</text>
<line x1="743" y1="1075.5" x2="747" y2="1075.5" stroke="black"/> <line x1="743" y1="1075.5" x2="747" y2="1075.5" stroke="black"/>
<text x="740" y="1079.5" text-anchor="end" font-size="11">4958</text> <text x="740" y="1079.5" text-anchor="end" font-size="11">155</text>
<line x1="743" y1="958.0" x2="747" y2="958.0" stroke="black"/> <line x1="743" y1="958.0" x2="747" y2="958.0" stroke="black"/>
<text x="740" y="962.0" text-anchor="end" font-size="11">6611</text> <text x="740" y="962.0" text-anchor="end" font-size="11">207</text>
<text x="1061" y="1461" text-anchor="middle" font-size="12">chunk interval (10-game chunks)</text> <text x="1061" y="1461" text-anchor="middle" font-size="12">eval cycle number</text>
<text x="16" y="1193" text-anchor="middle" font-size="12" transform="rotate(-90 16 1193)">games / hour</text> <text x="16" y="1193" text-anchor="middle" font-size="12" transform="rotate(-90 16 1193)">best single-round score</text>
<circle cx="747.0" cy="1159.8" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="747.0" cy="1259.8" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="773.2" cy="1413.4" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="795.3" cy="1200.7" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="799.3" cy="1148.0" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="843.6" cy="1359.8" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="825.5" cy="1404.7" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="891.9" cy="1396.2" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="851.7" cy="1153.6" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="940.2" cy="1398.5" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="877.8" cy="1399.6" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="988.5" cy="1357.5" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="904.0" cy="1000.7" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1036.8" cy="1391.6" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="930.2" cy="1399.5" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1085.2" cy="1357.5" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="956.3" cy="1021.4" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1133.5" cy="1391.6" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="982.5" cy="1394.8" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1181.8" cy="1378.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="1008.7" cy="1376.2" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1230.1" cy="1362.1" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="1034.8" cy="1394.4" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1278.4" cy="1278.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="1061.0" cy="1130.1" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1326.7" cy="1291.6" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="1087.2" cy="1399.7" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1375.0" cy="1425.7" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="1113.3" cy="1176.5" r="1.6" fill="#7f7f7f" opacity="0.25"/> <polyline points="747.0,1259.8 795.3,1200.7 843.6,1359.8 891.9,1396.2 940.2,1398.5 988.5,1357.5 1036.8,1391.6 1085.2,1357.5 1133.5,1391.6 1181.8,1378.0 1230.1,1362.1 1278.4,1278.0 1326.7,1291.6 1375.0,1425.7" fill="none" stroke="#d62728" stroke-width="2.5" opacity="1.0"/>
<circle cx="1139.5" cy="1402.0" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="747.0" cy="1403.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="1165.7" cy="1158.0" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="795.3" cy="1407.5" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="1191.8" cy="1400.0" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="843.6" cy="1378.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="1218.0" cy="1149.2" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="891.9" cy="1364.4" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="1244.2" cy="1400.6" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="940.2" cy="1373.5" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="1270.3" cy="1171.7" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="988.5" cy="1284.8" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="1296.5" cy="1405.2" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1036.8" cy="1330.3" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="1322.7" cy="1162.2" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1085.2" cy="1318.9" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="1348.8" cy="1416.5" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1133.5" cy="1325.7" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="1375.0" cy="1375.5" r="1.6" fill="#7f7f7f" opacity="0.25"/> <circle cx="1181.8" cy="1155.3" r="2" fill="#1f77b4" opacity="0.25"/>
<polyline points="747.0,1286.6 773.2,1276.3 799.3,1276.6 825.5,1200.1 877.8,1208.1 904.0,1376.2 930.2,1394.4 956.3,1130.1 1008.7,1399.7 1034.8,1176.5 1061.0,1402.0 1087.2,1158.0 1139.5,1400.0 1165.7,1149.2 1191.8,1400.6 1218.0,1171.7 1270.3,1405.2 1296.5,1162.2 1322.7,1416.5 1348.8,1375.5" fill="none" stroke="#2ca02c" stroke-width="3.5" opacity="1.0"/> <circle cx="1230.1" cy="1359.8" r="2" fill="#1f77b4" opacity="0.25"/>
<text x="70" y="1648" font-size="15" font-weight="bold">Max score per eval cycle</text> <circle cx="1278.4" cy="1268.9" r="2" fill="#1f77b4" opacity="0.25"/>
<text x="70" y="1663" font-size="11" fill="#555">campaign_v4_stdout.log - max of the 10 deterministic round scores per eval</text> <circle cx="1326.7" cy="1271.2" r="2" fill="#1f77b4" opacity="0.25"/>
<line x1="70" y1="2270.0" x2="697" y2="2270.0" stroke="#dddddd"/> <circle cx="1375.0" cy="1273.5" r="2" fill="#1f77b4" opacity="0.25"/>
<line x1="70" y1="2119.0" x2="697" y2="2119.0" stroke="#dddddd"/> <polyline points="747.0,1403.0 795.3,1407.5 843.6,1378.0 891.9,1364.4 940.2,1373.5 988.5,1284.8 1036.8,1330.3 1085.2,1318.9 1133.5,1325.7 1181.8,1155.3 1230.1,1359.8 1278.4,1268.9 1326.7,1271.2 1375.0,1273.5" fill="none" stroke="#1f77b4" stroke-width="2.5" opacity="1.0"/>
<line x1="70" y1="1968.0" x2="697" y2="1968.0" stroke="#dddddd"/> <circle cx="747.0" cy="1218.9" r="2" fill="#2ca02c" opacity="0.25"/>
<line x1="70" y1="1817.0" x2="697" y2="1817.0" stroke="#dddddd"/> <circle cx="795.3" cy="1223.5" r="2" fill="#2ca02c" opacity="0.25"/>
<line x1="70" y1="1666.0" x2="697" y2="1666.0" stroke="#dddddd"/> <circle cx="843.6" cy="1218.9" r="2" fill="#2ca02c" opacity="0.25"/>
<line x1="70" y1="2270" x2="697" y2="2270" stroke="black"/> <circle cx="891.9" cy="1348.5" r="2" fill="#2ca02c" opacity="0.25"/>
<line x1="70" y1="2270" x2="70" y2="1666" stroke="black"/> <circle cx="940.2" cy="1400.7" r="2" fill="#2ca02c" opacity="0.25"/>
<line x1="70.0" y1="2270" x2="70.0" y2="2274" stroke="black"/> <circle cx="988.5" cy="1359.8" r="2" fill="#2ca02c" opacity="0.25"/>
<text x="70.0" y="2287" text-anchor="middle" font-size="11">1</text> <circle cx="1036.8" cy="1000.7" r="2" fill="#2ca02c" opacity="0.25"/>
<line x1="127.0" y1="2270" x2="127.0" y2="2274" stroke="black"/> <circle cx="1085.2" cy="1355.3" r="2" fill="#2ca02c" opacity="0.25"/>
<text x="127.0" y="2287" text-anchor="middle" font-size="11">2</text> <circle cx="1133.5" cy="1368.9" r="2" fill="#2ca02c" opacity="0.25"/>
<line x1="184.0" y1="2270" x2="184.0" y2="2274" stroke="black"/> <circle cx="1181.8" cy="1278.0" r="2" fill="#2ca02c" opacity="0.25"/>
<text x="184.0" y="2287" text-anchor="middle" font-size="11">3</text> <circle cx="1230.1" cy="1307.5" r="2" fill="#2ca02c" opacity="0.25"/>
<line x1="241.0" y1="2270" x2="241.0" y2="2274" stroke="black"/> <circle cx="1278.4" cy="1309.8" r="2" fill="#2ca02c" opacity="0.25"/>
<text x="241.0" y="2287" text-anchor="middle" font-size="11">4</text> <circle cx="1326.7" cy="1291.6" r="2" fill="#2ca02c" opacity="0.25"/>
<line x1="298.0" y1="2270" x2="298.0" y2="2274" stroke="black"/> <circle cx="1375.0" cy="1198.5" r="2" fill="#2ca02c" opacity="0.25"/>
<text x="298.0" y="2287" text-anchor="middle" font-size="11">5</text> <polyline points="747.0,1218.9 795.3,1223.5 843.6,1218.9 891.9,1348.5 940.2,1400.7 988.5,1359.8 1036.8,1000.7 1085.2,1355.3 1133.5,1368.9 1181.8,1278.0 1230.1,1307.5 1278.4,1309.8 1326.7,1291.6 1375.0,1198.5" fill="none" stroke="#2ca02c" stroke-width="2.5" opacity="1.0"/>
<line x1="355.0" y1="2270" x2="355.0" y2="2274" stroke="black"/> <polyline points="747.0,1218.9 795.3,1200.7 843.6,1218.9 891.9,1348.5 940.2,1373.5 988.5,1284.8 1036.8,1000.7 1085.2,1318.9 1133.5,1325.7 1181.8,1155.3 1230.1,1307.5 1278.4,1268.9 1326.7,1271.2 1375.0,1198.5" fill="none" stroke="#555555" stroke-width="2.5" opacity="1.0" stroke-dasharray="6 4"/>
<text x="355.0" y="2287" text-anchor="middle" font-size="11">6</text> <line x1="759" y1="1480" x2="787" y2="1480" stroke="#d62728" stroke-width="3"/>
<line x1="412.0" y1="2270" x2="412.0" y2="2274" stroke="black"/> <text x="793" y="1484" font-size="12">Corners - 14 evals</text>
<text x="412.0" y="2287" text-anchor="middle" font-size="11">7</text> <line x1="759" y1="1498" x2="787" y2="1498" stroke="#1f77b4" stroke-width="3"/>
<line x1="469.0" y1="2270" x2="469.0" y2="2274" stroke="black"/> <text x="793" y="1502" font-size="12">Crazy - 14 evals</text>
<text x="469.0" y="2287" text-anchor="middle" font-size="11">8</text> <line x1="759" y1="1516" x2="787" y2="1516" stroke="#2ca02c" stroke-width="3"/>
<line x1="526.0" y1="2270" x2="526.0" y2="2274" stroke="black"/> <text x="793" y="1520" font-size="12">Target - 14 evals</text>
<text x="526.0" y="2287" text-anchor="middle" font-size="11">9</text> <line x1="759" y1="1534" x2="787" y2="1534" stroke="#555555" stroke-width="3"/>
<line x1="583.0" y1="2270" x2="583.0" y2="2274" stroke="black"/> <text x="793" y="1538" font-size="12">combined max</text>
<text x="583.0" y="2287" text-anchor="middle" font-size="11">10</text> <rect x="0" y="1540" width="1400" height="180" fill="#f2f2f2"/>
<line x1="640.0" y1="2270" x2="640.0" y2="2274" stroke="black"/> <text x="16" y="1561" font-size="15" font-weight="bold">How to read</text>
<text x="640.0" y="2287" text-anchor="middle" font-size="11">11</text> <text x="1384" y="1560" text-anchor="end" font-size="11" fill="#666">Regenerate anytime: python3 tools/plot_progress.py</text>
<line x1="697.0" y1="2270" x2="697.0" y2="2274" stroke="black"/> <text x="16" y="1583" font-size="13">Test matches: dots are single fights, thick line shows trend.</text>
<text x="697.0" y="2287" text-anchor="middle" font-size="11">12</text> <text x="16" y="1600" font-size="13">Loss spikes are normal early; endless growth is bad.</text>
<line x1="66" y1="2270.0" x2="70" y2="2270.0" stroke="black"/> <text x="16" y="1617" font-size="13">Throughput flat is healthy; dips mean something slowed.</text>
<text x="63" y="2274.0" text-anchor="end" font-size="11">0</text> <text x="16" y="1634" font-size="13">Max score: best single-round score the bot managed in that eval cycle.</text>
<line x1="66" y1="2119.0" x2="70" y2="2119.0" stroke="black"/> <text x="16" y="1651" font-size="13">This file reloads itself in Chrome every sixty seconds.</text>
<text x="63" y="2123.0" text-anchor="end" font-size="11">52</text> <text x="16" y="1668" font-size="13">Regenerate anytime with tools/watch_dashboard.sh or the python command.</text>
<line x1="66" y1="1968.0" x2="70" y2="1968.0" stroke="black"/>
<text x="63" y="1972.0" text-anchor="end" font-size="11">103</text>
<line x1="66" y1="1817.0" x2="70" y2="1817.0" stroke="black"/>
<text x="63" y="1821.0" text-anchor="end" font-size="11">155</text>
<line x1="66" y1="1666.0" x2="70" y2="1666.0" stroke="black"/>
<text x="63" y="1670.0" text-anchor="end" font-size="11">207</text>
<text x="383" y="2303" text-anchor="middle" font-size="12">eval cycle number</text>
<text x="16" y="1968" text-anchor="middle" font-size="12" transform="rotate(-90 16 1968)">best single-round score</text>
<circle cx="70.0" cy="2053.9" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="127.0" cy="1977.9" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="184.0" cy="2182.4" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="241.0" cy="2229.1" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="298.0" cy="2232.0" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="355.0" cy="2179.5" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="412.0" cy="2223.3" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="469.0" cy="2179.5" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="526.0" cy="2223.3" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="583.0" cy="2205.7" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="640.0" cy="2185.3" r="2" fill="#d62728" opacity="0.25"/>
<circle cx="697.0" cy="2077.2" r="2" fill="#d62728" opacity="0.25"/>
<polyline points="70.0,2053.9 127.0,1977.9 184.0,2182.4 241.0,2229.1 298.0,2232.0 355.0,2179.5 412.0,2223.3 469.0,2179.5 526.0,2223.3 583.0,2205.7 640.0,2185.3 697.0,2077.2" fill="none" stroke="#d62728" stroke-width="2.5" opacity="1.0"/>
<circle cx="70.0" cy="2237.9" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="127.0" cy="2243.7" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="184.0" cy="2205.7" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="241.0" cy="2188.2" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="298.0" cy="2199.9" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="355.0" cy="2086.0" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="412.0" cy="2144.4" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="469.0" cy="2129.8" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="526.0" cy="2138.6" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="583.0" cy="1919.5" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="640.0" cy="2182.4" r="2" fill="#1f77b4" opacity="0.25"/>
<circle cx="697.0" cy="2065.6" r="2" fill="#1f77b4" opacity="0.25"/>
<polyline points="70.0,2237.9 127.0,2243.7 184.0,2205.7 241.0,2188.2 298.0,2199.9 355.0,2086.0 412.0,2144.4 469.0,2129.8 526.0,2138.6 583.0,1919.5 640.0,2182.4 697.0,2065.6" fill="none" stroke="#1f77b4" stroke-width="2.5" opacity="1.0"/>
<circle cx="70.0" cy="2001.3" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="127.0" cy="2007.1" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="184.0" cy="2001.3" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="241.0" cy="2167.8" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="298.0" cy="2235.0" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="355.0" cy="2182.4" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="412.0" cy="1720.9" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="469.0" cy="2176.5" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="526.0" cy="2194.1" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="583.0" cy="2077.2" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="640.0" cy="2115.2" r="2" fill="#2ca02c" opacity="0.25"/>
<circle cx="697.0" cy="2118.1" r="2" fill="#2ca02c" opacity="0.25"/>
<polyline points="70.0,2001.3 127.0,2007.1 184.0,2001.3 241.0,2167.8 298.0,2235.0 355.0,2182.4 412.0,1720.9 469.0,2176.5 526.0,2194.1 583.0,2077.2 640.0,2115.2 697.0,2118.1" fill="none" stroke="#2ca02c" stroke-width="2.5" opacity="1.0"/>
<polyline points="70.0,2001.3 127.0,1977.9 184.0,2001.3 241.0,2167.8 298.0,2199.9 355.0,2086.0 412.0,1720.9 469.0,2129.8 526.0,2138.6 583.0,1919.5 640.0,2115.2 697.0,2065.6" fill="none" stroke="#555555" stroke-width="2.5" opacity="1.0" stroke-dasharray="6 4"/>
<line x1="82" y1="2322" x2="110" y2="2322" stroke="#d62728" stroke-width="3"/>
<text x="116" y="2326" font-size="12">Corners - 12 evals</text>
<line x1="82" y1="2340" x2="110" y2="2340" stroke="#1f77b4" stroke-width="3"/>
<text x="116" y="2344" font-size="12">Crazy - 12 evals</text>
<line x1="82" y1="2358" x2="110" y2="2358" stroke="#2ca02c" stroke-width="3"/>
<text x="116" y="2362" font-size="12">Target - 12 evals</text>
<line x1="82" y1="2376" x2="110" y2="2376" stroke="#555555" stroke-width="3"/>
<text x="116" y="2380" font-size="12">combined max</text>
<rect x="0" y="2340" width="1400" height="180" fill="#f2f2f2"/>
<text x="16" y="2361" font-size="15" font-weight="bold">How to read</text>
<text x="1384" y="2360" text-anchor="end" font-size="11" fill="#666">Regenerate anytime: python3 tools/plot_progress.py</text>
<text x="16" y="2383" font-size="13">Test matches: dots are single fights, thick line shows trend.</text>
<text x="16" y="2400" font-size="13">Loss spikes are normal early; endless growth is bad.</text>
<text x="16" y="2417" font-size="13">Alpha high means experimenting; falling too fast freezes habits.</text>
<text x="16" y="2434" font-size="13">Throughput flat is healthy; dips mean something slowed.</text>
<text x="16" y="2451" font-size="13">Max score: best single-round score the bot managed in that eval cycle.</text>
<text x="16" y="2468" font-size="13">This file reloads itself in Chrome every sixty seconds.</text>
<text x="16" y="2485" font-size="13">Regenerate anytime with tools/watch_dashboard.sh or the python command.</text>
<script type="text/javascript"><![CDATA[ setTimeout(function(){ location.reload(); }, 60000); ]]></script> <script type="text/javascript"><![CDATA[ setTimeout(function(){ location.reload(); }, 60000); ]]></script>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

+47 -54
View File
@@ -3,17 +3,17 @@
Pure-stdlib SVG output (matplotlib not available on this box). Pure-stdlib SVG output (matplotlib not available on this box).
Generates ONE file: Generates ONE file:
docs/campaign_dashboard.svg - five panels, current (v2) run only: docs/campaign_dashboard.svg - four panels, current (v2) run only:
1. test-match win % vs opponents (campaign_v4_stdout.log eval lines) 1. test-match win % vs opponents (campaign_v4_stdout.log eval lines)
2. critic_loss / |actor_loss| (training_metrics.jsonl, shared log-y) 2. critic_loss / |actor_loss| / alpha (training_metrics.jsonl; losses log
3. alpha temperature (training_metrics.jsonl, linear) left axis, alpha linear right axis)
4. throughput, games/hour buckets (training_metrics.jsonl 'epoch' deltas; 3. throughput, games/hour buckets (training_metrics.jsonl 'epoch' deltas;
1 metrics row == one 10-game chunk, 1 metrics row == one 10-game chunk,
counts match stdout chunk markers) counts match stdout chunk markers)
5. max score per eval cycle (campaign_v4_stdout.log eval blocks; 4. max score per eval cycle (campaign_v4_stdout.log eval blocks;
eval_log.jsonl only ever holds the eval_log.jsonl only ever holds the
LATEST cycle, so history comes from LATEST cycle, so history comes from
the stdout log) the stdout log)
plus an embedded JS snippet that reloads the page every 60 s when the SVG is plus an embedded JS snippet that reloads the page every 60 s when the SVG is
opened as a top-level document in Chrome. opened as a top-level document in Chrome.
@@ -42,10 +42,10 @@ GAMES_PER_ROW = 10 # one training_metrics.jsonl row per 10-round chunk
COLORS = {"Corners": "#d62728", "Crazy": "#1f77b4", "Target": "#2ca02c", COLORS = {"Corners": "#d62728", "Crazy": "#1f77b4", "Target": "#2ca02c",
"RamFire": "#ff7f0e", "SacTwin": "#9467bd"} "RamFire": "#ff7f0e", "SacTwin": "#9467bd"}
CRITIC_C, ACTOR_C = "#1f77b4", "#ff7f0e" CRITIC_C, ACTOR_C = "#1f77b4", "#ff7f0e"
ALPHA_C = "#9467bd" # same purple as the dedicated alpha panel ALPHA_C = "#9467bd" # alpha line on the losses panel
RELOAD_JS = ('<script type="text/javascript"><![CDATA[ ' RELOAD_JS = ('<script type="text/javascript"><![CDATA[ '
'setTimeout(function(){ location.reload(); }, 60000); ]]></script>') 'setTimeout(function(){ location.reload(); }, 60000); ]]></script>')
W, H = 1400, 2520 W, H = 1400, 1720
TITLE_H, GUIDE_H = 80, 180 TITLE_H, GUIDE_H = 80, 180
# rows: (header_y, panel_top_y, panel_bottom_y, x_left, x_right) # rows: (header_y, panel_top_y, panel_bottom_y, x_left, x_right)
C1_L, C1_R = 70, 697 C1_L, C1_R = 70, 697
@@ -55,19 +55,16 @@ ROWS = {
2: (100, 120, 720, C2_L, C2_R), 2: (100, 120, 720, C2_L, C2_R),
3: (940, 958, 1428, C1_L, C1_R), 3: (940, 958, 1428, C1_L, C1_R),
4: (940, 958, 1428, C2_L, C2_R), 4: (940, 958, 1428, C2_L, C2_R),
5: (1648, 1666, 2270, C1_L, C1_R), # third row, left column; right slot empty
} }
PANEL_TITLES = [ PANEL_TITLES = [
"Test matches - win % vs opponents", "Test matches - win % vs opponents",
"Training losses & alpha (log scale)", "Training losses (log) & alpha (linear)",
"Alpha temperature",
"Throughput - games per hour", "Throughput - games per hour",
"Max score per eval cycle", "Max score per eval cycle",
] ]
GUIDE_LINES = [ GUIDE_LINES = [
"Test matches: dots are single fights, thick line shows trend.", "Test matches: dots are single fights, thick line shows trend.",
"Loss spikes are normal early; endless growth is bad.", "Loss spikes are normal early; endless growth is bad.",
"Alpha high means experimenting; falling too fast freezes habits.",
"Throughput flat is healthy; dips mean something slowed.", "Throughput flat is healthy; dips mean something slowed.",
"Max score: best single-round score the bot managed in that eval cycle.", "Max score: best single-round score the bot managed in that eval cycle.",
"This file reloads itself in Chrome every sixty seconds.", "This file reloads itself in Chrome every sixty seconds.",
@@ -218,9 +215,9 @@ def dots(pts, color, r=2, opacity=0.25):
f'fill="{color}" opacity="{opacity}"/>\n' for x, y in pts) f'fill="{color}" opacity="{opacity}"/>\n' for x, y in pts)
def hgrid(x0, x1, ys): def hgrid(x0, x1, ys, color="#dddddd"):
return "".join(f'<line x1="{x0}" y1="{y:.1f}" x2="{x1}" y2="{y:.1f}" ' return "".join(f'<line x1="{x0}" y1="{y:.1f}" x2="{x1}" y2="{y:.1f}" '
f'stroke="#dddddd"/>\n' for y in ys) f'stroke="{color}"/>\n' for y in ys)
def axis(x0, y0, x1, y1, xt, yt, xlabel, ylabel, ylog=False): def axis(x0, y0, x1, y1, xt, yt, xlabel, ylabel, ylog=False):
@@ -368,45 +365,40 @@ def panel_losses(rows, geo):
s += f'<text x="{x0 + 10}" y="{pt + 40}" font-size="12" fill="#a00">' \ s += f'<text x="{x0 + 10}" y="{pt + 40}" font-size="12" fill="#a00">' \
"no valid loss points</text>\n" "no valid loss points</text>\n"
return return
allv = [v for _, v in critic + actor + alpha] x1 -= 46 # room on the right for the twin alpha axis labels
lo, hi = math.floor(math.log10(min(allv))), math.ceil(math.log10(max(allv)))
if lo == hi:
hi = lo + 1
n = len(rows) n = len(rows)
xm = lambda i: x0 + (x1 - x0) * i / max(n - 1, 1) xm = lambda i: x0 + (x1 - x0) * i / max(n - 1, 1)
base = critic + actor or alpha # log-domain source (losses in practice)
lo = math.floor(math.log10(min(v for _, v in base)))
hi = math.ceil(math.log10(max(v for _, v in base)))
if lo == hi:
hi = lo + 1
ym = map_fn(pb, pt, lo, hi, log=True) ym = map_fn(pb, pt, lo, hi, log=True)
s += hgrid(x0, x1, [ym(10 ** e) for e in range(lo, hi + 1)]) s += hgrid(x0, x1, [ym(10 ** e) for e in range(lo, hi + 1)])
s += axis(x0, pb, x1, pt, ticks_linear(1, n, x0, x1, n=5), s += axis(x0, pb, x1, pt, ticks_linear(1, n, x0, x1, n=5),
ticks_log(lo, hi, pb, pt), "metric line number", "loss (log)") ticks_log(lo, hi, pb, pt), "metric line number", "loss (log)")
s += polyline([(xm(i), ym(v)) for i, v in critic], CRITIC_C, 1.8) s += polyline([(xm(i), ym(v)) for i, v in critic], CRITIC_C, 1.8)
s += polyline([(xm(i), ym(v)) for i, v in actor], ACTOR_C, 1.8) s += polyline([(xm(i), ym(v)) for i, v in actor], ACTOR_C, 1.8)
s += polyline([(xm(i), ym(v)) for i, v in alpha], ALPHA_C, 1.8) if alpha: # twin axis: alpha on its own linear scale, purple like the line
ahi = max(1.0, max(v for _, v in alpha))
yma = map_fn(pb, pt, 0, ahi)
s += hgrid(x0, x1, [yma(ahi * k / 4) for k in range(5)], "#e9dcf5")
mid = (pt + pb) // 2
s += f'<line x1="{x1}" y1="{pb}" x2="{x1}" y2="{pt}" stroke="{ALPHA_C}"/>\n'
for v, py in ticks_linear(0, ahi, pb, pt, n=5, fmt="{:.3g}"):
s += (f'<line x1="{x1}" y1="{py:.1f}" x2="{x1 + 4}" y2="{py:.1f}" '
f'stroke="{ALPHA_C}"/>\n'
f'<text x="{x1 + 7}" y="{py + 4:.1f}" font-size="11" '
f'fill="{ALPHA_C}">{esc(v)}</text>\n')
s += (f'<text x="{x1 + 17}" y="{mid}" text-anchor="middle" font-size="12" '
f'fill="{ALPHA_C}" transform="rotate(90 {x1 + 17} {mid})">alpha</text>\n')
s += polyline([(xm(i), yma(v)) for i, v in alpha], ALPHA_C, 1.8)
items = [(CRITIC_C, "critic_loss"), (ACTOR_C, "|actor_loss|")] items = [(CRITIC_C, "critic_loss"), (ACTOR_C, "|actor_loss|")]
if alpha: if alpha:
items.append((ALPHA_C, "alpha")) items.append((ALPHA_C, "alpha"))
s += legend(items, x0 + 12, pb + 52) s += legend(items, x0 + 12, pb + 52)
return s return s
def panel_alpha(rows, geo):
_, pt, pb, x0, x1 = geo
s = ""
alpha = metric_col(rows, "alpha")
if not alpha:
s += f'<text x="{x0 + 10}" y="{pt + 40}" font-size="12" fill="#a00">' \
"no alpha points</text>\n"
return
n = len(rows)
hi = max(1.0, max(v for _, v in alpha))
xm = lambda i: x0 + (x1 - x0) * i / max(n - 1, 1)
ym = map_fn(pb, pt, 0, hi)
s += hgrid(x0, x1, [ym(v) for v in
[hi * k / 4 for k in range(5)]])
s += axis(x0, pb, x1, pt, ticks_linear(1, n, x0, x1, n=5),
ticks_linear(0, hi, pb, pt, n=5, fmt="{:.3g}"),
"metric line number", "alpha")
s += polyline([(xm(i), ym(v)) for i, v in alpha], "#9467bd", 1.8)
return s
def panel_throughput(rows, geo): def panel_throughput(rows, geo):
_, pt, pb, x0, x1 = geo _, pt, pb, x0, x1 = geo
s = "" s = ""
@@ -470,14 +462,11 @@ def build_dashboard(campaign, metrics_f, out):
"training_metrics.jsonl - big early spikes are normal", "training_metrics.jsonl - big early spikes are normal",
lambda: panel_losses(rows, ROWS[2])), lambda: panel_losses(rows, ROWS[2])),
(ROWS[3], PANEL_TITLES[2], (ROWS[3], PANEL_TITLES[2],
"training_metrics.jsonl - high = exploring, low = exploiting",
lambda: panel_alpha(rows, ROWS[3])),
(ROWS[4], PANEL_TITLES[3],
"method: training_metrics.jsonl 'epoch' deltas; 1 row = one 10-game chunk", "method: training_metrics.jsonl 'epoch' deltas; 1 row = one 10-game chunk",
lambda: panel_throughput(rows, ROWS[4])), lambda: panel_throughput(rows, ROWS[3])),
(ROWS[5], PANEL_TITLES[4], (ROWS[4], PANEL_TITLES[3],
"campaign_v4_stdout.log - max of the 10 deterministic round scores per eval", "campaign_v4_stdout.log - max of the 10 deterministic round scores per eval",
lambda: panel_max_score(maxes, ROWS[5])), lambda: panel_max_score(maxes, ROWS[4])),
] ]
for geo, title, sub, drawer in drawers: for geo, title, sub, drawer in drawers:
s += header(geo[3], geo[0], title, sub) s += header(geo[3], geo[0], title, sub)
@@ -540,14 +529,18 @@ def selftest():
assert esc(t) in text, f"panel title missing: {t}" assert esc(t) in text, f"panel title missing: {t}"
assert text.count(PANEL_TITLES[0]) == 1 assert text.count(PANEL_TITLES[0]) == 1
assert "How to read" in text, "reading guide missing" assert "How to read" in text, "reading guide missing"
assert 'width="1400"' in text and 'height="2520"' in text assert 'width="1400"' in text and 'height="1720"' in text
# circles: 4 eval dots (panel 1) + 2 throughput rate dots (panel 4) # circles: 4 eval dots (panel 1) + 2 throughput rate dots (panel 3)
# + 2 cycles x 2 opponents max-score dots (panel 5) # + 2 cycles x 2 opponents max-score dots (panel 4)
assert text.count("<circle") == 10, text.count("<circle") assert text.count("<circle") == 10, text.count("<circle")
# 2 trends + 3 losses-panel polylines (critic, actor, alpha) # 2 trends + 3 losses-panel polylines (critic, actor, alpha)
# + 1 dedicated alpha panel + 1 throughput # + 1 throughput
# + 3 max-score panel (Corners, Crazy, combined; Target absent in fixture) # + 3 max-score panel (Corners, Crazy, combined; Target absent in fixture)
assert text.count("<polyline") == 10, text.count("<polyline") assert text.count("<polyline") == 9, text.count("<polyline")
# losses panel twin axis: "alpha" text = legend + right ylabel; purple
# fills = 5 right-axis tick labels + rotated ylabel
assert text.count(">alpha<") == 2, text.count(">alpha<")
assert text.count('fill="#9467bd"') == 6, text.count('fill="#9467bd"')
assert "combined max" in text, "max-score combined line missing" assert "combined max" in text, "max-score combined line missing"
# orientation guard: a known rising series (10% -> 90%) rendered through # orientation guard: a known rising series (10% -> 90%) rendered through