[{"data":1,"prerenderedAt":735},["ShallowReactive",2],{"navigation":3,"\u002Fblog\u002Fblackwell-bakeoff":58,"posts":630,"blog-list-\u002Fblog\u002Fblackwell-bakeoff":710},[4],{"title":5,"path":6,"stem":7,"children":8,"page":57},"Blog","\u002Fblog","blog",[9,13,17,21,25,29,33,37,41,45,49,53],{"title":10,"path":11,"stem":12},"I Gave an AI Agent the Keys to Navisworks, and Five Trades of Takeoff Took Four Days","\u002Fblog\u002Fautomated-bim-takeoff","blog\u002Fautomated-bim-takeoff",{"title":14,"path":15,"stem":16},"I Benchmarked Nine Models to Spec a Four-GPU Node. Every Single Number Crowned the Wrong Winner.","\u002Fblog\u002Fblackwell-bakeoff","blog\u002Fblackwell-bakeoff",{"title":18,"path":19,"stem":20},"On an EPC Job, 'Sure, No Problem' Is the Most Expensive Sentence Onsite. An Agent Would Have Checked the Contract First.","\u002Fblog\u002Fconstruction-agents","blog\u002Fconstruction-agents",{"title":22,"path":23,"stem":24},"I Run AI Agents Around the Clock and My Best Productivity Tool This Year Has No Battery","\u002Fblog\u002Fde-digitizing","blog\u002Fde-digitizing",{"title":26,"path":27,"stem":28},"I Built a Bot Army to Attack My Own Game Server, and 45 of Them Took It Down","\u002Fblog\u002Fgame-server-scaling","blog\u002Fgame-server-scaling",{"title":30,"path":31,"stem":32},"I Chased Four Benchmark Points and Almost Missed the Model That's Twice as Fast","\u002Fblog\u002Flocal-ai-moe-vs-dense","blog\u002Flocal-ai-moe-vs-dense",{"title":34,"path":35,"stem":36},"I Spent $5K on GPUs Just to Learn That One GPU Was Enough","\u002Fblog\u002Flocal-ai-rig","blog\u002Flocal-ai-rig",{"title":38,"path":39,"stem":40},"I Billed Myself for 6.7 Billion Tokens and the Total Came Out to $35.85","\u002Fblog\u002Flocal-ai-true-cost","blog\u002Flocal-ai-true-cost",{"title":42,"path":43,"stem":44},"I Spent a Saturday Trying to Replace My Local AI to Save on Tokens. The Server Voted No.","\u002Fblog\u002Flocal-ai-upgrade","blog\u002Flocal-ai-upgrade",{"title":46,"path":47,"stem":48},"Building a Roguelike Game with Amazon Q","\u002Fblog\u002Fq-roguelike","blog\u002Fq-roguelike",{"title":50,"path":51,"stem":52},"I Spent 22 Years Programming Just to Fail at Making a Skeleton Swing a Sword","\u002Fblog\u002Fthundoria-architecture","blog\u002Fthundoria-architecture",{"title":54,"path":55,"stem":56},"Build First - Learn Later","\u002Fblog\u002Fvectly-scaling","blog\u002Fvectly-scaling",false,{"id":59,"title":14,"author":60,"body":61,"date":613,"description":614,"draft":57,"extension":615,"image":616,"imageHeight":617,"imageWidth":618,"meta":619,"navigation":620,"path":15,"seo":621,"seoTitle":622,"sitemap":623,"stem":16,"tags":625,"updated":628,"__hash__":629},"blog\u002Fblog\u002Fblackwell-bakeoff.md","Tony Costanzo",{"type":62,"value":63,"toc":600},"minimark",[64,69,97,101,105,108,111,114,117,121,124,127,130,133,153,156,163,166,174,178,181,184,308,311,314,317,321,324,334,340,400,407,417,420,424,427,430,433,436,452,455,458,464,475,478,481,487,490,494,497,502,505,511,514,521,524,528,531,534,574,577,581,584,587,594,597],[65,66,68],"h2",{"id":67},"links","Links",[70,71,72,79,84,89],"ul",{},[73,74,75],"li",{},[76,77,78],"a",{"href":35},"The original rig writeup",[73,80,81],{},[76,82,83],{"href":43},"The upgrade that the server voted down",[73,85,86],{},[76,87,88],{"href":39},"What this thing actually costs to run",[73,90,91],{},[76,92,96],{"href":93,"rel":94},"https:\u002F\u002Fgithub.com\u002FAider-AI\u002Faider\u002Ftree\u002Fmain\u002Fbenchmark",[95],"nofollow","The Aider polyglot benchmark",[65,98,100],{"id":99},"the-node-i-have-to-spec","The Node I Have to Spec",[102,103,104],"p",{},"There's a production deployment coming that I have to spec, and it's two to four of these cards.",[102,106,107],{},"I did not want to pick that hardware off a benchmark table.",[102,109,110],{},"Here's the problem with the tables. Every number you read on one is for BF16 weights, and I serve int4, sometimes int2, because that's what actually fits. A model sitting at 42 on some open-weight index is not that same model at a two-bit quant, and nobody publishes what the quantization did to it on the way down. You measure that yourself or you buy on vibes.",[102,112,113],{},"The second problem is worse. Those benchmarks measure the model. They don't measure the model doing my job.",[102,115,116],{},"So one card went on my bench first. Its entire job is to tell me what the real ones should be.",[65,118,120],{"id":119},"the-card-went-in-and-two-3090s-fell-out","The Card Went In and Two 3090s Fell Out",[102,122,123],{},"An RTX PRO 6000 Blackwell showed up and was in the server twenty minutes later, which is the fastest I have ever moved on anything involving a screwdriver.",[102,125,126],{},"96 GB on one card. Compute capability way up. Six hundred watts of \"please do not ask about the power bill.\" It replaced a Quadro P2000 that had been quietly doing autocomplete duty.",[102,128,129],{},"The rest of the box, because the new card does not live alone: four RTX 3090s, an EPYC 7532 with 128 GB of DDR4, and one GPU nobody was allowed to touch (the Zotac runs my embeddings and reranker around the clock, and I like being able to search my own notes).",[102,131,132],{},"First thing I did was move a model I already run onto it. Same model, same quant, off two 3090s in tensor-parallel and onto the one big card.",[70,134,135,142,148],{},[73,136,137,141],{},[138,139,140],"strong",{},"Decode up 40 to 56 percent"," at every context depth",[73,143,144,147],{},[138,145,146],{},"KV cache from 861,477 tokens to 3,174,512,"," which is 3.7 times the room",[73,149,150],{},[138,151,152],{},"Both Strix cards handed straight back to me",[102,154,155],{},"Under actual batching the gap got embarrassing:",[102,157,158],{},[159,160],"img",{"alt":161,"src":162},"Grouped bar chart comparing aggregate throughput on two RTX 3090s in tensor-parallel against one RTX PRO 6000 running the same Ornith-1.5-35B-A3B model: at 1 concurrent request 153.9 versus 200.0 tokens per second, at 8 concurrent 667.6 versus 1049.2, and at 32 concurrent 758.4 versus 2072.3, a 2.7 times gain","\u002Fimages\u002Fblog\u002Fblackwell-bakeoff\u002Fone-card-vs-two.svg",[102,164,165],{},"At 32 concurrent requests one card did 2,072 tokens per second against 758 for the pair, and time-to-first-token dropped from 11.76 seconds to 1.57.",[102,167,168,169,173],{},"That gap isn't mysterious. Tensor-parallel across two 3090s pays a PCIe all-reduce every single layer and there's no NVLink here to make that cheap. One large card never pays it. What matters for the node is that the gap ",[170,171,172],"em",{},"widens"," with exactly the load a real deployment produces, so line one of my notes was: scale with replicas, not tensor-parallel.",[65,175,177],{"id":176},"every-number-i-had-said-ornith","Every Number I Had Said Ornith",[102,179,180],{},"Then the boring question. What's fastest?",[102,182,183],{},"Single-stream decode in tokens per second, at roughly 2.4K, 38K and 151K prompt tokens. Median of three with a warmup call, thinking off, streamed.",[185,186,187,206],"table",{},[188,189,190],"thead",{},[191,192,193,197,200,203],"tr",{},[194,195,196],"th",{},"Config",[194,198,199],{},"2.4K",[194,201,202],{},"38K",[194,204,205],{},"151K",[207,208,209,232,249,263,277,291],"tbody",{},[191,210,211,217,222,227],{},[212,213,214],"td",{},[138,215,216],{},"Ornith-1.5-35B-A3B int4, vLLM, PRO 6000",[212,218,219],{},[138,220,221],{},"143.8",[212,223,224],{},[138,225,226],{},"172.7",[212,228,229],{},[138,230,231],{},"159.1",[191,233,234,240,243,246],{},[212,235,236,237],{},"Ornith-1.5 int4, vLLM, 2x Strix TP=2 ",[170,238,239],{},"(previous setup)",[212,241,242],{},"103",[212,244,245],{},"136",[212,247,248],{},"102",[191,250,251,254,257,260],{},[212,252,253],{},"Laguna-S-2.1 Q4_K_XL, llama.cpp",[212,255,256],{},"77.5",[212,258,259],{},"99.6",[212,261,262],{},"72.1",[191,264,265,268,271,274],{},[212,266,267],{},"Qwen3.8-Flash-Next Q3_K_XL, llama.cpp",[212,269,270],{},"70",[212,272,273],{},"54",[212,275,276],{},"28",[191,278,279,282,285,288],{},[212,280,281],{},"Qwen3.8-27B dense FP8, vLLM",[212,283,284],{},"46.1",[212,286,287],{},"48.2",[212,289,290],{},"40.2",[191,292,293,296,299,305],{},[212,294,295],{},"GLM-5.3-Flash IQ2_XXS, llama.cpp fork",[212,297,298],{},"32.7",[212,300,301,302],{},"19.7 ",[170,303,304],{},"(at 21K)",[212,306,307],{},"..",[102,309,310],{},"Ornith won. Ornith won at every depth, by a lot, and it kept winning the harder I pushed.",[102,312,313],{},"I also ran an 11-point quiz of my own against the whole field. Code-semantics puzzles, a planted bug, strict JSON, a reasoning trap, needle-in-a-haystack at three depths. Ornith scored 10 out of 11 and pulled an eight-character secret out of the middle of a 127,000-token document, which told me int4 hadn't broken long-context recall at all. That genuinely surprised me. I assumed that's where the bodies were buried.",[102,315,316],{},"So: fastest model, passes my quiz, frees two GPUs. I wrote it up as settled and felt great about myself for several hours.",[65,318,320],{"id":319},"three-optimizations-that-measured-backwards","Three \"Optimizations\" That Measured Backwards",[102,322,323],{},"Before the settled conclusion got unsettled, three things every forum will tell you are free wins. All three came out negative on this hardware.",[102,325,326,329,330,333],{},[138,327,328],{},"More GPUs made it slower."," I spread flash-next across the PRO 6000 plus three 3090s, 166 GiB of VRAM, against the one card. It came out 14 to 21 percent ",[170,331,332],{},"worse"," at every depth. Layer-split PCIe hops plus slower Ampere layers cost more than the extra memory bought.",[102,335,336,339],{},[138,337,338],{},"Speculative decoding never won, by any route."," The claim going around for this card was \"MTP gets you 2.7x, DFlash 3.7x, an n-gram stack maybe 6x on real coding work.\" Measured on actual code-edit tasks, median of three:",[185,341,342,361],{},[188,343,344],{},[191,345,346,349,352,355,358],{},[194,347,348],{},"Ornith-1.5 on the PRO 6000",[194,350,351],{},"refactor",[194,353,354],{},"extend",[194,356,357],{},"review",[194,359,360],{},"mean",[207,362,363,381],{},[191,364,365,368,371,374,376],{},[212,366,367],{},"baseline",[212,369,370],{},"199.5",[212,372,373],{},"199.8",[212,375,373],{},[212,377,378],{},[138,379,380],{},"199.7",[191,382,383,386,389,392,395],{},[212,384,385],{},"with vLLM n-gram lookup",[212,387,388],{},"91.8",[212,390,391],{},"96.1",[212,393,394],{},"82.1",[212,396,397],{},[138,398,399],{},"90.0",[102,401,402,403,406],{},"2.2 times ",[170,404,405],{},"slower",". Draft-and-verify overhead beats the savings, because code rewrites don't copy long verbatim spans out of the prompt. N-gram speculation only pays when the output echoes the input closely, and editing code is the opposite of that.",[102,408,409,412,413,416],{},[138,410,411],{},"Bigger and newer both lost."," GLM-5.3-Flash is 320 billion parameters with 18 billion active and sat at number three on the open-weight index. It did 32.7 tokens per second. Flash-next, 131B with 6B active, did 70. Ornith, 35B with ",[170,414,415],{},"3B"," active, did 143.8.",[102,418,419],{},"Active parameter count dominates decode speed. Not total size, not release date, not benchmark reputation.",[65,421,423],{"id":422},"the-benchmark-that-actually-compiles-the-code","The Benchmark That Actually Compiles the Code",[102,425,426],{},"Here's the thing about that 11-point quiz Ornith aced. I wrote it. It's small, it's mine, and all it really asks is whether a model knows some things about Python.",[102,428,429],{},"What I needed to know was whether it can do the job.",[102,431,432],{},"The Aider polyglot benchmark does that. 225 exercises across six languages pulled from real Exercism suites, graded by actually compiling the result and running its tests. More to the point, it measures whether a model can emit a valid edit into a real repository, which is the entire thing a coding agent does all day.",[102,434,435],{},"First run handed me 26.2 percent for Ornith and I almost wrote it down.",[102,437,438,439,443,444,447,448,451],{},"Then I found ",[440,441,442],"code",{},"max_tokens: 4096"," sitting in my harness config. It had been truncating edits mid-block, the API returned a length stop, and the benchmark logged that as \"exhausted context window.\" ",[138,445,446],{},"Thirty-one percent of that run had silently failed"," and handed me a number that looked completely reasonable. Nothing was broken on screen. The only evidence was one line reading ",[440,449,450],{},"Output tokens: ~3,897 of 8,192"," right before the harness gave up.",[102,453,454],{},"That's the bug I'd pay money to never hit again. A crash you can see. A plausible wrong number you cannot.",[102,456,457],{},"I raised the cap and ran it properly.",[102,459,460],{},[159,461],{"alt":462,"src":463},"Two panels showing a reversal between the same two models. Top panel, decode speed: Ornith-1.5-35B-A3B reaches 143.8 tokens per second against 70 for Qwen3.8-Flash-Next. Bottom panel, Aider polyglot pass at 2 across 225 compiled and tested exercises: Ornith scores 28.9 percent against 64.4 percent for Qwen3.8-Flash-Next, a paired McNemar p value of 1.1e-17","\u002Fimages\u002Fblog\u002Fblackwell-bakeoff\u002Fspeed-vs-score.svg",[102,465,466,467,470,471,474],{},"Ornith scored ",[138,468,469],{},"28.9 percent",". Flash-next scored ",[138,472,473],{},"64.4 percent",". Same 225 exercises, same harness, same afternoon.",[102,476,477],{},"Because both models saw identical problems, exercise difficulty cancels out and a paired test applies. Both passed 56, neither passed 71, flash-next-only 89, Ornith-only 9. That lands at p = 1.1e-17, which is statistics for \"this is not a coincidence, go sit down.\"",[102,479,480],{},"Per language it wasn't a fight either:",[102,482,483],{},[159,484],{"alt":485,"src":486},"Grouped bar chart of Aider polyglot pass at 2 by language. Ornith-1.5-35B-A3B scores 35.3 percent on Python, 40.8 on JavaScript, 28.2 on Go, 34.6 on C++ and 27.7 on Java. Qwen3.8-Flash-Next scores 82.4, 81.6, 71.8, 69.2 and 66.0 on the same languages. Rust is omitted because the benchmark container has a broken cargo toolchain and both models score zero","\u002Fimages\u002Fblog\u002Fblackwell-bakeoff\u002Fper-language.svg",[102,488,489],{},"Two notes on this bench, both on me. Both models scored 0.0 on Rust, purely due to an error in my setup of the container. I had enough data at this point and did not feel the need to rerun with Rust enabled. And I had thinking flagged off on Ornith, which is just due to the way I use the model, while I left it on with Qwen3.8.",[65,491,493],{"id":492},"the-part-where-the-edits-wouldnt-apply","The Part Where the Edits Wouldn't Apply",[102,495,496],{},"So what actually happened? The mechanism is the best part.",[102,498,499],{},[138,500,501],{},"134 malformed responses against 14.",[102,503,504],{},"Ornith can write code. What Ornith cannot do is reliably emit a valid search-and-replace edit block. Its output was well-formed 62.7 percent of the time. Flash-next managed 96.4 percent and never got truncated once.",[102,506,507],{},[159,508],{"alt":509,"src":510},"Two panels on edit-format compliance. Top, across the full 225-exercise run: Ornith-1.5 returns a well-formed edit 62.7 percent of the time with 134 malformed and 37 truncated responses, while Qwen3.8-Flash-Next returns 96.4 percent well formed with 14 malformed and none truncated. Bottom, a 20-exercise probe on Ornith-1.5 alone: 40 percent well formed when asked for search-and-replace diffs, against 100 percent when asked to rewrite whole files","\u002Fimages\u002Fblog\u002Fblackwell-bakeoff\u002Fedit-format.svg",[102,512,513],{},"Forty percent well-formed when asked for diffs. One hundred percent when asked to rewrite whole files. The intelligence was there the entire time and it kept falling out of the envelope on the way to disk.",[102,515,516,517,520],{},"For an agent that edits files in place, that isn't a quality gap. That's disqualifying. The output has to ",[170,518,519],{},"apply",".",[102,522,523],{},"And it reframes the speed win completely. Ornith was twice as fast at producing work I'd have to throw away.",[65,525,527],{"id":526},"what-im-actually-buying-now","What I'm Actually Buying Now",[102,529,530],{},"The bench card runs flash-next now. Four slots at 262,144 context each, 97.6 tokens per second on one stream and 305.3 across eight. Parallel tool calls in a single turn, character-exact OCR, and it found a needle at 101,570 tokens. More slots cost zero extra VRAM at a fixed total budget, which is the best trick I learned all week.",[102,532,533],{},"The node notes, which is what this whole exercise was for:",[70,535,536,546,556,562,568],{},[73,537,538,545],{},[138,539,540,541,544],{},"Target low ",[170,542,543],{},"active"," parameters, not low total."," A 6-14B-active mixture-of-experts at int4 is the sweet spot, and it beat everything with more active parameters regardless of total size or ship date.",[73,547,548,551,552,555],{},[138,549,550],{},"Design around four-bit Marlin."," The exotic formats on this architecture either fall back or corrupt, int8 is compiled out entirely, and FP8 mixture-of-experts crashes. Marlin is the fastest ",[170,553,554],{},"correct"," path, and it beat native FP8 even on dense weights.",[73,557,558,561],{},[138,559,560],{},"Scale with replicas, not tensor-parallel."," One card sustains 2,072 tokens per second at 32 concurrent with 12 times the KV headroom it needs.",[73,563,564,567],{},[138,565,566],{},"Never mix architectures in one engine."," Tensor-parallel across Blackwell and Ampere is documented-broken and closed as not-planned, and an Ampere card in the group forfeits the low-precision formats, which is the entire reason to own Blackwell.",[73,569,570,573],{},[138,571,572],{},"Weight \"merged upstream\" heavily."," Two of my most promising candidates died purely on engine support. One wouldn't load anywhere. The other needed a specific fork, required flash attention disabled to produce correct output, and overflows a grid dimension at exactly the context length its headline is about.",[102,575,576],{},"That last one deserves a footnote. Another agent's research estimated 90 to 110 tokens per second for that model. Measured reality was 32.7. Research is not measurement.. and I say that as the guy whose measurements were also wrong for six hours.",[65,578,580],{"id":579},"tokens-per-second-is-not-the-whole-product","Tokens Per Second Is Not the (whole) Product",[102,582,583],{},"Nine configurations, four benchmark suites, an entire night, and a conclusion I was confident enough to write down.",[102,585,586],{},"Every synthetic test favored the fast model. Decode, prefill, concurrency, KV capacity, my own quiz. Then one execution-graded benchmark that mirrors the actual work inverted the answer completely.",[102,588,589,590,593],{},"If I'd specced that node off night one, I'd have sized it around a model that can't reliably hand back an edit that applies. Run the workload-representative test ",[170,591,592],{},"first",", not last. That's the whole post.",[102,595,596],{},"Oh, and one thing got switched off along the way. My camera system's AI description feature had quietly burned about 27,000 requests and 100 million tokens describing my driveway to nobody. Not once has a human read one. I turned it off on every camera and the only thing that changed is the GPU got quieter.",[102,598,599],{},"The math still does not work out. It was never going to work out.",{"title":601,"searchDepth":602,"depth":602,"links":603},"",2,[604,605,606,607,608,609,610,611,612],{"id":67,"depth":602,"text":68},{"id":99,"depth":602,"text":100},{"id":119,"depth":602,"text":120},{"id":176,"depth":602,"text":177},{"id":319,"depth":602,"text":320},{"id":422,"depth":602,"text":423},{"id":492,"depth":602,"text":493},{"id":526,"depth":602,"text":527},{"id":579,"depth":602,"text":580},"2026-09-14T00:00:00.000Z","I have to spec a two-to-four card inference node, so one Blackwell went on the bench first. Every throughput test picked one winner. Then a benchmark that actually compiles the code scored it 28.9% against 64.4%.","md","\u002Fimages\u002Fblog\u002Fblackwell-bakeoff\u002Fhero.webp",864,1536,{},true,{"title":14,"description":614},"RTX PRO 6000 Local LLM Bakeoff: Nine Models Tested",{"loc":15,"lastmod":624},"2026-09-14",[626,627],"AI","Self Hosting",null,"GB4EwNR49-UZFQ4EO_pxD_4hBSqEInEfrcfVHkLVEBs",[631,633,642,649,655,663,669,677,683,689,696,704],{"title":14,"author":60,"date":613,"draft":57,"description":614,"image":616,"tags":632,"navigation":620,"path":15,"stem":16,"id":59},[626,627],{"title":10,"author":60,"date":634,"draft":57,"description":635,"image":636,"tags":637,"navigation":620,"path":11,"stem":12,"id":641},"2026-08-19T00:00:00.000Z","Automated BIM takeoff platforms assume your model followed the rules. Real models never do. So an AI agent drove Navisworks headless.. and five trades of takeoff took four days.","\u002Fimages\u002Fblog\u002Fautomated-bim-takeoff\u002Fhero.webp",[626,638,639,640],"Agents","Construction","BIM","blog\u002Fblog\u002Fautomated-bim-takeoff.md",{"title":26,"author":60,"date":643,"draft":57,"description":644,"image":645,"tags":646,"navigation":620,"path":27,"stem":28,"id":648},"2026-07-25T00:00:00.000Z","My movement bots said the server could hold hundreds. Then I taught them to swing a sword and the whole thing fell over at 45.. which is how I ended up shopping for CPUs instead of RAM.","\u002Fimages\u002Fblog\u002Fgame-server-scaling\u002Fhero.webp",[647,627],"Game Development","blog\u002Fblog\u002Fgame-server-scaling.md",{"title":38,"author":60,"date":650,"draft":57,"description":651,"image":652,"tags":653,"navigation":620,"path":39,"stem":40,"id":654},"2026-07-07T00:00:00.000Z","My friends said the new model on my rig was drunk. Root-causing that from LiteLLM request logs turned into pricing every token my GPUs have ever produced.. and a $961 cloud comparison.","\u002Fimages\u002Fblog\u002Flocal-ai-true-cost\u002Fhero.webp",[626,627],"blog\u002Fblog\u002Flocal-ai-true-cost.md",{"title":22,"author":60,"date":656,"draft":57,"description":657,"image":658,"tags":659,"navigation":620,"path":23,"stem":24,"id":662},"2026-06-17T00:00:00.000Z","I built a homelab full of AI agents to run my life, then got actually organized with a pen, an A5 notebook, and a bullet journal key I bent to fit my markdown brain.","\u002Fimages\u002Fblog\u002Fde-digitizing\u002Fhero.webp",[660,661],"Productivity","Journaling","blog\u002Fblog\u002Fde-digitizing.md",{"title":30,"author":60,"date":664,"draft":57,"description":665,"image":666,"tags":667,"navigation":620,"path":31,"stem":32,"id":668},"2026-06-08T00:00:00.000Z","I finally got Qwen3.6 running locally, ran the dense flagship against the sparse MoE, and learned that four benchmark points are worth a lot less than 5x prefill.","\u002Fimages\u002Fblog\u002Flocal-ai-moe-vs-dense\u002Fhero.webp",[626,627],"blog\u002Fblog\u002Flocal-ai-moe-vs-dense.md",{"title":18,"author":60,"date":670,"draft":57,"description":671,"image":672,"tags":673,"navigation":620,"path":19,"stem":20,"id":676},"2026-06-02T00:00:00.000Z","A client asks your superintendent for a small favor. He says yes. Months later it's a claim nobody can reconstruct. The case for AI agents on EPC jobs.","\u002Fimages\u002Fblog\u002Fconstruction-agents\u002Fhero.webp",[626,638,639,674,675],"EPC","Project Controls","blog\u002Fblog\u002Fconstruction-agents.md",{"title":42,"author":60,"date":678,"draft":57,"description":679,"image":680,"tags":681,"navigation":620,"path":43,"stem":44,"id":682},"2026-04-28T00:00:00.000Z","Six hours, five models, one IPMI reboot, zero upgrades -- a field report on why the bleeding edge of local LLM hosting is mostly bleeding.","\u002Fimages\u002Fblog\u002Flocal-ai-upgrade\u002Fhero.webp",[626,627],"blog\u002Fblog\u002Flocal-ai-upgrade.md",{"title":34,"author":60,"date":684,"draft":57,"description":685,"image":686,"tags":687,"navigation":620,"path":35,"stem":36,"id":688},"2026-03-25T00:00:00.000Z","Four RTX 3090s, an EPYC server, and a 122B parameter model -- the journey from underwhelming to overkill and back to surprisingly elegant.","\u002Fimages\u002Fblog\u002Fai-server\u002Fhero.webp",[626,627],"blog\u002Fblog\u002Flocal-ai-rig.md",{"title":50,"author":60,"date":690,"draft":57,"description":691,"image":692,"tags":693,"navigation":620,"path":51,"stem":52,"id":695},"2025-08-27T00:00:00.000Z","REST APIs to roguelikes: How I'm using a smaller game to learn the fundamentals before building my dream MMORPG. A honest indie gamedev journey.","\u002Fimages\u002Fblog\u002Fthundoria\u002Fhero.webp",[647,694],"Nuxt","blog\u002Fblog\u002Fthundoria-architecture.md",{"title":54,"author":60,"date":697,"draft":57,"description":698,"image":699,"tags":700,"navigation":620,"path":55,"stem":56,"id":703},"2025-06-25T00:00:00.000Z","Building an AI app with zero knowledge of AI, hitting deployment walls, and evolving architecture to meet real-world needs.","\u002Fimages\u002Fblog\u002Fvectly\u002Fhero.webp",[626,701,702,694],"Web Development","Side Projects","blog\u002Fblog\u002Fvectly-scaling.md",{"title":46,"author":60,"date":705,"draft":57,"description":706,"image":707,"tags":708,"navigation":620,"path":47,"stem":48,"id":709},"2025-06-17T00:00:00.000Z","Using Amazon's AI coding assistant, Q, to build a browser-based roguelike with Nuxt.js — the potential and the limits of AI-assisted development.","\u002Fimages\u002Fblog\u002Fq-roguelike\u002Fhero.webp",[626,647,694],"blog\u002Fblog\u002Fq-roguelike.md",[711,713,715,717,719,721,723,725,727,729,731,733],{"title":14,"path":15,"date":613,"tags":712,"image":616,"draft":57},[626,627],{"title":10,"path":11,"date":634,"tags":714,"image":636,"draft":57},[626,638,639,640],{"title":26,"path":27,"date":643,"tags":716,"image":645,"draft":57},[647,627],{"title":38,"path":39,"date":650,"tags":718,"image":652,"draft":57},[626,627],{"title":22,"path":23,"date":656,"tags":720,"image":658,"draft":57},[660,661],{"title":30,"path":31,"date":664,"tags":722,"image":666,"draft":57},[626,627],{"title":18,"path":19,"date":670,"tags":724,"image":672,"draft":57},[626,638,639,674,675],{"title":42,"path":43,"date":678,"tags":726,"image":680,"draft":57},[626,627],{"title":34,"path":35,"date":684,"tags":728,"image":686,"draft":57},[626,627],{"title":50,"path":51,"date":690,"tags":730,"image":692,"draft":57},[647,694],{"title":54,"path":55,"date":697,"tags":732,"image":699,"draft":57},[626,701,702,694],{"title":46,"path":47,"date":705,"tags":734,"image":707,"draft":57},[626,647,694],1789429243986]