Notes | QuarkMind
DECLINE wired: QG2 finally closed
The branch closes four issues — three small doc fixes and one that needed thinking.
The attribution errors you don't see until you verify
Writing four chapter entries for an architecture document turned out to be mostly a verification problem.
The Bridge Between Two Engines
The poc dependency had been on borrowed time for months. casehub-core:1.0.0-SNAPSHOT — the retired proof-of-concept — was still running every game tick, dispatching plugins via createAndSolve() and...
Trust Routing is Degenerate CBR
The question going in: is QuarkMind actually using CaseHub, or just wearing it as a label? We’d built six layers — connection, physics, the plugin pipeline, scouting, economics, and trust-weighted ...
Wiring playerResult to L6 Trust Routing
L6 trust routing shipped two weeks ago. The machinery was correct — Bayesian Beta model, four-phase maturity, designated fallback tiebreaker. The problem was that GameOutcomeRecorder always wrote A...
Pulling out ocraft's Vert.x heart
The original plan for the real SC2 connection was to use ocraft-s2client-bot — the only Java library that speaks the SC2 Remote API. It did the job for a while: ocraft handles the WebSocket handsha...
QuarkMind — Layer 3: Four Surprises from qhorus
QuarkMind — Layer 3: Four Surprises from qhorus
Layer 4: the ledger watches the plugins
Two things shipped today. The first was small — a null correctness fix in InMemoryCaseFile that we’ve known about since #172 surfaced the problem. The second was the Layer 4 milestone: every agent ...
Layer 5: The Gate That Works
Layer 5 is done. TacticsTask now activates only when scouting has found a threat
and strategy has set a course of action. In the early game — no enemy contact — tactics
never runs.
EigenTrust Has No Work to Do Here
The question has been waiting since casehubio/ledger#114 was filed: when L4 and L6
land, should EigenTrust run alongside Bayesian Beta?
Arc42Stories and a Lighter Ledger
Two things landed today that change how the next few months look.
canProduce Was Never Just a Query
The last entry ended with #165 tracked but deferred — canProduce() read-only contract was doc-only. Making PlayerState public was the right call, but it left the plugin seam in an awkward position:...
Opening the Race Plugin Seam: Splitting PlayerState
Issue #164 was a small one by description: PlayerState is package-private and RaceModel takes it as a parameter, so external race implementations (required by #74) can’t implement the interface. Ma...
Phase 5 Complete: EmulatedGame Accuracy Gaps Closed
Phase 5 is done. I expected to branch and start coding. The test suite said otherwise: all four child issues closed, 828 unit and integration tests passing.
The Pixel Buffer That Didn't Know The Camera Had Moved
The visualizer has been working since April. It renders probes, geysers,
minerals, buildings, fog — the full SC2 picture. But four things sat on the
deferred list since then: HUD mineral formatting...
Three races, one seam
The EmulatedGame has been Protoss since the day it was built. Twelve probes, a Nexus, 15 supply — all hardcoded. Adding Terran and Zerg (#138) forced a decision I’d been putting off: where does rac...
Two Extractors, One State
Issue #162 was filed yesterday during the #160 review — not a bug, just a
duplication I didn’t want to leave in place. AbilityMapping.onSelection()
and IEM10CommandExtractor.applySelectionDelta() b...
ZeroIndices Doesn't Mean Zero
Three issues in one branch: unit tests for IEM10CommandExtractor.applySelectionDelta
(#160), a SimulatedGame.isComplete() base-contract test (#161), and Terran ability IDs
in AbilityMapping (#140)....
Three Ways to Extract Nothing
The IEM10 dataset has 30 tournament replays from 2016. Until now we’d used
them for tracker events only — building state, counting units, tracking births.
The gameEvents array was sitting there the...
Dead State, Lucky Guesses, and a Layer That Didn't Exist
Five small issues. The word “small” proved relative.
Two Wrong Build Times
The sub-tick timing fix for unit training had one known gap: buildings still used integer tick counts, no loop offset, whatever we’d written down.
Override and Cleanup
Three code review nits and a follow-up feature. The nits are barely worth a paragraph.
Two Precision Fixes
The previous entry ended with a ±1 tick residual in the replay validation — Stalkers completing one tick early because drainBuildingQueues passes 0L to startTraining for the next queued unit, losin...
The Vespene Fix
The previous entry ended with gas units as the remaining divergence: EmulatedGame starts with 0 vespene and earns none, so every TrainIntent for a Stalker (50 gas) or Immortal (100 gas) is silently...
A Tick Too Early
The last entry ended with a claim: the ≤ 2 unit delta was the mining model.
That turned out to be wrong — or at least, incomplete.
What the Smart Command Hides
Phase 6 was about feeding real player commands into EmulatedGame and watching the unit counts match the replay. The question was how to get those commands out.
The Engine Fights Back
Phase 6 requires the emulated engine to behave like real SC2 — fixing independent building queues, supply reservation timing, building type validation, and an enemy AI that generated fake building ...
Accurate, Not Just Working
A tier-4 health check before Phase 6 finds the README still naming replaced stubs and the emulated mode guide completely absent — accuracy over progress.
Clean Desk, Bigger Picture
Clearing the backlog before Phase 6 — ADRs written, PixiJS bundle removed, scouting threshold recalibrated, and documentation that had described stubs instead of real implementations finally fixed.
Both Sides of the Board
The scouting calibration was quick — ran the replay dataset, updated three string constants to match the live DRL thresholds, done. The real work was the enemy AI.
Seeing Is Believing
I asked for visual verification three times. Each time Claude reported it done. When I sent a screenshot showing blank terrain where minerals should be, the gap was obvious.
The Map Fills In
The replay was navigable but half-blind. Units moved. Buildings appeared. But the economy was invisible — no mineral patches, no geysers, no enemy Hatcheries expanding across the map. For a Protoss...
The Replay Plays
The visualizer had terrain, buildings, all sixty-five units rendered as sprites.
Buildings, All Three Races
The visualizer had sprites for 65 multiplayer units across Terran, Protoss, and
E18–E19: The Full Roster
When we added Zerg sprites and looked at the replay parser, there was a gap nobody had noticed: SCV, Drone, Overlord, Baneling, Phoenix, Oracle, Tempest, Mothership, Warp Prism, Locust, Broodling, ...
E16: Zerg Sprites and the Showcase That Lied
E16 is done. Zergling, Roach, Hydralisk, Mutalisk — four draw functions, four distinctly different body plans, all following the palette and dispatch pattern that E14 and E15 established.
E15: Terran Sprites and the Cost of Looking Instead of Testing
E15 delivered the Terran side of the cartoon roster: Marine, Marauder, and
E14: A New Visualizer
The existing visualizer was a flat 32×32 PixiJS grid — top-down, static
E13: Scouting Calibration
The plan for #16 assumed both replay datasets would feed into `ReplaySimulatedGame`.
E12: Stalker Blink
E12 turned out to be exactly the session I'd predicted: thorough, mechanical in parts, with a couple of genuinely non-obvious moments.
E11: The Strategy Question
Before touching E11, we ran the post-E10 benchmark baseline. Stalker kiting, focus-fire, and cooldown tracking all in — game loop still at 0ms mean, 1ms p95. Good.
Kiting and the planner's perfect mistakes
E9 gave the agent eyes. The enemy staging area went dark behind the fog,
What the probe sees
Before E9, the visualizer showed everything. Every Zealot waiting in the staging
High Ground
The wall works. E7 fixed pathfinding through the chokepoint, with a physics
Defending the Wall
Something went through the wall. I said it was the probe — consistently,
Armour, Retreat, and Walls
The emulator has been getting more honest about SC2.
The Enemy Gets to Work
The plan from April 10th didn't survive.
The Enemy Gets a Brief
E3 left us with a working combat loop: units fight, shields absorb, units die. The enemy Zealots still marched from spawn to nexus on a script — at frame 200, regardless of what the player bot was ...
Watching the Game Without Playing It
No live SC2 binary. No immediate path to get one. The bot could reason about StarCraft II and dispatch commands — but to test that against anything real, I needed SC2 running. Rather than wait, I d...
The Game Has Stakes Now
There was a budget bug I'd been carrying. The economics decision service was overcommitting resources every tick — hand it 110 minerals and watch it queue both a Pylon (costs 100) and a Probe (cost...
QuarkusMind — Making the Bot Play
Four plugins working. All four emit intents from real game state — `BuildIntent`, `TrainIntent`, `AttackIntent`, `MoveIntent`. But `SC2BotAgent.onStep()` drained the queue and logged every entry as...
QuarkusMind — Scouting Gets a Mind
Four plugin seams, four frameworks. Strategy got Drools forward-chaining rules.
StarCraft Agent — Tactics Gets a Brain
`TacticsTask` has been a stub since Phase 0. The agent can decide macro
StarCraft II Quarkus Agent — Flow Economics Arrives
With Drools running strategy, the next target was Quarkus Flow for economics. The library research had flagged them as complementary — CaseHub for per-tick reactive decisions, Flow for multi-step o...
StarCraft II Quarkus Agent — Drools Strategy Arrives
The whole point of this project is to use StarCraft II as a testbed for Drools, Quarkus Flow, and CaseHub. Every plugin so far has been hand-coded Java — good discipline, but not the experiment. Dr...
StarCraft II Quarkus Agent — Day Two: No More Stubs
Yesterday's work built the scaffold — mock architecture, real SC2 wiring, replay parsing. Impressive plumbing. The agent still did nothing intelligent. Today's goal: all four plugins real, all stub...
StarCraft II Quarkus Agent — Getting Replays the Long Way Round
The mock works. The CaseEngine cycles, the four dummy plugins log what they see, the QA endpoints respond. But the mock feels fake — a hand-crafted economic trickle that doesn't resemble an actual ...
StarCraft II Quarkus Agent — Phase 1: Wiring Real SC2
Phase 1 had one job: implement `sc2.real` — the real ocraft-backed implementations of the three CDI interfaces (`SC2Client`, `GameObserver`, `CommandDispatcher`) — and prove they satisfy the same c...
StarCraft II Quarkus Agent — Phase 0: The Mock That Runs
Phase 0 had one goal: get the entire plugin stack working against a simulated game. No real SC2 required. Sixteen tasks, ten of them implementation, the rest review. By the end: 27 tests passing, C...
StarCraft II Quarkus Agent — Day Zero
I've been building CaseHub — a Blackboard/CMMN framework for Quarkus — and it's reached the stage where I need something demanding to build against. Not a toy. Not a contrived demo. Something that ...