The short version
Nightshift runs many attempts at a job across several local models, clusters and judges them, and records whether the result is good enough to keep. We ran the Mac campaign's harnesses, ported to Windows, against the installed app on a gaming PC with a 24 GB RTX 3090, in daily use.
On a 24 GB card, the catalog fleets that fit run in seconds. Twelve catalog fleets, three jobs each, three times over: 108 of 108 jobs completed, and 100 of 108 crowned winners were correct (93 %, against 87 % for a random attempt). The judge panel ran on every job. Eight of the twelve fleets keep every lane on the card at once. A median job took 3–33 s; the same fleets took 6–472 s on the 16 GB Mac, so the PC is 1.5–115× faster depending on whether the Mac had to rotate models.
It holds up for hours. A 3-hour back-to-back run completed 553 of 553 jobs (3 318 attempts, 0 errors) at 185, 188 and 180 jobs an hour, with the runtime's control channel answering every check and the lanes' memory flat from start to finish. The Mac's numeric release gates pass 7 of 7, with a median model switch of 3.3 s against a 7 s gate.
Heat and energy, measured. A heat brake at the card's own limit held the card at 76 °C under an 80 °C owner limit, and never engaged in normal work, up to 83 °C. GPU energy: about 0.3–0.4 Wh per resident best-of-4 job, about 1.3 Wh per best-of-6 job with 512-token answers.
What is weak. The judge: shown a correct answer, the 3B judge still crowns another in 19 of 42 jobs, and fleets with no capable judge end with unparseable panels. "Verified" for a generated app means statically valid: 10 of 12 apps were verified and 6 worked. Per-job synthesis needs room for an 8B curator; on a busy desktop most jobs went without it. And a PC's GPU is shared: other programs take VRAM, compute and memory, and Nightshift's plans shrink to match.
Every number names its raw folder. Failures, refusals and timeouts stay in the denominators.
At a glance
| Measure | Result | Source |
|---|---|---|
| Catalog-fleet sweep, 12 fleets × 3 jobs × 3 reps | 108/108 completed, 100/108 winners correct (Mac, same fleets: 31/36) | fleets/w5-r1..r3 |
| Same, crowned winner vs a random attempt | 93 % vs 87 % | §2.1 |
| Model switching in a job that rotates models (median) | 21 s | switch-audit.mjs |
| Judge panel shown a correct candidate (modes grid) | 42 of 45 jobs; crowned one in 23 | modes/grid-w5 |
| Bulk, 20 receipts × 9 jobs | 180/180 units, 179 correct, 3 300–12 600 units/h (Mac: 1 436–3 918) | modes/bulk-w5 |
| Auto (n = 256, as planned) | 521 s, winner wrong (Mac: 50.7 min, wrong) | modes/extras-w5 |
| Sustained run, 3 h | 553/553 jobs, 0 errors; median 20 s, max 46 s; no drift hour to hour | sustained/ |
| Restart with a backlog of queued work | /health answered 289 of 289 probes over 5 min; p95 104 ms | boot-b12.jsonl |
| Release gates (the Mac's numeric gates) | 7/7 pass; generation 115 tok/s; switch median 3.3 s | gates/gates-b12.json |
| Watcher and schedule | 3 changes → 3 fires, 0 false, 0 duplicates; schedule 9 of 9 | modes/watch-w6 |
| Quiet window and idle gate | quiet job started 22:00:28; idle-gated job waited for an idle box | modes/quietwin-w6 |
| Decode, Llama-3.2-1B / Llama-3.1-8B (CUDA) | 190–355 / 50–70 tok/s (Mac 1B: 120–144) | §2.10 |
| GPU energy per resident best-of-4 job | 0.32–0.35 Wh (about 290–320 J per attempt) | §2.13 |
| Heat brake, normal load / under an 80 °C owner limit | 0 engagements / held the card at 76 °C | §2.11 |
| JS suite / Rust tests on the final build | 4 385 pass, 0 fail, 27 skipped / 415 pass, 0 fail | §1 |
1. The machine and how it was measured
The machine. A desktop PC in daily use: AMD Ryzen 9 5900X (12 cores), 64 GB RAM, NVIDIA GeForce RTX 3090 24 GB (driver 560.94, 350 W, NVML slowdown temperature 95 °C), Windows 10 Pro 22H2. A browser, VS Code and several AI desktop apps were open throughout; the owner also ran a Whisper speech server (2 GB of VRAM) and, at times, a game emulator, a local bridge server and test runs. The models were on the internal NVMe drive (C:\NightshiftModels).
How Windows differs from the Mac and the DGX. The same product and code, with Windows behaviour behind cfg(windows). A discrete GPU has its own 24 GB of VRAM beside system RAM, so the planner packs fleets against the VRAM free right now (21.4 GB with the desktop open) and treats RAM only as spill. Commit charge, not swap pressure, is the hard memory limit. Lanes run CUDA on NVIDIA cards, Vulkan elsewhere.
What ran. The Mac campaign's harnesses, ported, against the installed app through its public API and control pipe:
| Suite | What it does |
|---|---|
| Catalog-fleet sweep | Every Mac-campaign catalog fleet whose models fit (12 of 19), best_of_n n = 4 on three prompts: code (merge_intervals, 7 hidden cases), fact (an 80-word explanation), extract (receipt → JSON) |
| Job-modes grid | 156 jobs over 52 cells × 3 reps on a controlled fleet (Phi-4-mini and Qwen2.5-Coder-3B racers, a Llama-3.2-3B judge lane) |
| Extras, bulk, watchers, resume | App generation checked in headless Chrome, repair, refine, synthesis, rerun and continue, Methods, Auto, holds, media; bulk over 20 receipts; a folder watcher and an interval schedule; a crash mid-chain |
| Quiet window | A quiet-window job and an idle-gated job submitted before 22:00 local |
| Substrate | Raw prefill and decode of every model with the bundled llama-bench |
| Sustained run, gates, restart | 3 hours of back-to-back best_of_n n = 6; the Mac's numeric release gates; a relaunch with queued work, /health probed every second |
| Heat, energy | The heat brake under load; board power, temperature and clock-event reasons from nvidia-smi every second through every job |
Scoring. "Winner correct" scores the attempt the product crowned, not the best one it had; "candidates correct" scores every attempt. The suites are small and on the easy side, as on the Mac: they measure whether the runtime delivers a fleet's ability, not how capable the models are.
Caveats. One PC, one card: a 12 GB or 8 GB card would rotate most of these fleets. A working desktop: substrate numbers move by a third from run to run. Licence opt-ins were left as the owner had them (the Liquid models are off, and lanes that pin them sit out of the race). Token rates are the product's estimates; energy is the GPU board only.
2. Results
2.1 Every catalog fleet that fits, three times over
12 catalog fleets × 3 jobs × 3 repetitions, best_of_n n = 4 (fleets/w5-r1..r3). The owner's Whisper server held 2 GB of VRAM throughout.
| Fleet | Completed | Winners correct | Candidates correct | Median s per job | Plan | GPU Wh per job | Mac: winners · s per job · plan | Faster than the Mac |
|---|---|---|---|---|---|---|---|---|
| starter-16 | 9/9 | 8/9 | 33/36 | 3.7 | concurrent | 0.26 | 2/3 · 12 s · concurrent | 3× |
| percept-lite | 9/9 | 9/9 | 32/36 | 9.1 | concurrent | 0.61 | 2/3 · 6 s · concurrent | — |
| asr-factory | 9/9 | 6/9 | 22/36 | 10.3 | concurrent | 0.80 | 1/3 · 30 s · concurrent | 3× |
| xfer-lite | 9/9 | 8/9 | 33/36 | 6.1 | concurrent | 0.41 | 2/3 · 9 s · concurrent | 1.5× |
| ext-lite | 9/9 | 7/9 | 30/36 | 3.3 | concurrent | 0.18 | 3/3 · 379 s · batched | 115× |
| agentcode-lite | 9/9 | 9/9 | 29/36 | 9.4 | concurrent | 0.74 | 3/3 · 400 s · batched | 43× |
| migrate-lite | 9/9 | 9/9 | 36/36 | 6.2 | concurrent | 0.41 | 3/3 · 141 s · batched | 23× |
| testgen-lite | 9/9 | 9/9 | 26/36 | 33.2 | batched | 2.38 | 3/3 · 444 s · batched | 13× |
| mdcode-lite | 9/9 | 9/9 | 36/36 | 6.2 | concurrent | 0.45 | 3/3 · 352 s · batched | 57× |
| ops-lite | 9/9 | 8/9 | 29/36 | 27.6 | batched | 2.40 | 3/3 · 472 s · batched | 17× |
| web-bulk-lite | 9/9 | 9/9 | 36/36 | 9.2 | batched | 0.60 | 3/3 · 401 s · batched | 44× |
| ext-core | 9/9 | 9/9 | 35/36 | 21.2 | batched | 1.32 | 3/3 · 84 s · batched | 4× |
| All | 108/108 | 100/108 (93 %) | 377/432 (87 %) | 1.04 mean | 31/36 (86 %) |
- Every job completed, and the judge panel ran on all 108. The crowned winner was correct 93 % of the time, against 87 % for a random attempt from the same jobs. Selection adds a little on an easy suite, as on the Mac (90 % vs 82 %).
- Eight of the twelve fleets race with every lane on the card at once. The Mac rotated four of those eight, so the gap is widest there (ext-lite 3.3 s against 379 s).
- Four fleets still rotate on 24 GB with the desktop open (testgen-lite, ops-lite, web-bulk-lite, ext-core). They finish in 9–33 s; the model switching inside a rotated job costs a median 21 s.
- Where both machines run concurrently (starter-16, percept-lite, xfer-lite, asr-factory), the PC is 1.5–3× faster: decode speed, not planning, is the difference.
- The 8 wrong winners: asr-factory 3, ext-lite 2, starter-16 1, xfer-lite 1, ops-lite 1. asr-factory seats only a 1B "thinking" router and a 3B reasoning verifier, neither of which can judge, so its panels came back unparseable.
- Every job record carries the fleet that was active when it ran (108 of 108).
2.2 Job modes on the controlled fleet (the grid)
The Mac's modes grid unchanged: 52 cells × 3 repetitions = 156 jobs, deterministic scorers (modes/grid-w5). The fleet is resident for every job on this card (155 of 156 plans concurrent).
| Mode | Windows | Mac |
|---|---|---|
| Verifier panel (default selector): correct winner when a correct candidate existed | 9 of 10 | 13 of 13 (plain best-of-4 cells) |
| … picked the best-scoring candidate | 18 of 24 | 20 of 24 |
| … the panel was shown a correct candidate (every panel job in the grid) | 42 of 45 | raw grid: 32 of 45 |
| … and crowned one | 23 of 45 | raw grid: 26 of 45 |
| Majority vote: correct when one existed | 9 of 11 | 9 of 12 |
| Unit-test selector | declined 6/6 (no candidate passed every case) | declined 6/6 |
| Tournament vs full coverage, wildcard (n = 8) | winners 2/3 vs 3/3 | 1/3 vs 0/3 |
| Quality judge, invoice | meets_bar 3/3; 0 attempts passed the hidden tests | meets_bar 12/12, 0/12 fully right |
| Quality judge, fact | 3/3 winners; 12 of 12 attempts correct | 12/12 |
| Consistency judge, planted / subtle contradictions | precision 0.71, recall 1.0 | precision 0.75, recall 1.0 |
| Creative judge (n = 8) | no single winner 6/6, spread wide | the same |
| Diversity, wildcard (default low / medium / high) | 1/3 · 0/3 · 0/3, at 2–3× the tokens | 2/3 · 0/3 · 0/3 |
| Deliberate, invoice | the delivering chunk every time (0.86, 0.86, 1.0) | fact 3/3 in 2.8–4.3 s |
| Batch with one bad request (9) | 8 landed, the bad one failed alone, 3/3 | 48/48 good requests landed |
| Deadline 45 s / 120 s (n = 16) | all 16 attempts in 16–18 s / 16–20 s | 39–43 s / 92–107 s |
| Stop when no new cluster (K = 2, n = 8) | stopped after 4 of 8 | 3–4 of 8 |
| Median best-of-4 job | 2–5 s | 21–53 s |
| GPU energy, 156 jobs | 76.4 Wh | not measured |
- The panel sees the right answer; the judge is the limit. Almost every job lands in one lexical cluster (74 of 84 panel jobs), and the panel shows the judge up to six distinct attempts across lanes. It was shown a correct candidate in 42 of the 45 jobs that had one; the 3B judge then picked another in 19 of those 42.
- Speed is the card, not the mode. Every mode ran in seconds, so deadlines of 45 s and 120 s were never the constraint.
- Weaknesses shared with the Mac: a quality rubric passes an invoice whose line items are wrong; the consistency judge flags some true answers (2 of 3 consistent prompts); more diversity costs tokens without improving the winner.
2.3 Makes, repair, synthesis, lineage and Auto
The Mac's extras steps on the modes fleet (modes/extras-w5), with a real headless Chrome for the app checks.
| Step | Windows | Mac |
|---|---|---|
| App generation → static → runtime | 12 attempts: 10 static-valid, 8 ran, 6 worked; 10 marked verified (static tier) | 12 static-valid, 11 ran, 8 worked; 12 verified |
| Gate repair, seeded syntax error | 3 of 3 repaired to static-valid; 2 of 3 then worked | 6 of 6 repaired |
| Gate repair, seeded missing click handler | passes the static gate unchanged, verified 3 of 3, works 0 of 3 | 7 of 7 verified, 0 working |
| Refine a seeded off-by-one | 6 of 6 fixed (5/7 → 7/7 hidden cases), 2–7 s each | — |
| Cluster reports, cut (no model) | 6 of 6 clusters, every section cited, about 50 ms each | — |
| Cluster reports with a bound curator | refused by name: the fleet's 8k-slot lane is below the 100k curator floor | ran with a bound curator |
| Rerun | code winner byte-identical 2/3 (identical words 3/3); fact correct 3/3; wildcard 2/3 correct where the original was wrong | code 3/3 identical; fact 3/3; wildcard 1/3 |
| Continue | the child is generation 2 with its lineage recorded; 14 s | — |
| Methods | a kept Method reused on a new creative prompt: 8 clusters in 16 s, 1 449 tokens with it; 2–3 clusters in 3–4 s without | with: 7 clusters in 42–48 s; without: 3 in 19–20 s |
| Auto, wildcard | planned n = 256, high diversity, a deadline of 07:00; ran as planned in 521 s, 81 532 tokens; winner wrong (20 of 256 right) | 50.7 min, 92 666 tokens, wrong (45 of 256) |
| Media autopilot (image) | no image weights on this PC: each make is retried 4 times (about 8 minutes) before failing | media transforms report available without models |
| Fail closed | consistency mode with no canon is refused (400); with an unindexed canon the job errors by name | the same |
| Holds | quiet-window and idle-gated jobs queue for 22:00 local; a start scheduled 90 s out began 0.26 s after its time | the same |
2.4 Bulk, pause and resume, and a crash mid-chain
| Run | Windows | Mac |
|---|---|---|
| Bulk, 20 receipts, 1, 2 and 4 units in flight × 3 repetitions | 180/180 units done, 179 correct; 5.7–22 s per 20-unit job (about 3 300–12 600 units an hour) | 200/200 done, 190/200 correct; 1 436–3 918 units an hour |
| Paused mid-run, resumed | paused with 7 done (2 in flight finished, 11 stayed queued); resumed to 20/20, all correct, no duplicates | paused with 6 done; 20/20, no duplicates |
| Convert every file (PDF; Markdown) | 20/20 units each | — |
A crash mid-chain. A deliberate chain was killed (the engine host process, taskkill /F) after its first chunk landed and before any checkpoint was written. The app restarted the engine host by itself and the chain restarted at chunk 1, the correct behaviour with no checkpoint to resume from, and completed. Forking from a chunk that was never written was refused by name, never guessed.
2.5 Watchers and schedules
A filesystem watcher on the 20-receipt folder (5-minute cadence, debounce of 2 stable observations) beside an interval schedule every 5 minutes, 46 minutes in all (modes/watch-w6):
| Minute | Change | Watcher | Mac |
|---|---|---|---|
| 11 | one receipt's total edited | fired at minute 20 (9.0 min: floor × debounce), 1 unit re-read | 9.3 min to fire |
| 21 | one file touched, bytes unchanged | no fire (correct) | no fire |
| 26 | five receipts edited within 60 s | one job covering all 5 units, no duplicates | one job |
| 36 | one receipt edited, then a manual check | fired at once, 1 unit | — |
3 real changes → 3 fires, 0 false fires, 0 duplicates. The interval schedule ran 9 of 9 times, 300–303 s apart; seven of its runs took 3.6–4.3 s, and the two that shared the GPU with another long run took 33 s and 233 s.
2.6 The quiet window and the idle gate
Two extraction jobs submitted at 21:04 local (modes/quietwin-w6), on a box that was busy with a long run:
| Job | Started | Mac (box idle) |
|---|---|---|
window: quiet (22:00–07:00) | 22:00:28, posture switched to Swarm; the 28 s were another job holding the slot; winner correct | 0.19 s after 22:00 |
start_gate: idle | 22:03:32, seconds after the box went idle; winner correct | 8 s later, when the box was free |
Both holds did what they say: the quiet job took the first free slot after 22:00, and the idle-gated job waited for an idle box, not merely for the window.
2.7 A 3-hour sustained run
best_of_n n = 6 jobs back to back on five rotating prompts (512-token answers), on ext-lite, with the runtime's status sampled every 30 s and the GPU every second (sustained/, 07:25–10:26Z):
| Measure | Value |
|---|---|
| Jobs completed | 553 of 553; 3 318 attempts, 0 attempt errors |
| Wall time per job (10 s polling) | median 20 s, p90 30 s, max 46 s |
| Jobs per hour, hour by hour | 185, 188, 180 |
| Plans | 551 concurrent, 2 batched |
| Status samples | 361, 0 errors; posture normal in 361 of 361 |
| Lane placements | 22, all fully on the GPU; 0 on the CPU |
| Lane memory (commit, all lanes) | 20.32 → 20.36 GB over 2.9 h |
| System commit | 59.9 → 67.7 GB of 80.8, the growth in other apps |
| GPU | 732.9 Wh; mean 242 W, max 351 W; max 83 °C; heat brake never engaged |
- No failure, stall or slowdown. Every job completed, the third hour ran at the rate of the first, and the status channel answered all 361 samples.
- Memory stayed put. The seven lanes held the same 20.3 GB of commit from the first sample to the last. When system commit crossed 85 % of its limit (other apps growing), the posture went to Reduce once, between two samples, and back to Normal within 15 healthy ticks; the 13 GB curator was refused a start for commit 34 times rather than pushed into a nearly full commit limit.
- Per-job synthesis needs a seat. Each job also queues a synthesis on an 8B curator. With the fleet holding the card and the desktop holding memory, the curator rarely got room: 133 of the 553 jobs got a finished synthesis. On the final build the queue stops at 16 nights waiting on one curator, and later nights record
curator_behind(a 1-hour run: the backlog held at 16 for 52 minutes and 200 nights recorded the reason). The jobs' winners never depend on it.
2.8 Restart with queued work
The app was relaunched with the owner's own lanes while 21 queued synthesis rows waited for a curator that was no longer configured, and /health was probed once a second for 5 minutes (boot-b12.jsonl). The API answered 289 of 289 probes after first contact at 9 s: p50 16 ms, p95 104 ms, p99 479 ms, worst 1.5 s. Its startup work ran meanwhile: the 17 orphaned makes failed by name, and 25 archived nights were indexed.
2.9 Release gates and quitting the app
The Mac's numeric release gates (tools/mac/release-gates.mjs --model extract, ext-lite's Llama-3.2-1B lane, gates/gates-b12.json), unchanged:
| Gate | Threshold | Windows |
|---|---|---|
| Control status p95 | 250 ms | 32 ms (p50 24) |
| API health p95 | 150 ms | 0 ms |
| Generation, 1B lane (wall, including the prompt) | ≥ 70 tok/s | 115.4 tok/s |
| API health under generation load, p95 | 400 ms | 5 ms |
| Model switch, median | ≤ 7 000 ms | 3 309 ms over 50 |
| Memory pressure | not critical | normal |
| Swap growth | ≤ 512 MB | 116 MB |
All 7 pass. Measured straight after a burst of jobs, the gates can fail: the engine host keeps working on the finished jobs (enrichment, consistency checks) for some minutes, and a run started then measured generation at 41.7 tok/s and health under load at 1 474 ms.
Quitting. With nothing running, closing the app window stops the background runtime with it: in two tries the app exited in 2 s, and the runtime logged its shutdown and was gone within the same 2 s, lanes and engine included. When a job is working, the runtime keeps going in the background and the app says so.
2.10 Substrate: what the card does with one model
llama-bench from the app's own llama.cpp build, the lane flags (flash attention, q8_0 KV cache), all layers on the GPU, 3 repetitions, with the starter-16 lanes resident but idle (substrate/).
| Model | Size | Prefill 512 tok/s | Prefill 4 096 tok/s | Decode tok/s |
|---|---|---|---|---|
| Llama-3.2-1B Q4_K_M | 0.8 GB | 11 238 | 13 914 | 190 |
| PaddleOCR-VL 1.6 | 0.9 GB | 5 938 | 21 158 | 199 |
| MiniCPM5-1B-thinking Q8_0 | 1.2 GB | 12 812 | 10 177 | 149 |
| Qwen2.5-Coder-3B Q4_K_M | 1.9 GB | 4 220 | 4 115 | 106 |
| VibeThinker-3B Q4_K_M | 1.9 GB | 4 244 | 4 842 | 96 |
| Llama-3.2-3B Q4_K_M | 2.0 GB | 4 268 | 6 616 | 181 |
| Phi-4-mini Q4_K_M | 2.5 GB | 3 993 | 3 709 | 84 |
| LFM2.5-VL-3B Q8_0 | 2.9 GB | 5 317 | 5 490 | 81 |
| Qwen2.5-Coder-7B Q4_K_M | 4.7 GB | 2 363 | 2 312 | 55 |
| Llama-3.1-8B Q4_K_M | 4.9 GB | 1 736 | 2 087 | 50 |
| LFM2.5-8B-A1B Q4_K_M (MoE, 1B active) | 5.2 GB | 5 124 | 5 438 | 150 |
- Working-desktop numbers: back-to-back runs of the 1B decoded at 233 and 355 tok/s, and of the 8B at 70 and 53. Read the table as magnitudes.
- Against the Mac: the M5 decodes the same Llama-3.2-1B at 120–144 tok/s. This card is about 1.5–2.5× faster on decode and an order of magnitude faster on prefill.
- Vulkan on the same card (the backend a PC without CUDA gets): about the same as CUDA on a 1B, but 2–3× slower on an 8B (decode 19–27 vs 53–70 tok/s) and 3–4× slower on prefill.
2.11 Heat
Windows ports the DGX's Hunyuan3D heat pacer as a brake at each card's own limit (NVML's slowdown threshold, 95 °C on this RTX 3090):
- it engages on a hardware slowdown that persists for two readings, or within 8 °C of the limit;
- while engaged, every path that hands the GPU new work waits; work in flight finishes, so no answer is cut off;
- it releases after at least 8 s and 3 readings in a row 15 °C or more under the limit; no request waits more than 300 s;
- an owner can lower the line for a small case or a laptop (
settings.json"heat": {"limit_c": N}), never raise it.
Run (12 back-to-back best_of_n n = 8 code jobs) | Brake engagements | GPU max | Mean board power | Jobs done | Energy |
|---|---|---|---|---|---|
| Owner limit 80 °C (below this card's working temperature) | 37 in 11.5 min | 76 °C | 155 W | 4 of 12 when stopped | — |
| No owner limit (the card's own 95 °C) | 0 | 82 °C | 294 W | 12 of 12 in 545 s | 44.6 Wh |
With a limit to enforce, the brake held the card under it and board power halved; work slowed, as it must. At the card's own limit it never engaged: 0 times in that run, and 0 times in the 3-hour run at up to 83 °C, where a single hardware-slowdown reading at 78 °C came and went without effect. In-flight work carries the temperature about 4 °C past the engage line, which at the real limit stays under the card's own 95 °C protection.
2.12 Disks
| Drive | Bus / media | Read (5 GB model, sequential) | A 5 GB cold load |
|---|---|---|---|
C: | NVMe SSD | 3 648 MB/s | ~1.4 s |
H: | USB SSD | 603 MB/s | ~8.5 s |
D: (the owner's models folder) | USB hard disk | 23 MB/s | ~3.8 min |
Every lane start and every rotation reads its model from disk; from a USB hard disk one switch of a 5 GB model costs about 4 minutes. The app warns at launch when the models folder is on a USB hard disk.
2.13 Energy
Board power sampled once a second through every job and integrated per job (GPU only, not the wall socket):
| Workload | Jobs | GPU energy | Per job |
|---|---|---|---|
| Modes grid | 156 | 76.4 Wh | best-of-4 median 0.32–0.35 Wh; about 290–320 J per attempt |
| Catalog sweep | 108 | 112.8 Wh | 0.18–2.40 Wh (median per fleet); 1.04 mean |
| Sustained run, n = 6, 512-token answers | 553 | 732.9 Wh | 1.33 Wh; about 800 J per attempt |
| Heat test, n = 8 code jobs, no limit | 12 | 44.6 Wh | 3.7 Wh |
- A resident best-of-4 job costs about a third of a watt-hour of GPU energy. At $0.15 per kWh, a thousand such jobs cost about 5 cents.
- Rotation costs energy as well as time: the rotating fleets used about 2.4 Wh per job against 0.2–0.8 Wh for resident ones, mostly loading and unloading models.
- Idle: with lanes resident and nothing running, the card settles at 37–66 W.
2.14 One PC, one Mac, one Spark
| Windows PC (RTX 3090 24 GB) | Apple M5, 16 GB | DGX Spark (GB10, 128 GB) | |
|---|---|---|---|
| Memory for models | 24 GB VRAM, packed against what is free right now (21.4 GB with the desktop open); RAM as spill | 16 GB unified; about 8.6 GB granted live | 128 GB unified; 106 GB allocatable |
| Typical resident fleet | five or six 1–8B lanes; 8 of 12 catalog fleets race fully resident | about 10 GB; most fleets rotate | three 27–32B lanes + embedder + media server |
| Decode, 1B / 8B | 190–355 / 50–70 tok/s | 120–144 tok/s on a 1B | 6.2–7.7 tok/s per 27–32B lane |
| Catalog-fleet best-of-4 (same 12 fleets) | 108/108 completed, 100/108 winners correct; 3–33 s per job | 36/36 completed, 31/36 correct; 6–472 s per job | not run on this suite |
| Model switching | about 21 s per rotated job | 5–18 s per switch; minutes per rotated job | rarely rotates |
| Heat | a brake at the card's own limit; never engaged in normal work | macOS thermal state into the memory posture | a pacer in the 3D server |
| Energy | about 0.3–0.4 Wh of GPU energy per resident best-of-4 job | not measured | not measured |
| Cloud spend | $0.00 | $0.00 | $0.00 |
A 24 GB gaming GPU is a very good Nightshift host for small and mid-sized fleets: it does in seconds what the 16 GB Mac does in minutes, because the whole fleet stays resident and decodes 1.5–2.5× faster. It cannot hold the 27–32B models that produce the Spark's best work, and on a PC the GPU is shared with whatever else the owner runs.
3. Strengths
- Throughput on a gaming card. Every catalog fleet that fits completes every job in seconds; 108 of 108 jobs, 93 % correct winners, the panel judging every one.
- It runs for hours without drifting. 553 of 553 jobs in 3 hours at a steady rate, lane memory flat to within 43 MB, every status sample answered.
- It adapts to a shared machine. Plans pack against the VRAM free right now; a model that would not fit beside the fleet waits rather than spilling onto the CPU; a model that would overrun the commit limit is refused by name.
- Honest refusals. Licence-gated models, a curator below its context floor, a fork from a missing checkpoint, consistency mode without a canon: each refused by name, never guessed.
- Bulk and makes at speed. 180 of 180 bulk units with one wrong field; refine fixed 6 of 6 seeded bugs; Auto's 256-attempt plan ran in under 9 minutes.
- Safe heat behaviour at no cost. A brake that held an owner-set line and never engaged in normal work.
- The release gates pass with margin, including the switch-time gate (3.3 s against 7 s).
- Installs keep the owner's state. Every install over the running app left lanes, fleets and keys byte-identical.
4. Weaknesses and limits
- The judge is the ceiling. Shown a correct candidate, the 3B judge crowns another in 19 of 42 grid jobs. Fleets that seat no capable judge (asr-factory, percept-lite: a 1B "thinking" router plus a reasoning or OCR model) end with unparseable panels.
- "Verified" is static. A generated app's
verifiedmeans it parses: 10 of 12 verified, 6 worked; a missing click handler passes 3 of 3 times. - Synthesis needs a seat. When the 8B curator cannot get room beside the fleet, most jobs go without their per-job synthesis (133 of 553 in the 3-hour run). The queue is bounded and each skipped night says why, but nothing seats the curator for them.
- A media make for weights that are not installed is retried four times over about 8 minutes before it fails.
- Rubric and canon judges still pass what they forget to check (a wrong line item) and flag some true answers (precision 0.71), as on the Mac.
- Work after a burst. After many jobs finish, the engine host stays busy with them for some minutes, and API latency rises while it does.
- Big models. 24 GB holds no 27–32B dense model beside anything else.
- The PC is shared. A game, an emulator or a large app takes VRAM, compute and commit; Nightshift adapts its plans but cannot reserve the card against the owner.
- The installer stops every
llama-server.exeon the PC, not only Nightshift's.
5. What the numbers say
- The Windows edition delivers a fleet's ability at the card's speed. With the fleet resident, a best-of-4 job is a few seconds of GPU work and a third of a watt-hour. Every catalog fleet that fits completed every job; the winners were as correct as the models allow.
- Residency decides speed. Fleets that fit on the card finish in 3–10 s; fleets that rotate models through it finish in 9–33 s, about 21 s of which is switching. A smaller card, or a busier desktop, moves more fleets into the second group.
- Selection, not generation, is the ceiling. The panel sees the right answer in 42 of 45 jobs that have one, and a 3B judge still picks another in 19 of them. Better judges, not more attempts, are the next gain; the Mac and the DGX reached the same conclusion.
- It is steady over hours. Three hours of back-to-back jobs ran at a constant rate with flat memory, and a restart with work still queued kept the API answering.
- A PC is a shared machine. The planner reads what is free right now, which kept every job alive while other programs came and went. What it cannot do is reserve the card against the owner, and it should not.
Sources and method notes
Raw data is on the bench PC under C:\NightshiftBench\; the harnesses are in nightshift-build/bench-win/. Each suite's final run:
| Folder | What | Build measured |
|---|---|---|
fleets/w5-r1..r3 | the catalog-fleet sweep, 12 fleets × 3 reps | 5 |
modes/grid-w5 | the job-modes grid | 5 |
modes/extras-w5, modes/bulk-w5, modes/resume-w5 | makes, repair, synthesis, lineage, Methods, Auto, holds, media; bulk; crash and resume | 5 |
modes/watch-w6, modes/quietwin-w6 | watcher and schedule; the quiet window and the idle gate | 6 |
substrate/ | llama-bench per model and backend | 4 |
heat/ | the heat-brake test | 2 |
sustained/ | the 3-hour run (jobs.jsonl, samples.jsonl, gpu.jsonl, commit.jsonl, analysis.json) | 10 |
sustained-b11/ | the 1-hour run with the bounded synthesis queue (synth-backlog.jsonl) | 11 |
boot-b12.jsonl, gates/gates-b12.json | restart with queued work; release gates | 12 |
CONFOUNDERS.log, logs/meterlessd.log | closing the app with nothing running | 13 |
analysis/ | every derived table (analyze-fleets.mjs, switch-audit.mjs, analyze_grid.py, analyze-energy.mjs, analyze-soak.mjs) | — |
CONFOUNDERS.log | every build, install, run and outside GPU tenant, with times | — |
All builds are Windows edition 1.2.1 from one source line, installed over the running app; the shipped build is 13 (setup sha256 4b7e858f…). Each suite's numbers come from its last run. The builds after it changed model rotation, memory accounting and startup behaviour, which the long runs exercised, so a repeat of an early suite on the shipped build could differ in detail (the campaign report records each change). Not measured here: the 7 catalog fleets that need 12–14B models; media renders (no image, video or music weights on this PC); a card smaller than 24 GB; a second PC; the wall-socket power of the whole machine.