06 — AI Opponents
This document specifies the Staff: Every Last City's AI opponent, the framework that runs it, and the evidence that has to exist before any claim about its strength may be made. It owns the layered decision architecture and how search stays tractable; the evaluation function and its exact integer arithmetic; how an AI seat forms belief under fog and issues orders under commit-before-you-see; the difficulty ladder and the shipped personality roster; time, memory and determinism budgets for mobile, desktop and the headless farm; the plugin interface third-party AIs are written against; AI substitution for absent players; and the evaluation, anti-regression and adversarial-testing pipeline.
Advanced AI opponents are a headline feature of this product (00-overview.md pillar 6, OV-100 through OV-120). Most people who play a game of this shape will play it mostly alone, and for them the AI is not a substitute for the game — it is the game. Two commitments follow and they govern every requirement below:
The Staff sees exactly what a human in its seat sees, and gets nothing a human seat could not have. Difficulty is quality of play. §3.
A weak opponent plays a smaller game, not a broken one. Weakness is produced by a smaller world model and a slower re-plan, never by corrupting a decision the AI already made correctly. §13.
Status: Draft v0.2 · Owner: unassigned · Depends on: 00-overview.md, 01-game-rules.md,
02-units-and-industry.md, 03-architecture.md, 10-turn-model.md, 11-combat.md, 12-economy.md,
13-command.md, 14-victory.md, and — for plugin hosting, seat substitution and the platform that runs
the farm — 05-multiplayer.md, 07-modding-content.md, 08-services-platform.md. Binding non-requirement
sources: docs/design/00-direction.md, docs/design/01-decision-turn-model.md, and the four AI design
proposals docs/design/ai-architecture.md, ai-opponents.md, ai-learning.md, ai-redteam.md.
A note on the numbers. Every microsecond, millisecond and step figure in this document is a budget being proposed, not a measurement, with two exceptions that are measured and belong to 11-combat.md (CB-2590): the engine sustains ≥ 500 Clash resolutions per Cascade and ≥ 100,000 previews per second on reference hardware. Everything else is engineering estimate, and every requirement that rests on one says so. An AI specification that quotes invented timings as if they were data is exactly the over-promise pillar 6 is most at risk from.
1. What this document owns, and what it does not
Owns: the Staff's architecture, evaluation, belief model, budgets and determinism obligations; the AI seat contract; the difficulty ladder (Rank); the shipped personality roster; the AI plugin interface's decision surface; AI mandates for absent seats; the self-play, tuning and anti-regression pipeline; and the adversarial test roster.
Does not own, and cites rather than restates: the order vocabulary and the command layer (13-command.md); the turn structure and activation (10-turn-model.md); the combat predictor (11-combat.md); the economy's closed forms (12-economy.md); the Track abstraction and the endgame (14-victory.md); the fog model and the Contact Register (01-game-rules.md); the plugin container, sandbox, transport and SDK (07-modding-content.md); the WASM host, determinism CI and performance fixtures (03-architecture.md); the substitution transport and consent flow (05-multiplayer.md); the farm's operation as a service (08-services-platform.md).
AI-005 This document MUST NOT define a way for an AI seat to affect the world other than by submitting order records to the authoritative order log (10-turn-model.md TM-200, 13-command.md CM-2040). Any AI behaviour that is not expressible as a legal order record is a defect in this document or in 13-command.md, and MUST be resolved in one of those two places rather than by adding a private path.
2. Vocabulary
Seven named objects, one named score, and three words that had to be chosen carefully because the specification set has run short of good ones.
| Term | What it is |
|---|---|
| the Staff | The whole shipped AI system, named for a general staff: a few people deciding what the army is for, and a much larger machinery executing it. |
| the Slate | The Staff's belief state — Contacts and their ages, the threat field, force accounting, opponent hypotheses. Everything the Staff thinks it knows. |
| the Atlas | A graph of at most 256 named places — cities, Landmarks, Region capitals, chokepoints, Depots, formation anchors — with abstract inter-node distances per movement class. The map, reduced to something a plan can be written on. |
| the Docket | The turn's candidate Operations: dated, located, valued things worth doing. |
| the Sandtable | A cheap abstract forward model that advances the game a few turns at formation granularity, to rank plans. It exists to order candidates, never to predict the game. |
| the Assay | The evaluation function. An integer score for a position, denominated so that 100 points = one city. |
| Operation | One of exactly twelve named things a force can be assigned to do (§6.5). |
| Rank | An AI difficulty level. Six: Cadet, Lieutenant, Captain, Colonel, General, Marshal. |
| Personality | A named, published set of parameter offsets from a tuned baseline. Seven shipped. |
| Decisive Point | A unit or small group the Staff hand-orders as an explicit Task, outside the Posture vocabulary, within a per-Rank budget. |
| Intent Record | The per-turn audit artifact of an AI seat's reasoning; sibling to 13-command.md CM-1940's CommandDecisionRecord, and on the advisory stream (CM-190), never the rules hash. |
AI-015 Rank, Personality, Operation, Decisive Point and Intent Record MUST have exactly one meaning across this specification set (00-overview.md OV-080), and this document MUST NOT reuse a word another document owns for a different thing. Specifically, an AI difficulty level MUST NOT be called a Tier (02-units-and-industry.md US-810 owns Tier for the Industry ladder), a Grade (11-combat.md owns Grade for veterancy and 01-game-rules.md GR-1260 owns fidelity grade), a Class (02-units-and-industry.md US-090 owns unit class), or a Band (14-victory.md VC-2200 owns Rumour/Report/Alarm).
Rationale: an AI difficulty called "Veteran" would be a word already carrying a combat meaning in the same sentence a player reads it in — "a Veteran AI moved a Veteran battalion". The naming cost is paid once here; the confusion would be paid in every support thread and every design discussion forever.
3. The seat contract
The two hard constraints, and the seven rules that make them checkable rather than promised.
3.1 The Staff is a seat, not a subsystem
AI-010 An AI position MUST be a seat: its decisions MUST enter the simulation as ordinary order records in the authoritative order log, in the same envelope as any human order (03-architecture.md AR-260, 10-turn-model.md TM-200, TM-210), submitted during that seat's Orders phase, and resolved by the same Cascade. The Staff MUST NOT be part of the simulation core, MUST NOT be reachable from rules code, and MUST NOT be able to alter any state except by an order the authority accepts.
Rationale: this is 00-overview.md OV-100 and it is the design's strongest structural advantage, obtained without being designed for the AI's benefit. Because orders are persistent conditional policies evaluated at activation (10-turn-model.md TM-280) rather than a stream of keystrokes, an AI and a human write in the same language, into the same log, evaluated by the same code. An AI that cannot express something has found a gap in the player's vocabulary — which is a bug report about 13-command.md, not about the AI.
AI-020 The fairness constraint — information. An AI seat MUST receive exactly the per-player fog-filtered player view a human seat receives, and nothing else. It MUST NOT read true world state for any tile, unit, city or installation its owner cannot presently see and has not previously observed (13-command.md CM-130 states the same rule for the command layer); it MUST NOT read any other seat's view, orders, Contact Register, Dispatch, or internal state; and it MUST NOT read any value from which those can be recovered.
AI-030 The fairness constraint — resources. No shipped preset MAY grant an AI position a production, economic, movement, vision, combat, supply or victory-side advantage of any kind (00-overview.md OV-110). Every handicap that exists is an explicitly configured, disclosed, recorded setup option under §4, applies identically to human seats, and is never part of a difficulty Rank.
AI-040 The Staff MUST NOT read the global activation order, any opponent's position in it, or any opponent's exact Initiative. 10-turn-model.md TM-380 and TM-1120 withhold these from every player; an AI seat is a player. The Staff MAY compute its own units' relative activation order, because TM-380 grants that to every seat, and MAY estimate opponents' Initiative from the published Initiative terms (TM-900) applied to its own Contacts.
Rationale: this is the single most seductive leak available, because the frozen order is sitting in memory and reading it is easier than estimating it. TM-1120 makes withholding it a rule about players, and the Staff is bound by rules about players.
AI-050 The plausibility constraint. No Rank MAY produce behaviour that reads as broken rather than as weak. The Constraint Floor of §6.9 MUST run at full quality at every Rank, and a Floor violation MUST be a build gate rather than a tuning metric (AI-620, AI-1410).
Rationale: an opponent making blunders no human would make is unsatisfying even when it is easy to beat. A beginner who loses a city because they forgot it existed feels bad about themselves; a beginner who watches the AI forget a city feels bad about the game.
AI-055 An AI seat MUST always be declared. Setup, the player list, the Watch, the replay
header and the game's Terms MUST identify every AI seat as an AI seat, with its Rank and every active
handicap. Concealment of which personality an AI seat is running is permitted as the Opponents: Anonymous option of AI-756; concealment of the existence of an AI seat MUST NOT be offered.
Rationale: concealment requires the AI to fake human behaviour it does not have, starting with commit timing — a seat that commits in 40 ms every turn is identifiable within three turns unless artificial latency is added, which is a lie with a code path in it. It also corrupts the terms of the contest, which the rest of this set treats as the thing that must be public (14-victory.md publishes the Ebb schedule and the Landmark locations on exactly this principle), and it makes the Debrief (AI-754) impossible to offer, because offering it would reveal the seat.
3.2 What the Staff may do that a human may do
AI-060 The Staff MUST be permitted to issue explicit Tasks and per-unit orders exactly as a human
may (13-command.md CM-070, CM-270). Restricting an AI seat to Postures and Sanctions MUST NOT be
treated as a fairness measure or an elegance: it would be a handicap the human does not carry, and
every command-layer exploit in §18 would gain a free multiplier. The number of units an AI seat
hand-orders outside the Posture vocabulary per turn MUST be a declared per-Rank budget P (AI-610),
and MUST be recorded in the Intent Record (AI-750).
AI-070 The Staff's order-selection process MAY consume a dedicated seeded stream (AI-390). The orders it submits MUST be ordinary orders and MUST be executed by the same deterministic command layer as any player's. 13-command.md CM-110 forbids the command layer from drawing randomness; it does not bind a seat's choice of what to submit, any more than it binds a human's.
Rationale: without this stated normatively, someone will read CM-110 as binding on the AI, and the AI will ship as a pure strategy in a simultaneous-move game — which is the definition of exploitable (§9.3). CM-110's rationale is that a player must be able to predict their own screen; it says nothing about whether an opponent should be able to predict a plan.
3.3 Evidence, not assertion
AI-080 No difficulty Rank, personality, or strength claim MAY ship without measurement by the pipeline of §17 and the gates of §20 (00-overview.md OV-120). A Rank whose claimed strength has not been measured MUST NOT appear in the difficulty selector; §13.5 specifies what the selector shows instead.
AI-090 Version-pinned dependencies. This document's weights, thresholds and evaluation features are functions of the constants in 11-combat.md, 12-economy.md and 02-units-and-industry.md. The AI build MUST record the exact document versions and content hashes it was tuned against, and weight tuning (§17) MUST NOT begin until those three documents are mutually consistent. Structural work — the planner, the belief filter, the Cascade rollout, the Antagonist harness (§18) — MUST NOT be blocked on that consistency, because none of it depends on the constants.
Rationale: self-play tuning against an inconsistent rules set produces confident, well-tested, wrong weights, and the confidence is the dangerous part — a tuned vector carries a promotion-gate p-value and a release note, so it looks like knowledge. The first tuning cycle would be thrown away, and with it 14-victory.md's length-estimate calibration (VC-3210) and the Antagonist calibration done against the old numbers.
4. Handicaps, and why every one of them is published
4.1 The disclosure rule
AI-100 Every advantage or disadvantage in force for any position — AI or human — MUST be disclosed in three places: the setup screen at the moment it is chosen, the in-game rules review, and the replay header. Disclosure MUST name the position, the handicap, its magnitude and its direction. No shipped configuration MAY grant any position a resource, production, combat, movement, vision or information advantage that is not disclosed in all three (04-ui-ux.md renders these).
Rationale: the shallow reason is fairness. The real reason is epistemic — a player who beats a handicapped AI and does not know it has been told something false about their own skill, and the game has spent their evening teaching it. Everything else in this design is built to make the player's model of the world correct: 11-combat.md's exact preview, 13-command.md's decision records, 14-victory.md's published Ebb schedule, 12-economy.md's visible Integration. A hidden AI bonus is the same sin as an invisible production tax (12-economy.md EC-010, EC-040), committed against the player's model of themselves rather than of the economy. Two practical reasons follow it: an undisclosed advantage is indistinguishable from a bug, so every unexplained AI success becomes a support ticket; and in any game with more than one human it is a rigged contest.
AI-110 A difficulty preset MAY bundle a Rank with handicap values, but the setup UI MUST expand the bundle into its disclosed components before the game starts, and the recorded game configuration MUST carry the components rather than the bundle name.
4.2 What is offered
AI-105 The handicap catalogue MUST be exactly the following. Each applies to any seat, in either direction where a range is signed, and each is chosen at setup and never changed during a game.
| Handicap | Range | Why it is legitimate |
|---|---|---|
| Extra starting cities | ±3 | Visible from turn 1, positional, and reasonable-about |
| Starting Industry | 1–3 | 02-units-and-industry.md US-810 already makes Industry a per-city rating; starting higher is a legible head start |
| Industry cap | 1–4 | The same lever from the other end: a veteran capped at a lower ceiling against a newcomer at the full one |
| Opening stock | ±400 Works, ±200 Manpower, once | A finite, spendable, visible head start |
| Cadre discount | 50–200‰ of the escalating cost 12-economy.md §11 defines | Dials the anti-snowball brake directly and visibly |
| Start-position quality | seeded and labelled | Map generation already ranks starts; saying so is free |
| Foreknowledge | on/off | AI-150 |
| Full vision | on/off, off by default | AI-330 |
Rationale for opening stock rather than a production-rate multiplier: a rate multiplier distorts every derived number in 12-economy.md — the 25-to-35-turn payback target of EC-570, the Cadre cost curve, the Works-to-Manpower ratio bands of EC-290 that determine the forced army mix — so a handicapped game is quietly playing different economics and none of that document's worked reasoning holds. A one-time stock leaves the arithmetic intact and can be understood as "they started with an army", which is a sentence a player can hold.
AI-108 The following MUST NOT be offered as handicaps: production-rate multipliers, movement-rate bonuses, vision-radius bonuses, and per-seat exemptions from any brake of 12-economy.md EC-030. All four are invisible in play and all four corrupt a derived system.
AI-112 A combat handicap, where one is offered at all, MUST be an ordinary force modifier that is visible to the predictor and enumerated in the attack preview's line items alongside every other contribution. It MUST NOT be applied after prediction, and MUST NOT be applied to resolution without being applied to the preview.
Rationale: 11-combat.md CB-2280 makes the preview a pure function of the Clash Specification and CB-2690 puts the binary-search prediction against a brute-force oracle in CI. A hidden combat handicap makes the preview lie and turns that CI gate into a false alarm. A visible one costs nothing and, by appearing in the panel every single time, means nobody forgets it is on.
AI-150 Foreknowledge MUST be offered as a labelled handicap granting a seat revealed terrain and city locations at turn 0 and no unit information at any time. It MUST NOT reveal, then or later, any foreign unit, any Contact the seat has not earned, or any city's garrison.
Rationale: this is the handicap most players are actually asking for when they ask for full vision — an opponent that does not spend twenty turns exploring. It is legible, it is equivalent to very good early scouting, and it changes nothing about how the seat behaves once contact is made.
4.3 The rule that keeps the ladder honest
AI-115 No handicap preset MAY ship, and no handicap MAY be offered as a difficulty step above the top Rank, until the un-handicapped top Rank's win rate against the human ladder has been measured and recorded (AI-080, AI-730).
Rationale: the day the top Rank loses to good players, the instinct will be to reach for the handicap levers, and the metrics will go green because the subsidised AI wins. That converts a strength problem into a fairness problem and hides the strength problem permanently. This requirement is the only thing standing between "difficulty comes from quality of play" and a slow, well-intentioned death.
5. What the Staff sees
5.1 The view surface
AI-280 An AI seat MUST be served exactly the player view of 00-overview.md §9.6: revealed terrain, current vision, its own units and cities in full, its own economy, and foreign entities only as Contacts from its own Contact Register (01-game-rules.md GR-1200, GR-1210) at the fidelity GR-1260 admits. The view an AI seat receives MUST be produced by the same projection a fog-enforced client receives (05-multiplayer.md MP-250), and MUST NOT be a second, more permissive projection built for convenience.
AI-285 The AI's input stream MUST be byte-identical to the compacted per-player observable event stream a network client receives for the same seat. The Staff MUST NOT consume the raw per-activation event stream, the unfiltered Cascade trace, or any intermediate the core produces while resolving. CI MUST assert this equality over the benchmark corpus (AI-1400); a divergence MUST be a release blocker.
Rationale: the Staff runs in-process, so the raw per-activation stream is right there and consuming it is easier than consuming the compacted one. 10-turn-model.md already closes this leak for network clients because activation gaps correlate with Initiative bands and therefore leak enemy composition. An AI that reads the raw stream is cheating by construction, in a way that is invisible to inspection and that would make every strength measurement in this project meaningless. It is also the cheapest anti-cheat proof available: one byte comparison in CI.
AI-290 The Staff's economy view MUST expose exactly the derived economic values the owning human would see — Works and the Yard, Manpower, Integration, Unrest, garrison requirement and points present (12-economy.md EC-1230), supply state, production queues and completion estimates — and nothing about another player's economy beyond what Contacts and the published Track bands (14-victory.md VC-2200) reveal.
AI-300 The Staff MUST NOT be able to observe pending or future random results. Combat randomness is
drawn by the core's seeded rules streams at resolution (03-architecture.md AR-370) and MUST NOT be
exposed through any view or any AI-facing call. The Staff MUST NOT hold the game root Seed (AI-195).
AI-310 The Staff MUST be given the complete active rules configuration, the complete unit set (02-units-and-industry.md US-700, US-380, US-470), the enabled Tracks with their thresholds, Vigils and published schedules (14-victory.md VC-350), and the Ebb schedule. There is no fog over rules, only over the map (02-units-and-industry.md US-930 makes the encyclopedia complete from turn one for every player), so withholding any of this from an AI seat would be a handicap, not a fairness measure.
AI-320 The Contact Register MUST be the Staff's only source of knowledge about foreign units, cities and installations. The Staff MUST NOT maintain a parallel record populated by any other means, MUST NOT retain a Contact the Register has decayed beyond what GR-1260 admits, and MUST NOT infer a foreign entity's attributes from any field the Register does not carry.
AI-330 A labelled option AI Full Vision MAY be offered per AI position, granting that
position an unfogged view. Where offered it MUST be labelled as a cheat, disclosed under AI-100,
recorded in the game configuration and therefore visible in replays, and off by default in every
shipped preset (00-overview.md OV-110). It MUST NOT be bundled into any difficulty Rank, and the
setup screen MUST state that it changes what kind of opponent the seat is, not how well it plays.
Rationale, and a recommendation this document makes against its own option: full vision does not make the Staff harder, it makes it a different and much less interesting opponent. An AI that knows where everything is does not scout, does not screen, does not misjudge, and never plans against a Contact that turns out to be stale — so every behaviour that makes it readable (§16) disappears. It also violates AI-050's shared-vocabulary premise outright: no player can express "march confidently through fog to the exact tile where the thing you cannot see is standing." OV-110 requires the option to exist as a labelled, disclosed, recorded, off-by-default handicap, and this requirement provides it; AI-150's Foreknowledge is what should be recommended in the UI instead, and Open question 3 asks whether the option should be withdrawn entirely at the next overview revision.
AI-340 AI instances MUST be information-isolated from one another: no shared memory, no messaging channel, no shared belief state, and no host call that reveals another AI seat's internals. Two AI seats of the same personality MUST NOT coordinate implicitly. This game has no diplomacy (00-overview.md §4), and an emergent AI coalition would be a diplomacy system nobody chose.
6. The Staff — the layered architecture
6.1 The shape, and the bet it is making
┌──────────────────────────────────────────────┐
player view ────►│ L0 PERCEPTION builds the Slate, │
(fog-filtered) │ the Atlas, the Docket │
└───────────────────┬──────────────────────────┘
│ belief · places · candidate Operations
┌───────────────────▼──────────────────────────┐
│ L1 STRATEGY Track portfolio, │ exhaustive
│ Empire Stance, │ over ~8
│ theatre & industry budget │ candidates
└───────────────────┬──────────────────────────┘
│ objective weights · force budget
┌───────────────────▼──────────────────────────┐
│ L2 OPERATIONS assign formations to │ portfolio
│ Operations; set Postures, │ + local
│ Sanctions, Postings, │ search over
│ Requisitions, Tasks │ the Sandtable
└───────────────────┬──────────────────────────┘
│ plan → compiled order delta → Rehearsal
┌───────────────────▼──────────────────────────┐
│ L3 EXECUTION Postures & Sanctions, │ no search
│ in the core, identical │
│ for every seat (CM-100) │
└──────────────────────────────────────────────┘
══════════ THE CONSTRAINT FLOOR ══════════════════════════════════
garrison sufficiency · Cadre routing · Depot chains · transport lift
· air endurance · production continuity · no idle unit · no stranded
formation · retreat degree. FULL QUALITY AT EVERY RANK. NEVER DEGRADED.
The bet, stated before the machinery so it can be judged on its own:
This design does not try to out-search a human. It tries to out-administer one, never make a mistake a competent player would not make, and reason about the same handful of objectives a human reasons about — in the same vocabulary the human uses.
That is a smaller claim than "superhuman 4X AI" and a much more achievable one, for a reason specific to this game. Of the eight ways opponents in this genre visibly lose, seven are not search problems: leaving cities ungarrisoned is arithmetic; stranding transports and running aircraft out of endurance is constraint satisfaction; idle cities and misdirected reinforcement is scheduling; walking a column into a garrison it could have inferred is belief; fighting at bad odds is a solved arithmetic problem because 11-combat.md CB-2250 gives an exact predictor; and never noticing that an opponent is three turns from winning is impossible when 14-victory.md publishes it (VC-2280). Only two are search: picking the wrong axis of advance, and mistiming a concentration. The plan is to be perfect at the seven and spend the whole compute budget on the two. §21 is honest about how strong that makes us and about the one place it could ship weak.
AI-500 The Staff MUST be organised as four layers over one Constraint Floor, with the responsibilities, inputs, outputs and methods of the table below. A layer MUST NOT reach past the layer beneath it, and no layer MUST re-derive a quantity an owning specification computes in closed form.
| Layer | Input | Output | Method | Cadence |
|---|---|---|---|---|
| L0 Perception | the player view (AI-280) | the Slate (§8), the Atlas (AI-515), the Docket (AI-525) | incremental update, no search | every turn |
| L1 Strategy | Slate, Docket, Track state | Empire Stance, per-Track weights w_T, theatre force budget, Industry and Cadre policy |
exhaustive over ~8 surviving candidates | every k turns (AI-610), plus triggers (AI-545) |
| L2 Operations | L1 output, Docket, Formations | an assignment of formations to Operations, plus Postures, Sanctions, Postings, Requisitions, Consignments and Decisive-Point Tasks | portfolio of K seeds + steepest-ascent local search, scored through the Sandtable (AI-565) |
every turn, subject to commitment lock C |
| L3 Execution | the committed order records | unit behaviour | no search. 13-command.md CM-100's command layer, in the core | every activation |
| Constraint Floor | Slate, own state | obligations that are solved, not scored | exact algorithms (AI-560) | every turn, every Rank |
AI-505 L0 MUST be a pure function of the player view and the Staff's own persisted advisory memory (AI-460). It MUST NOT consume the rules PRNG streams, and MUST NOT depend on wall-clock time, host locale, iteration order of a hash container, or object identity (03-architecture.md AR-090, AR-100, AR-110).
AI-575 L3 MUST NOT exist as AI code. Unit-level behaviour under a Posture — how a Screen picks its tile, how a Survey chooses where to look, when a unit withdraws, what happens when a plan meets an obstruction — MUST be the core's, identically for every seat (13-command.md CM-100). The Staff MUST NOT ship a movement engine, a pathing policy, or a per-unit tactical search of its own.
Rationale: this is the cleanest structural win in the design and it costs nothing. A unit ordered
Screen by the Staff runs the identical CM-460 candidate-scoring loop as a unit ordered Screen by a
human. There is no AI movement engine to keep in sync with the rules, no class of bug where the AI's
units path differently, and no way for an AI's units to execute better than a human's — which is
CM-050's fairness contract, obtained by construction rather than promised.
6.2 How search stays tractable — counted honestly
This is the design's central structural advantage and it deserves arithmetic rather than a gesture.
The raw action space is not merely large; it is the wrong space. On a 1,000 × 1,000 map with ~300
units of our own, a unit with movement 4 on mixed terrain reaches roughly 25–45 tiles; add up to four
attack targets and four Stances (10-turn-model.md TM-630) and call it ~160 distinct per-unit
commitments. Jointly that is 160^300 ≈ 10^661. Restricted to the ~30 units a human actually re-orders
in a turn it is still 160^30 ≈ 10^66. Neither number is interesting, because under Orders and the
Cascade the raw space is not the player's action space at all. A player does not choose destinations;
they choose order policies (13-command.md CM-340: a Posture is a policy evaluated at activation, never
a recorded sequence of steps). The raw space is what the engine explores while executing a policy.
The command space, counted properly. The seat's actual action space per turn is a change to some subset of its command objects:
| Object | Reference midgame | Late large |
|---|---|---|
| Groups (13-command.md CM-860, ≤ 5 Formations each) | 4 | 10 |
| Formations (≤ 8 units each) | 15 | 50 |
| Unattached units — garrisons, Cadre, Depots, scouts | ~25 | ~90 |
| Postings (CM-1130) | 5 | 12 |
| Cities — Consignment, Template, Industry | 20 | 60 |
(Reference midgame: 200 × 200 map, 48 cities, 4 players, turn ~120, ~90 units — 14-victory.md's reference configuration, used throughout so the numbers are comparable to that document's.)
Per command object: six Postures (three for a Group) × ~8 feasible geometries × 3 Sanction presets,
less illegal combinations ≈ 60 legal assignments. Jointly, 60^19 ≈ 6 × 10^33 at reference midgame
and 60^60 ≈ 5 × 10^106 late-large.
AI-510 The specification MUST NOT claim that the command abstraction makes the action space
searchable, and no budget, schedule or Rank definition MAY be justified on that claim. The abstraction
takes 10^661 to 10^106. Both are infinite for our purposes.
Rationale: the branching-factor argument is seductive, correct-sounding, and about to be used to justify a small planner budget. Postures collapse the branching factor of issuing orders. They do not collapse the branching factor of planning, because good plans live above the vocabulary (§6.7). An AI that searches only over Posture assignments is searching a small space of mostly-bad plans, and it will be fast and weak.
What the abstraction actually buys is four things, each of which is what makes the search work:
- Moves become meaningful, so local search becomes possible. In a raw action space one move is "a
unit steps one tile", which changes the position by almost nothing, so hill-climbing is noise. In
posture-and-objective space one move is "III Corps stops screening the river and marches on Ash
Ford", which changes six units' behaviour for five turns by a computable amount. A space of
10^106with a smooth, sparse-interaction neighbourhood is a space local search does well in; a space of10^661with a meaningless neighbourhood is not. - Operations are mostly separable. Two formations' assignments interact only when they compete for the same objective or share a theatre, so a change can be scored as an Assay delta over a handful of terms rather than a full re-evaluation (AI-1050).
- The bottom layer is free. L3 is the game's code, not the AI's (AI-575).
- The geometry parameter is bounded by the Atlas, not by the map. This is the mechanism that turns an unbounded parameter into a finite one, and it is specified next.
AI-515 The Atlas. The Staff MUST NOT search raw geometry. All Posture geometry parameters MUST be selected from an Atlas: a graph of at most 256 nodes and at most 16 regions, built once at map load from the player view and maintained incrementally. Nodes MUST be drawn from: every known city; every Landmark (14-victory.md VC-1080, public from turn 1); every Region capital (VC-1030); every derived chokepoint; every friendly Depot; and each Formation's current anchor. Edges MUST carry an abstract integer path cost per movement class, obtained from the hierarchical chunk-boundary pathfinder of 03-architecture.md AR-750, and MUST be invalidated on terrain change, city capture, Depot change, or a supply-state change.
A Screen line is therefore "the frontage between node A and node B"; a March is "to node N"; a Survey is "region R"; a Garrison is "city C". Of ~16 regions, only ~8 are feasible for any one formation within the planning horizon, which is where the "~8 feasible geometries" in the count above comes from.
AI-520 Chokepoints MUST be derived deterministically and cached: on the chunk graph, a tile is a chokepoint if making its 8-neighbourhood impassable increases the abstract distance between two chunk regions by more than 3×. Where 01-game-rules.md's map generator can supply chokepoints directly, the Staff MUST use those instead of deriving them.
AI-522 Through fog, the Atlas MUST use 13-command.md CM-140's routing prior verbatim: an unrevealed tile is passable at the cheapest cost the movement class pays, and contains no enemy. This prior MUST NOT reach threat evaluation (AI-1100). The Staff plans optimistically and discovers the truth, exactly as a human does.
AI-525 The Docket. Candidate Operation generation MUST be rule-based, bounded, deterministic and hard-capped per kind, so the Docket cannot grow with map size or contact count. The caps MUST be:
| Kind | Generated from | Cap |
|---|---|---|
Seize |
enemy and neutral cities within horizon × pace of any formation |
64 |
Relieve |
own cities where the 2-turn threat field exceeds garrison value | 32 |
Screen |
Atlas edges crossing a believed approach corridor | 24 |
Deny |
any opponent in the Alarm band — sites are published with live vision (14-victory.md VC-2280, VC-2290) | 16 |
Claim |
open and announced Warrants; upcoming Tallies | 8 |
Raid, Interdict |
enemy Depots, Cadre Contacts, high-Industry rear cities | 24 |
Survey |
fog-frontier regions with unrevealed area | 12 |
Escort, Establish, Integrate, Besiege |
lift routes; Depot sites; un-integrated cities; fortified places | 24 |
| Total before filtering | ≤ 204 |
The Docket MUST then be filtered to at most 40 entries by value × 1000 / (cost + 1),
cross-multiplied rather than divided, ties broken by lowest Atlas node index. That filtered Docket is
what L2 searches.
AI-527 An Operation MUST carry exactly: a kind from the closed twelve-value vocabulary
(Seize, Relieve, Screen, Raid, Interdict, Survey, Escort, Establish, Integrate,
Besiege, Deny, Claim); a target that is an Atlas node, an Atlas edge, or a region; an integer
requiredForce computed by the exact predictor (AI-1030) against believed defence; a frontage
(AI-570); a (earliest, latest) turn window; an integer value and an integer risk, both Assay
deltas; and a template — the Posture and Sanction tuple to project onto whoever is assigned. Adding a
thirteenth kind MUST be a specification change here, not an implementation choice.
Rationale for Deny and Claim existing at all: they are the §6.2 argument made concrete. The Alarm
hands every player the address of the fight, so the correct response is not subtle — generate Deny
Operations against those exact sites at a value that dominates the Docket, because the alternative is
losing. Warrants and Tallies are announced with dates, so an AI that arrives at the Iron Gate on the
Tally turn, having started its march twelve turns earlier, reads as genuinely intelligent and is an ETA
lookup. The single hardest thing in strategic AI is deciding what matters, and 14-victory.md publishes
a calendar of it.
6.3 L1 — Strategy
AI-530 L1 MUST decide exactly three things every k turns and MUST evaluate them exhaustively
over the surviving candidates, because the space is small enough to:
(a) Track portfolio. An integer weight w_T per enabled Track, feeding Assay features A4 and A5.
The default schedule MUST key on the published visibility bands (14-victory.md VC-2200), so that the
Staff's strategic attention sharpens exactly when the game says it should and a watching player can
predict when it will:
| Highest band any player holds on that Track | w_T |
|---|---|
| Nobody above Rumour | 400‰ |
| Any player in Report | 1000‰ |
| Any player in Alarm, or any Vigil running | 2000‰ |
(b) Empire Stance. Exactly five values, which are 12-economy.md's central dilemma expressed as one enum:
| Stance | Effect on the Docket and the weights |
|---|---|
| Expand | Seize value ×1400‰; accepts un-integrated cities; Cadre purchases deferred |
| Consolidate | Integrate and Establish ×1600‰; Seize ×600‰; Cadre purchases prioritised |
| Strike | one theatre takes 70% of uncommitted force; Deny and Raid ×1500‰; cautious Sanction presets dropped |
| Defend | Relieve ×1800‰; Screen ×1400‰; Leashes halved; reserve fraction raised to 30% |
| Endure | play for Tenure: hold, garrison, deny, refuse engagements below 850‰ |
(c) Industry and Cadre policy, both of which MUST be computed as arithmetic rather than searched, using the owning documents' own closed forms: 02-units-and-industry.md's Industry payback for the upgrade decision, and 12-economy.md §11's Cadre cost curve for the next-Cadre decision. The Staff performs the sums those documents already state; it MUST NOT restate or approximate them.
AI-533 Cadre assignment MUST be scheduled by rate, not by total value:
priority = integratedValueGain × 1000 / (turnsToIntegrate + travelTurns), cross-multiplied.
Rationale: greedy-by-value sends every Cadre to a Metropolis and spends the longest integration time per Cadre, when in the same window several smaller cities would have been fully digested. This one expression probably beats any hand-tuned weight this subsystem will otherwise receive, and it is the kind of thing self-play discovers slowly and a designer discovers instantly.
AI-535 Strategic variables MUST carry hysteresis. Retasking a command object MUST cost the Assay's A27 term, and changing Empire Stance MUST additionally cost a flat penalty, so that a Stance flips only when the alternative is decisively better rather than marginally. An opponent whose army reverses direction every turn is both weaker and infuriating to play against.
AI-540 The Staff MUST condition its strategy on the enabled Tracks and on nothing else: it MUST NOT carry a hard-coded objective, and adding a Track to 14-victory.md's catalogue MUST give the Staff that Track's progress function and threshold for free through the uniform Track shape (VC-350). Under a Track keyed on a Seat, the Staff protects its own and threatens others'; under a threshold Track it races, denies and times against the Vigil clock; under a Tenure Track it plays the Ebb schedule backwards from the Horizon. Multiple simultaneous Tracks MUST be scored jointly.
AI-545 Re-planning MUST be trigger-driven, not unconditional. A full L1+L2 re-plan MUST run
when any of the following fires, and a cheap refinement otherwise: a city taken or lost; any Track
entering Report or Alarm, or a Vigil starting or breaking; a Formation destroyed or under strength; the
unaccounted-force estimate moving by ≥ 15%; a Warrant opening or a Tally six turns out; an Operation
completing or becoming Impossible (13-command.md CM-1340); the Assay falling by more than the Rank's
gradient threshold since the last plan; and unconditionally every 8 turns as an anti-staleness
floor.
Rationale: the triggers already exist and are free. 13-command.md CM-1610 requires the core to emit Attention Events deterministically, per player, from that player's fog-filtered view (CM-1850), which is a deterministic, fog-honest change detector the Staff can read at no cost. It does not depend on them for behaviour — CM-1630 forbids that, and AI-1310 restates the prohibition on borrowing the Dispatch's ranking — it uses them as a signal that something changed.
6.4 L2 — Operations: the search
AI-550 L2 MUST use portfolio search with steepest-ascent local search, in this order, with deterministic tie-breaks throughout:
for each of K strategic seeds: -- K by Rank (AI-610)
plan ← GREEDY_ASSIGN(Docket, Formations, seed weights)
plan ← LOCAL_SEARCH(plan, step budget / K)
for each opponent hypothesis H (1..Y by Rank):
outcome[plan][H] ← SANDTABLE(plan, H, depth D) → Assay at leaf
score[plan] ← RISK_WEIGHT(outcome[plan][*]) -- AI-1200
commit argmax score, ties by lowest plan seed index -- then AI-1220 mixing
Strategic seeds MUST be qualitatively different emphasis vectors over the same Docket — Seize-heavy, Defend-heavy, Deny-heavy, Economy-heavy, Tempo-heavy, and the L1 Stance's own weighting — not perturbations of one vector. Rationale: a portfolio of qualitatively different plans, each locally optimised, beats one plan optimised harder, because the seeds converge to genuinely different local optima. This is portfolio search and it is the right technique here for the same reason it is right in real-time strategy research: the space is too big to search but candidate strategies are few and enumerable.
AI-555 Greedy assignment MUST use integer, cross-multiplied fitness:
sufficiency = clamp(forceValue(F) × 1000 / requiredForce(O), 0, 1500)
timeliness = clamp(1000 − 80 × max(0, eta(F,O) − window.earliest(O)), 100, 1000)
fit(F,O) = value(O) × sufficiency × timeliness / 1000000
sufficiency MUST be capped at 1500‰ so that over-committing to an easy objective scores no better
than committing adequately — this is the anti-doom-stack term, and it works with AI-570. Assignment
MUST proceed by Docket value descending, ties by lowest Atlas node index; MUST skip any pairing with
fit < 200; MUST allow a second formation onto an under-strength Operation only up to that
Operation's frontage; and MUST place leftover formations as Reserve, then Screen on the nearest
uncovered frontage, then Survey — never Idle (13-command.md CM-540).
AI-557 Local search MUST use exactly these five move types, scored by Assay delta rather than by full Assay, with ties broken by lowest formation id then lowest Operation id: reassign one formation to a different feasible Operation; swap two formations' Operations; reinforce an under-strength Operation from the reserve; abandon an Operation, freeing its formations; escalate or de-escalate one assignment's Sanction preset. Estimated neighbourhood per pass: ~335 moves at reference midgame, ~1,905 late-large.
AI-559 The plan's commit MUST also write, in the same order delta: Posting anchors and weights
(13-command.md CM-1130) proportional to committed force × Operation value, normalised to [1, 10], so
that CM-1190's deficit round-robin delivers the reinforcement ratio without further AI involvement;
Requisition rows derived from the Operations assigned to each theatre; Consignments for cities
near a theatre; and one Doctrine per role archetype (CM-770, CM-790) so that newly produced units
arrive correctly ordered without a decision (CM-080).
Rationale: this is a genuinely large amount of AI work that simply does not have to exist. The Staff sets a ratio and the core delivers it, using the same scheduler a human's empire uses.
6.5 The Sandtable
AI-565 The Sandtable MUST be an abstract forward model at formation and city granularity — never per-tile, never per-unit — carrying per formation: Atlas node or edge with a progress fraction, aggregate attack and defence value, pace, supply state, current Operation, ETA; per city: owner, base Works, Integration, Unrest, garrison value, incoming threat; per player: Works and Manpower rates, Standing, Tenure, per-Track progress. It MUST step by: move along Atlas routes; resolve contested nodes and edges as one aggregate exchange (AI-570); flip cities and apply 12-economy.md's capture consequences exactly; advance the economy using 12-economy.md's closed forms; and recompute Track progress, Standing and Tenure at an abstract Seal using 14-victory.md's own functions.
AI-567 The Sandtable MUST NOT consume the rules PRNG. Aggregate exchanges MUST be resolved at fixed draws — the median for the mean case and the extremes for the risk band — so that the Sandtable is a deterministic function of the plan and the hypothesis.
Rationale: the Sandtable's economy is not an approximation at all — it is exact, because 12-economy.md's Works, Levy, Integration, Unrest and Cadre-cost functions are already integer and already closed-form (EC-060 forbids that document the PRNG entirely). That is a real and unusual advantage: most abstract forward models in this genre are wrong about the economy on the first step.
AI-570 Frontage limitation. An aggregate exchange MUST engage at most φ(n) × stackLimit
members, where φ(n) is the Operation target's frontage — the number of tiles from which the
target may legally be engaged — derived once from the map and stored on the Atlas node. Support
contributions MUST use the same aggregate shape 11-combat.md defines, so the Sandtable's arithmetic
and the real thing's do not diverge.
Rationale: the obvious way to fight two formations is to sum attack and defence and resolve one exchange, and that is wrong in a specific and dangerous way — it makes concentration free, so the AI learns to build a doom-stack, which is precisely the behaviour 11-combat.md and 13-command.md are designed to prevent. Frontage does two jobs at once: it makes the model honest about concentration, and it gives the Staff a reason to value chokepoints that falls out of the arithmetic rather than being asserted as a heuristic. An AI that defends a defile because the defile makes its numbers count is reasoning, not following a rule.
AI-572 The Sandtable's output MUST be treated as a ranking signal only. The Staff MUST NOT
carry a Sandtable projection forward as knowledge between turns; plans MUST be re-derived from the
current view at every trigger (AI-545), and the only thing carried between turns MUST be the switching
cost baseline (A27) and the commitment lock C.
Rationale, stated plainly because it is this design's largest single risk: the Sandtable has no terrain below the Atlas, no per-unit losses, no reactions, no interruptions, and no knowledge of what the opponent actually ordered. It will be wrong. §21.3's plan-ranking measurement (AI-1490) decides whether it is wrong in a way that still ranks correctly, and §21.3 names the fallback if it is not.
6.6 The Rehearsal
AI-585 After compiling a plan to orders and before committing them, the Staff MUST rehearse: run the compiled order set forward through a forked Cascade against the chosen opponent hypothesis and evaluate the result from its own seat's view. If the rehearsal shows the compilation did not express the plan — the concentration did not arrive together, the Screen did not cover the corridor, a Sanction declined the fight the plan required — the Staff MUST choose a different plan or a different compilation rather than commit a compiled shadow of a plan it liked better.
AI-587 The Rehearsal's opponent model MUST read only the acting seat's knowledge view. Where a hypothesis requires simulating an opponent's decisions, the opponent's modelled view MUST be constructed from the Staff's own Slate: the opponent is assumed to see what the Staff's units are within the vision radius of the Staff's own Contacts on them, to hold the force the Staff's force-accounting estimate says they hold (AI-1120), and to know the same published information. The Staff MUST NOT read true state to build an opponent model, at any Rank, under any option except AI-330.
Rationale: this is the one place where cheating would be invisible and catastrophic to trust — modelling an opponent's decisions requires modelling their view, and their view is not ours to read. AI-1400's fog-leak gate is what keeps a hundred small opponent-modelling changes honest over a project's lifetime.
Rationale for rehearsing at all: the Orders-and-Cascade model makes a turn a pure function of committed orders and frozen Initiative (10-turn-model.md TM-040, TM-150), so the Staff can simulate its own turn before committing it. Most strategy AIs cannot do this. The cost estimate this rests on — that a copy-on-write fork with activation memoisation brings a marginal Cascade to a small fraction of a full one — is the single load-bearing unmeasured assumption in this document and is Open question 5.
6.7 The planner's language is richer than the order vocabulary
AI-580 The Staff's plan representation MUST be separate from its order encoding. The planner MUST be able to represent, at minimum: objectives with deadlines; corridors and frontages; fixing forces; synchrony groups (these units strike in this Cascade or none of them do); retreat-degree constraints; refusal of a specific named city; and Operations valued by what they remove from an opponent rather than by what they gain. Each turn the Staff MUST compile the current plan down to Postures, Sanctions, Tasks, Postings and Requisitions, so that every unit ends the compilation holding ordinary orders indistinguishable from a human's, executed by the same command layer (13-command.md CM-100, CM-2040). The compilation MUST be treated as lossy, and AI-585's Rehearsal is what detects the loss.
Rationale, and it is the sharpest correction the red team made to this design. The Posture and Sanction vocabulary was sized for a unit panel: 13-command.md CM-330 fixes exactly six Postures and CM-230 fixes the stack at three levels, both with the stated reason that a deeper structure cannot be explained on a panel. Those are correct decisions for a human interface and terrible ones for a planner. Five things a good player conceives cannot be said in that vocabulary at all — simultaneity (CM-1010's cohesion radius is proximity, not synchrony); refusal of one specific city (CM-700's Seize is a policy over a class of cities); feints and fixing attacks, and crucially the ability to recognise one, since a demonstration is indistinguishable from an attack that has not happened yet; graph properties such as retreat degree, Depot-chain articulation, and corridor control, which are properties of the position graph rather than of any tile or unit; and timing, since no Posture takes a turn number and 14-victory.md's published Tally calendar exists precisely to make "be at the Iron Gate on turn 96" a plan. If the planner shares the order vocabulary it cannot conceive any of these, and the AI is fast and weak.
6.8 Playing any unit set
AI-590 All unit reasoning MUST derive from 02-units-and-industry.md's declared capability fields and closed flag vocabulary (US-380, US-470) and from the class enumeration (US-090). The Staff MUST NOT branch on a unit's identity, name or index, and MUST play any valid unit set competently. A unit whose capabilities give it no usable role in the active set MUST be garrisoned or escorted, never left without a Posture and never a planning crash.
AI-595 Setup MUST match an AI plugin's declared unit-set support against the selected set: a plugin
declaring any is always offered; a plugin declaring an explicit list is offered only for those sets,
and selecting it elsewhere is refused with an explanation rather than silently degrading.
AI-600 A custom unit set MUST NOT be able to carry executable code (02-units-and-industry.md US-2060, 07-modding-content.md MOD-300), so the Staff's declarative capability reasoning is always sufficient. A set author MAY ship AI hint data alongside a set — role annotations and weight overrides — and the Staff SHOULD consume it; a set with no hint data MUST still be played competently from capability data alone.
6.9 The Constraint Floor
AI-560 The following obligations MUST be solved, not scored, MUST run at full quality at every Rank, and MUST NOT yield to the step budget. Each MUST be exact arithmetic against the owning specification.
| Obligation | Method | Bound |
|---|---|---|
| Garrison sufficiency | 12-economy.md EC-1170 gives the requirement by class and Integration and EC-1200 the test. Compute required − present per city; deficits become Requisition shortfalls (13-command.md CM-1250, EC-1220) and Relieve Operations |
O(cities) |
| Cadre routing | AI-533's rate priority over the exact 12-economy.md formulas; escort mandatory wherever the route's threat field is non-zero | O(cadre × cities) |
| Depot chains | Set-cover maximising supplied tiles along the intended axis, subject to every Depot's own path home remaining intact; candidates capped at 64 tiles per axis | ≤ 64 per axis |
| Transport lift | 13-command.md CM-530's Ferry loop modes execute shuttles with no per-turn input; the Staff picks route endpoints and capacity only | O(routes) |
| Air endurance | A hard filter, never a scored decision: no sortie is generated whose return leg exceeds remaining endurance against a reachable base or carrier. An aircraft is never considered for a one-way trip | O(air × bases) |
| Production continuity | Every city always carries a Consignment or Template (13-command.md CM-1160, CM-1310); a newly captured city defaults to Auto and is therefore never idle |
O(1) per city |
| No idle unit | 13-command.md CM-540 raises an Idle event every turn. The Staff MUST treat any Idle as a hard defect and assign a Posture in the same turn |
O(events) |
| No stranded formation | CM-1440's Stalled detection is core-side and fog-honest. Two consecutive non-progressing turns MUST force the Operation to be abandoned and re-planned |
O(events) |
| Retreat degree | AI-1160 | incremental |
Rationale: most of what makes an opponent look intelligent is not intelligence. It is never doing the nine things in that table wrong. A shipped AI that gets all nine right at every Rank will read as far stronger than its search budget suggests, and one that gets any of them wrong will read as broken regardless of how good its planning is. This is also exactly 13-command.md CM-020's ledger split: Execution-ledger work is arithmetic and is always performed correctly; Commitment-ledger judgement is where an AI is allowed to be worse.
7. The Assay — the evaluation function
7.1 Scale and arithmetic
AI-1000 The Assay MUST be denominated so that one city = 100 points, on the same scale as 14-victory.md's Standing, so that every weight is interpretable — "a Cadre on station is worth nine-tenths of a city" — and the Assay and the game's own score cannot drift apart.
AI-1010 All Assay arithmetic MUST be exact integer arithmetic. Weights MUST be integers with a declared scale, expressed as per-mille multipliers on integer quantities, defaulting to 1000‰ so that the untuned origin is neutral. Ratio comparisons MUST be performed by cross-multiplication, never by division. No floating-point value MAY appear anywhere in the Assay, in the Sandtable, in the Docket, in local search, or in any weight file at rest or in memory. Where a divide is unavoidable it MUST be floor division toward negative infinity, matching 11-combat.md CB-070.
Rationale: this is deliberately stricter than what binds plugins in general — AI-385 requires only
that no float cross the ABI and 07-modding-content.md MOD-600 permits float arithmetic inside a guest.
The shipped Staff gives that permission up anyway, for a specific reason: the utility sum is the one
place an evaluator naturally reaches for floats, and it is also the value the self-play pipeline
reproduces across tens of thousands of farm games. A promotion result (AI-660) has to mean the same
thing on every machine that re-runs it, including the farm reproduction that adjudicates a dispute
three years from now. A tuned weight of 0.734 is a different number on two decimal-to-binary paths; a
tuned weight of 734 per-mille is the same number everywhere, forever.
AI-1020 Every number the Staff uses to make a choice MUST live in a versioned parameter manifest — named integers with declared ranges, a declared scale, and a content hash — and MUST NOT be a constant in code. An AI whose thresholds are code constants cannot be tuned, cannot be A/B tested, cannot ship two Ranks from one binary, and cannot have a promotion gate, because there is nothing to promote.
7.2 The features
AI-1030 The Assay MUST be a weighted integer sum over the following feature set. press(p) is the
shared convexity function that makes progress near a threshold worth disproportionately more, with p
in per-mille of the threshold:
press(p) = p for p < 500
500 + 2 × (p − 500) for 500 ≤ p < 900
1300 + 6 × (p − 900) for p ≥ 900
| # | Feature | Definition | Default weight |
|---|---|---|---|
| Territory and victory | |||
| A1 | Cities held | 100 × cities |
1000‰ |
| A2 | Landmarks | 150 × landmarks |
1000‰ |
| A3 | Seats | 200 × seats held |
1000‰ |
| A4 | Track pressure | Σ_T w_T × press(p_T) / 1000 |
1000‰ |
| A5 | Track denial | − Σ_T Σ_opp 3 × w_T × press(p_opp,T) / 4000 |
1000‰ |
| A6 | Vigil equity | +400 × held/required (mine), −600 × held/required (theirs) |
1000‰ |
| Economy | |||
| A7 | Integration stock | 3 × Σ_cities (baseWorks × integration / 100) |
1000‰ |
| A8 | Integration slope | 2 × Σ_cities (projected Δintegration over 10 turns × baseWorks) / 100 |
1000‰ |
| A9 | Levy rate | 20 × manpowerPerTurn |
1000‰ |
| A10 | Production rate | 8 × worksPerTurn |
1000‰ |
| A11 | Industry depth | 40 × Σ_cities (industry − 1) |
600‰ |
| A12 | Cadre on station | 90 × cadre stationed where unrest < 50 |
1000‰ |
| A13 | Occupation drag | − Σ_foreign cities (100 − integration) × baseWorks / 100 |
1000‰ |
| Force | |||
| A14 | Force value | Σ_units cv(u) × mobility‰ / 1000, where cv(u) = cost × max(0, 100×strength − 50×disorder) / 40000; mobility 1000‰ mobile, 500‰ immobile |
1000‰ |
| A15 | Supply state | − Σ_units cost × penalty‰ / 400000 |
1000‰ |
| A16 | Veterancy | + Σ_units grade × cost / 200 |
600‰ |
| A17 | Lift capacity | + 30 × min(transportSlots, unitsNeedingLift) |
800‰ |
| Position | |||
| A18 | Garrison shortfall | − 200 × Σ_cities max(0, required − present) |
1000‰ |
| A19 | City threat | − Σ_cities threat[city][2] × cityValue / 4000 |
1000‰ |
| A20 | Seat exposure | − 800 where the 3-turn threat at a Seat meets or exceeds its garrison value |
1000‰ |
| A21 | Frontier opportunity | + Σ_takeable cities cityValue × takeProb‰ / 4000 |
800‰ |
| A22 | Reach coverage | + 2 × supplied tiles within 6 of the contested band |
400‰ |
| A23 | Chokepoint control | + 60 × held chokepoints on an active axis |
1000‰ |
| A24 | Observation | + 1 × currently-observed tiles in the contested band |
200‰ |
| A25 | Unaccounted enemy force | − unaccounted Works / 8 |
1000‰ |
| A28 | Retreat degree | − 150 × own stacks at retreat degree ≤ 1; + full target stack value where an attack drives an enemy stack to degree 0 |
1000‰ |
| A29 | Strategic-asset exposure | − replacementCost × P(loss within 6 turns) / 1000 over Cadre, Depots and high-Industry rear cities |
1000‰ |
| A30 | Trend | signed 20-turn deltas of mean Industry, total Works, Cadre count and integrated-city count, each scaled | 1000‰ |
| Hygiene | |||
| A26 | Idle or stalled | − 40 × (idle formations + stalled formations) |
1000‰ |
| A27 | Switching cost | − 25 × command objects retasked this turn |
1000‰ |
AI-1032 cv(u) MUST equal cost / 4 at full strength and zero disorder, matching 14-victory.md's
military Standing term, so that a healthy army is worth the same in the Assay as on the scoreboard.
Disorder MUST cost half as much per point as missing strength, mirroring 11-combat.md's resolve
arithmetic inverted — their disorder helps the evaluating seat and its own hurts it.
AI-1034 Features A28, A29 and A30 MUST NOT be omitted at any Rank at or above the Rank that introduces them (§13.2), and A28's defensive half MUST additionally be enforced by the Constraint Floor at every Rank (AI-1160).
Rationale for the three additions to the original 27: each closes a failure this design's own systems create. Retreat degree (A28) is a property of the position graph, not of any tile or unit, so a tile-and-unit evaluator is blind to it in both directions — it neither notices its own stacks losing their last exit nor notices that one move would take an enemy stack's — and 11-combat.md CB-050 makes that the largest single swing in tactical play. Strategic-asset exposure (A29) exists because 12-economy.md's Administrative Cadre is simultaneously the anti-snowball engine and the softest target in the game, and rear-area security is exactly the region of a per-turn utility landscape that is systematically under-served. Trend (A30) exists because several of this game's worst outcomes are monotone ratchets — a captured city drops an Industry level and recapture does not restore it — and a level-only evaluator sees each event as a small negative while twelve of them are a collapsed industrial base.
AI-1040 The Staff MUST NOT compare its own Assay to an estimate of an opponent's Assay. Opponent standing MUST enter only through A5, A6 and A25, in the evaluating seat's own currency.
Rationale: cross-player evaluation comparison is a classic source of nonsense in this genre — my 4,000 and your 4,000 are not commensurable when we hold different things under different fog — and refusing to do it costs nothing.
AI-1050 The Assay MUST be decomposable into independently computable term groups keyed by entity, so that a local-search move can be scored as a delta over the few terms it touches. Full Assays MUST be computed only at Sandtable leaves. Estimated budgets, labelled as estimates: full Assay ≤ 15 µs at reference midgame and ≤ 60 µs late-large; one delta ≤ 3 µs.
AI-1060 Every committed plan MUST emit an Assay decomposition into the Intent Record (AI-750): the total, every non-zero feature's contribution, the chosen seed, and the top three rejected alternatives with their scores and the terms that separated them.
8. Belief — the Slate
8.1 Two priors, because one is wrong in one of its two jobs
AI-1100 The Staff MUST maintain two distinct priors over unrevealed space, and MUST NOT use one for both jobs:
(a) Routing MUST use 13-command.md CM-140's optimistic prior — an unrevealed tile is passable at the cheapest cost and contains no enemy (AI-522).
(b) Threat evaluation MUST use a pessimistic occupancy prior: unrevealed space MUST be treated as potentially containing the unaccounted enemy force of AI-1120, distributed over unobserved chunks weighted by reachability from last-known Contact positions and from believed enemy cities.
Rationale: CM-140 is a good requirement with a good rationale — pessimistic routing produces units that refuse to cross unexplored ground, which is behaviour no player would ever choose. The danger is that the same assumption reaches evaluation, where it means every unexplored region is a free approach corridor in the AI's model and an actual approach corridor in reality. An AI that asks "is my flank safe?" over a knowledge view in which unknown means empty concludes that its flank is always safe. This is expected to be the source of most "the AI got flanked by an army that walked through the obvious gap" reports, and it is expected to be misdiagnosed as a pathfinding or scouting bug rather than as a belief-representation one.
8.2 Contacts are discs, not points
AI-1110 A Contact of age k MUST be treated in threat evaluation as a disc of radius
k × lastKnownMovement, capped at a horizon, rather than as a point. Contact weight MUST decay with
age on a published integer curve — the default is clamp(1000 − 120 × age, 200, 1000) per-mille, so a
four-turn-old Contact counts at 52% and a six-turn-old at 28%, floored at 20% — and a Contact MUST NOT
be deleted merely for being old, only aged, within whatever 01-game-rules.md's own decay rules leave in
the Register.
Rationale: this is the single most valuable belief decision available and it costs one integer per Contact and a radius comparison. Both naive alternatives are bad in recognisable ways. Markers that never expire produce an AI that defends against ghosts, pinning units against an enemy that left thirty turns ago — paranoia, and a garrison sink that compounds with the turtling failure of §18. Markers that expire immediately produce an AI repeatedly surprised by forces it has already seen. A disc changes the shape of the AI's defence from "a unit at every remembered contact" to "a reserve that can reach any of them," which is also what a good human does.
AI-1112 The Staff's threat field MUST be a per-chunk integer grid — 64 × 64-tile chunks, one
plane per horizon h ∈ {1, 2, 4, 8} turns, optionally one set per opposing player — summing reachable
Contacts' combat value scaled by age decay, plus the spread of unaccounted force. City-level decisions
MUST NOT use the chunk grid; they MUST use an exact per-city query over Contacts reachable within h
turns along the Atlas.
8.3 Reasoning about what has never been seen
AI-1120 The Staff MUST maintain an integer unaccounted force estimate per opposing player, derived only from information the game publishes to every seat and from the Staff's own observations:
believedCities(P) from the published band (14-victory.md VC-2200, VC-2250), band midpoint ± width
believedWorks(P, t) = believedCities(P, t) × own observed Works per city
believedProduction(P) = Σ over turns of believedWorks(P, turn), carried incrementally
militarySpend(P) = believedProduction(P) × militaryShare‰ − believedCadreSpend − believedIndustrySpend
unaccounted(P) = max(0, militarySpend(P) − observedAliveValue(P) − confirmedDestroyedValue(P))
The estimate MUST feed Assay feature A25 and MUST bias Sanction selection: a high unaccounted estimate
pushes the Staff toward cautious presets, larger reserves, Screen over March, and shorter Leashes.
Rationale: this is what a strong human does with the same information, and it is fog-honest by construction because every input is either published (VC-2200's bands, the public city count) or observed. It produces the correct relationship — the AI becomes cautious because it is ignorant — and that is legible: a player can watch the AI stop expanding after a scouting raid revealed a rival's army and understand exactly why. A hostile note against it: a human who understands this estimator can inflate the AI's fear by holding cities they cannot defend, or deflate it by hiding production. That is a bluffing surface rather than a defect, it is symmetric, and it is far better than an AI with no model of the unseen at all — but AI-1450 measures whether the equilibrium is interesting or degenerate.
8.4 Turning an unknown into a reconnaissance objective
AI-1130 Where an Operation's outcome pivots on a single unobserved field, the Staff MUST generate a reconnaissance Operation against that specific unknown, valued at the swing in the pivot, rather than guessing. 11-combat.md CB-2330 evaluates over the full domain of an unobserved input and CB-2340 performs pivot analysis over each unobserved field with an enumerable domain; the Staff MUST consume that pivot output directly.
AI-1132 A Contact that has been continuously visible for 3 turns without its fidelity improving MUST be treated as class-typical rather than as unknown for avoidance purposes, and MUST raise a reconnaissance obligation rather than an avoidance response.
Rationale: without this the Staff deadlocks by construction. Scouts avoid unidentified Contacts; Contacts stay unidentified because scouts avoid them; and AI-522's optimistic routing prior then tells the Staff that the unexplored region is empty. The AI ends up confidently blind precisely where the enemy is, and the behaviour reads as caution rather than as a bug. §18 E1 gives the exploit this closes and AI-1400's tripwire table gives the counters that detect it.
8.5 Step changes in information
AI-1140 A transition into or out of the Alarm band — the Staff's own or any opponent's — MUST be an unconditional full re-plan trigger (AI-545). When an opponent enters Alarm, 14-victory.md VC-2290 grants every player live vision of the Bellwether sites for the duration plus two turns; the Staff MUST re-plan immediately rather than drifting toward the new optimum over ten turns and arriving after the grace period expired. When the Staff itself enters Alarm, it MUST re-price its own hold probability to account for its garrisons now being public.
8.6 Graph properties the Staff must hold explicitly
AI-1160 The Staff MUST maintain an integer retreat degree per friendly stack — the count of tiles that pass 11-combat.md's retreat-destination filter (CB-1310, CB-1120) as computed from the Staff's own knowledge view (CB-1360) — updated incrementally when an adjacent tile's occupancy changes. Retreat degree ≤ 1 MUST raise a Constraint-Floor obligation (AI-560) rather than merely contributing a score, and an attack that drives an enemy stack's retreat degree to 0 MUST be valued at the full value of that stack rather than at expected losses (A28).
AI-1165 The Staff MUST maintain a stack liability term: the total value in a friendly stack multiplied by the probability that its retreat degree reaches 0 within the horizon. Stack liability MUST be consulted both defensively, before stacking, and offensively, before declining an attack on a stack whose top defender is unfavourable but whose exits are few.
AI-1170 The Staff MUST have access to an incremental supply oracle: the ability to answer "what does Reach look like if this tile changes hands" without a full re-propagation of 12-economy.md's flood fill (EC-1560). Where an implementation cannot provide one, the Staff MUST NOT evaluate supply-cut Operations at all rather than evaluate them from stale data.
Rationale: cutting a supply chain at an articulation point is one of this game's strongest moves, and a naive implementation that recomputes propagation per candidate is either unusably slow or quietly supply-blind. Supply-blind is far worse and far more likely, because it is invisible — the AI simply never plans an encirclement and nobody can say why. Refusing to evaluate is honest; evaluating from stale data is not.
AI-1180 The Staff MUST maintain a horizon estimate — expected remaining turns — computed from 14-victory.md's published Ebb schedule and the Horizon, and MUST price every option whose correctness depends on remaining game length against it. An option that repays over a longer window than the horizon estimate MUST NOT be taken, and an option that is a deliberately bad trade taken only when losing MUST NOT be taken while the Staff leads.
Rationale: this class of decision — "am I about to lose?" and "how long will this game last?" — has no term in a naive evaluator, and 14-victory.md has already handed the answer over: the Ebb schedule is published from turn 1 and is a closed form, the Horizon is a hard backstop, and VC-2600 through VC-2620 make the elimination arithmetic exact. An AI that presses a loser's button while winning reads to a player as broken.
9. Commit before you see
The Staff issues orders blind, against the board as the previous Reckoning left it (10-turn-model.md
TM-030, TM-340), exactly like every other seat. docs/design/01-decision-turn-model.md names the
conditional vocabulary as the model's largest execution risk. For the Staff it is also the largest
opportunity, because unlike a human it can afford to actually evaluate the branches.
9.1 Hypotheses and risk
AI-1200 The Staff MUST evaluate each candidate plan against Y opponent hypotheses (Y by Rank)
and MUST combine them by an integer risk-weighted score:
mean = Σ_H outcome[H] × prior[H] / 1000
worst = min over H of outcome[H]
score = mean − k × (mean − worst) / 1000
The hypothesis set MUST be drawn from: Passive (every Contact holds; production continues; prior 250‰), Continuation (every Contact keeps its last-observed heading and pace, and unaccounted force appears on the shortest axis toward the Staff's weakest city; prior 500‰), and Best reply (a shallow Staff run for the opponent over the modelled view AI-587 constructs; prior 250‰). Best reply MUST be available only at the top Ranks.
AI-1210 k is the caution coefficient, an integer per-mille, and MUST be a personality dial
(§14). At k = 0 the Staff is an expected-value maximiser that will bet the game; at k = 1000 it is
a pure minimaxer that never attacks. The shipped baseline MUST be 500‰.
Rationale, because this single integer is doing the strategic work 12-economy.md was built to create.
A blitzing position — many cities, most of them barely integrated, thin garrisons, a long amber supply
frontier — evaluates higher on the Assay than a consolidated one, and that is correct: it is worth
more. The mortgage does not show up as a lower level. It shows up as spread. Under the Passive
hypothesis "keep expanding" scores brilliantly; under Continuation with a large unaccounted force it
scores badly, because un-integrated cities have thin garrisons, a broken Reach chain isolates a whole
axis, and 12-economy.md's Loyalty memory means every one of those cities snaps back to full value the
moment its original owner walks in. So a Staff at k = 300‰ keeps expanding and sometimes gets away
with it; at k = 750‰ it consolidates; and at k = 500‰ it expands while the unaccounted-force
estimate is low and consolidates when it rises. That third behaviour is the one we want, it is emergent
rather than scripted, and it is legible.
AI-1215 City valuation MUST include the value a capture would hand back to its original owner on recapture:
value = expectedIntegratedWorks × P(hold ≥ N turns)
− garrisonCost − cadreOpportunityCost
− recaptureValueToOriginalOwner × P(they retake it)
and the Staff MUST be able to decide not to take a specific city — which requires the planner language of AI-580, because 13-command.md CM-700's Seize Sanction expresses a policy over a class of cities and cannot name one.
9.2 Mixing, because a pure strategy is a solved strategy
AI-1220 The Staff MUST mix over plans, never over actions. Given candidate plans scored as
descending integers with best = score[0]:
keep i where score[i] × 1000 ≥ best × (1000 − EPS) -- EPS default 50 (5%)
weight[i] = score[i] − floor(best × (1000 − EPS) / 1000) + 1 -- integer, ≥ 1
r = hash64(salt, turn, playerId, "plan") mod Σ weight[i]
select the first i whose running weight sum exceeds r
The draw MUST be positionally addressed on (salt, turn, playerId, slot) rather than taken from a
stream cursor, so that it is unaffected by the order in which the Staff happens to evaluate things.
AI-1225 The mixing salt MUST be a separate secret value generated at game creation, stored in
the save so that replay and farm reproduction are exact, and never displayed. It MUST NOT be
derived from the game Seed, which is conventionally shown at setup.
Rationale: this is the load-bearing detail and it is easy to get wrong. If the mixing stream derives from the visible seed, a determined opponent holding a copy of the binary can compute the Staff's plan choice offline and the mixing has bought nothing. In ranked AI-versus-human play, where replays must verify, the salt needs a commit-reveal — its hash published at game start, the salt itself at game end — which is Open question 8.
AI-1230 Mixing MUST NOT reach: retreat-degree checks, supply state, garrison thresholds, Cadre escort decisions, air endurance, or anything else in the Constraint Floor (AI-560). The Staff MUST mix over aggression and axis of advance, never over survival.
Rationale: a player who watches an AI randomly abandon a garrison concludes the AI is broken, and they are right. Against a non-adaptive opponent mixing is a pure loss — the Staff sometimes takes its second-best plan. The case for it is that a human learns the AI's policy across turns and across games while the AI does not learn theirs within a game, and Orders and the Cascade makes each turn a simultaneous-move game in which a pure strategy known to the opponent is dominated by the best reply. That is not a heuristic worry; it is the definition of exploitability.
AI-1235 The mixing width EPS MAY be adaptive within a game, raised when a cheap regret signal
fires (repeated net-loss outcomes from plans of the same class) and lowered while the Staff is winning.
This MUST be the only online adaptation the Staff performs, and it MUST change how much the Staff
mixes, never what it believes (AI-680).
9.3 Strategic route selection
AI-1240 The Staff MUST randomise among near-cost-equal strategic routes: it MUST enumerate Atlas routes within 110% of the cheapest and choose by seeded draw from its own stream, keeping the choice replay-exact.
Rationale: 03-architecture.md AR-750 requires deterministic pathfinding with tie-breaks on lowest tile index, and 14-victory.md publishes the Tally calendar 24 turns ahead. Together those hand an opponent three things — where the Staff must be, when, and by which route, computable to the tile — and pre-placing entrenched reaction units on that corridor is a free ambush. This is the clearest case in the design where determinism of the engine and predictability of the agent must be separated: the engine must be deterministic for replay; the agent must not be predictable to an opponent holding the same rules.
9.4 Using the activation order the Staff is entitled to
AI-1250 The Staff MUST attach a condition to every committed order whose target is contestable, and its measured stance-fallback rate MUST be at or below the human median (AI-1420). The Staff MAY assign contingent Operations preferentially to low-Initiative formations, whose orders are evaluated against more of the turn (10-turn-model.md TM-280), and races for fixed objectives to high-Initiative formations; and MAY select Formation commanders for activation freshness under 13-command.md CM-960. All of this MUST use only its own units' relative order (AI-040).
Rationale: an AI can afford to enumerate conditions and a human cannot. If the Staff's stance-fallback rate is above the human median, the conditional vocabulary is buying the AI nothing and the central bet of the turn-model decision has failed on the AI side specifically — which is a finding worth having early, and AI-1420 is what surfaces it.
AI-1260 The Staff SHOULD solve a small deterministic set cover for reaction screens: for each believed approach corridor into its territory, place at least one unit in a Stance that carries a live reaction adjacent to it. Candidates MUST be bounded — at most 64 corridors and 256 candidate tiles — with deterministic tie-breaks.
Rationale: this costs almost nothing and produces the single most "how did it know" behaviour available in this turn model — a picket line stopping a raid it could not have seen coming, because it was covering the corridor rather than the unit.
10. Budgets — work units, not wall clock
10.1 The rule everything else rests on
AI-405 The Staff's internal budget MUST be an integer step counter, never a clock. A step is one unit of declared work — one Assay delta, one Sandtable turn, one greedy marginal, one exact combat preview — each with a declared integer cost. A Rank's budget MUST be a fixed integer step count, and the search MUST be structured so that a complete legal plan exists after greedy assignment and every subsequent local-search move is optional, so that truncation at the step count always yields a committable plan.
AI-415 The Staff's decision procedure MUST be a total function of (player view, configuration, Rank, salt). Elapsed time MUST NOT be an input. There MUST be no iterative deepening cut off by a clock, no "spend the remaining milliseconds", and no adaptive work count. A slow device MUST take longer; it MUST NOT play worse.
Rationale, and the reconciliation of two proposals that appeared to disagree: the search is anytime in structure — it can stop at any checkpoint and commit — but the stopping point is a fixed integer step count, not a deadline. Three things fall out, and they answer three separate questions at once. Phone versus desktop versus farm becomes one knob: same code, same algorithm, different integer step budgets, so there is no mobile AI and no farm AI, only one AI with a number. Determinism survives time-boxing, because truncation happens at the same step on every machine — a wall-clock budget would make a faster computer play a stronger game, which is a fairness defect in multiplayer and makes the self-play farm irreproducible since the same experiment would explore a different search on every host. And difficulty stays honest, because difficulty is the step budget plus knowledge discipline rather than a hidden bonus. Wall clock survives only as the fault watchdog of AI-420.
AI-417 A device that cannot complete a Rank's step budget within its watchdog MUST NOT offer that Rank, and the setup screen MUST say so ("this device supports up to Colonel"). It MUST NOT silently run a weaker version of a Rank. Desktop headroom buys more Ranks, never a secretly stronger Captain.
10.2 The budget table
AI-400 The host MUST enforce a per-turn budget with a soft target and a hard cap, configured per context, with every value disclosed in the lobby and recorded in the game configuration:
| Context | Soft target (default) | Hard cap (default) | Enforced quantity |
|---|---|---|---|
| Local interactive game | the Rank's step budget; wall-clock calibration target 2 s + 10 ms × own-unit count, max 15 s | 60 s watchdog | steps for the shipped Staff; fuel for a plugin where AI-410 requires it, otherwise the AI-420 watchdog |
| Real-time multiplayer, server-run | lobby-configured, default 10 s calibration target | 30 s watchdog | steps; fuel for plugins |
| Correspondence / cloud turn | 60 s calibration target | 300 s watchdog | steps; fuel for plugins |
| Simulation farm and tuning | experiment-configured | experiment-configured | steps; fuel for plugins |
The seconds in this table are calibration targets on REF-HW (03-architecture.md AR-700), not the enforced quantity. The enforced quantity is the Rank's step budget for the shipped Staff and the fuel figure of AI-410 for a plugin; it is that figure, with the transform id and version, that the recorded game configuration carries (03-architecture.md AR-857).
AI-610's step budgets, and estimated wall-clock cost on REF-HW headless. Multiply by 2× for a browser tab and 2× again for a 2019-class ARM device, per AR-700. Every millisecond figure is an estimate.
| Rank | Step budget | Est. ms, reference midgame | Est. ms, late large |
|---|---|---|---|
| Cadet | 1,500 | 3 | 12 |
| Lieutenant | 6,000 | 10 | 40 |
| Captain (default) | 25,000 | 35 | 140 |
| Colonel | 80,000 | 100 | 400 |
| General | 160,000 | 200 | 800 |
| Marshal | 250,000 | 300 | 1,200 |
AI-407 The latency that mostly is not there. The Orders phase is concurrent and the board is stable throughout it (10-turn-model.md TM-340), so the Staff MUST begin planning as soon as the new views are published and MUST run off the UI thread (AI-440). In solo play the Staff's latency is therefore hidden behind the human's own thinking and behind Cascade playback. The Staff MAY additionally use 10-turn-model.md TM-2550's rolling planning on the same terms a human client does: once a unit has activated in turn T's Cascade, planning for T+1 may begin, subject to TM-2570 — nothing reaches the core until the next Orders phase opens.
10.3 Degrading without a cliff
AI-457 Where a platform cannot afford a Rank's full search, the quality knob MUST be the breadth of the plan portfolio, never the depth of the Constraint Floor and never the belief model. The Staff MUST degrade by evaluating fewer strategic seeds with shallower Sandtable depth, and MUST NOT degrade by dropping opponent hypotheses to one, dropping the belief filter, or dropping rollout to zero.
AI-458 Plan continuation MUST be the default. The Staff MUST keep the previous turn's plan and re-validate it cheaply, running a full re-plan only on an AI-545 trigger. The measured full-re-plan rate MUST sit at or below 20% in steady state (AI-1430).
Rationale: under budget pressure a team cuts in order of visibility rather than value — rollout depth first, then hypothesis count, then opponent modelling, then belief maintenance, which is the least visible of all. The first two are phase changes, not degradations: at rollout depth 0 the Staff is a greedy per-unit scorer and every exploit in §18 becomes available at once, and at one hypothesis it is a pure strategy and therefore maximally exploitable. So the honest answer to "does it degrade gracefully on a phone" is no, not unless the knob is changed — and changing the knob to portfolio breadth makes the mobile AI narrower, not dumber, with a floor of "a competent operational plan, executed coherently" rather than "greedy per-unit scoring." AI-1460 turns that into a shipping gate.
10.4 Memory
AI-435 The Staff's working set MUST be dominated by structures whose size is independent of unit count and nearly independent of map size — the Atlas and its cached distances, the chunk threat field, the Contact ledger, the Docket, the plan store, and the Sandtable's working state — and MUST remain under 4 MiB at every scale and every Rank. Estimated composition at the largest map: Atlas nodes plus all-pairs distances across three movement classes ≈ 384 KB; threat field ≈ 32 KB; Contact ledger ≈ 13 KB; Docket ≈ 13 KB; plan store ≈ 17 KB; Sandtable working state ≈ 200 KB.
Rationale: this is the happy consequence of the abstraction, and it arrived before any of the others. The Staff reasons about formations and places, not units and tiles, so its memory is structural rather than proportional.
AI-430 An AI plugin instance's linear memory MUST be limited by the declared maximum of its
WebAssembly.Memory, so a growth attempt past it traps in the engine rather than being discovered by
host bookkeeping. Defaults and caps:
| Platform class | Default per instance | Manifest-requestable cap | Aggregate, all AI instances |
|---|---|---|---|
| Server (Node, REF-HW class) | 256 MiB | 1 GiB | 2 GiB |
| Desktop client (Tauri web view or browser tab) | 256 MiB | 1 GiB | 2 GiB |
| Mobile client (Tauri web view, 2019-class ARM) | 128 MiB | 512 MiB | 768 MiB |
AI-instance memory is additional to 03-architecture.md's simulation-state budgets and MUST be accounted separately. A manifest request above the platform cap MUST NOT be a load failure: the host MUST grant the cap, warn at setup, and let the plugin degrade. Exceeding the granted limit is a fault under AI-240. On every client platform the AI aggregate shares one process with the whole UI and the AI-235 core replica, so the host MUST treat the aggregate cap as a hard client-wide budget and serialise AI turns rather than approach it. These numbers are engineering estimates and Open question 11 tracks their measurement.
AI-440 AI computation MUST run off the UI thread — a Web Worker in the client, a worker_threads
worker on the server — and the client MUST remain responsive and MAY show progress. Worker isolation is
an enforcement mechanism, not only a responsiveness measure: it is what makes AI-420's interrupt
possible at all, and what keeps a runaway plugin from freezing the client's render and input loop. The
worker MUST hold the plugin instance and, where one exists, the AI-235 core replica, and the host MUST
be able to terminate it unilaterally at any point and recover under AI-240.
AI-450 Parallel evaluation MUST be a host service rather than plugin threads: a batch call that runs each task by invoking the plugin's pure evaluation export on isolated instance copies across available workers, returning results in submission order. Results MUST be bit-identical regardless of worker count or scheduling, and batch fuel cost MUST be the deterministic sum of task fuel costs. Plugins MUST NOT be given raw threading primitives, and the service MUST NOT be implemented with WASM threads or shared memory (AI-380(a); also, that would force cross-origin isolation on the web client). Where workers are unavailable (03-architecture.md AR-860), the batch MUST execute sequentially in submission order with identical results and identical fuel accounting; only wall-clock time differs.
10.5 Headless operation
AI-470 The Staff and every shipped AI MUST run fully headless — no UI, GPU, DOM or platform-service
dependency — under Node on Linux servers against @everylastcity/core, in the simulation farm
(03-architecture.md AR-970), in CI, and in a browser worker with no DOM access. The plugin host MUST be
a single implementation across all of those; the only permitted environment-specific code is the worker
primitive of AI-440 and the module-loading path, both behind one interface.
Rationale: the farm and the client must exercise the same host, or the farm's determinism evidence says nothing about what players run.
AI-475 The CLI MUST provide the farm drivers this document's pipeline needs on top of 03-architecture.md AR-810's existing verbs: a head-to-head match driver supporting fixed-N and sequential testing; a gauntlet driver scoring a candidate against an anchor pool; and a tuning driver that emits matches and consumes results under a named optimiser. Every job MUST be content-addressed by a hash of its own inputs — map spec, game seed, ruleset, victory terms, per-seat agent and manifest and model hashes, pair index, hashing policy — so that a disputed result is re-runnable by anyone with the same build.
11. Determinism and replay integrity
11.1 What is already settled, and what it buys
AI-350 Every order an AI seat submits MUST be appended to the authoritative order log exactly as a human's is, in the same envelope (03-architecture.md AR-250, AR-260). A replay MUST NOT re-invoke AI code (10-turn-model.md TM-2420); replays and desync checks derive purely from the order log and are exact regardless of AI determinism. No AI-produced datum MAY exist only in the derived event stream, because events are a re-derivable cache and never authoritative (AR-250).
Rationale, and the consequence worth naming: this decouples AI determinism from replay exactness, which
means an experimental AI cannot corrupt a saved game, and it means the AI can improve every release for
the life of the product without invalidating a single replay. Contrast 13-command.md CM-2050, where
changing how a Screen picks its tile is a rules change with a commandLogicVersion bump. Command-layer
changes are expensive and rare; AI changes are cheap and continuous, and whoever schedules the work
should know that.
AI-352 A change to the Staff's weights, evaluation model or planner MUST NOT bump
commandLogicVersion (13-command.md CM-2050) and MUST NOT be a RulesVersion change
(03-architecture.md AR-880). The command layer decides what a Posture does; the Staff only decides
which Posture it sets, and setting a Posture is an ordinary order any human could issue.
11.2 Where AI determinism is required anyway
AI-360 Every shipped AI MUST be strictly deterministic: given the same view sequence, options, advisory memory, salt and seed, it MUST produce an identical order sequence on every platform. Shipped AIs MUST take all randomness from AI-390's streams. The only budget observation any plugin may make is fuel, which is deterministic, so a shipped AI MAY shape decision content on it; there is no wall-clock observation in the ABI to depend on (AI-210).
AI-362 AI determinism is required for four things replay exactness does not give: farm reproducibility, desync arbitration, bug reproduction, and the fog-leak gate of AI-1400. It is required for nothing else.
AI-370 A third-party plugin MUST declare deterministic truthfully in its manifest. A
non-deterministic plugin remains playable — AI-350 keeps replays exact — but MUST be excluded from every
context that re-executes AI decisions for verification: farm reproduction runs, desync arbitration, and
any ranked mode 05-multiplayer.md marks verification-required. The host SHOULD spot-check a determinism
claim by occasionally re-running a turn from the pre-turn state and comparing order streams; a mismatch
flags the plugin.
Note: with no clock and no ambient entropy in the import set (AI-210), deterministic: false declares
an internal property of the module — a NaN-payload-derived value, reliance on host-observable memory
layout, or an engine-dependent construct module validation does not reach — and never a capability the
host granted. A plugin cannot become non-deterministic by reading something; only by computing
something.
AI-375 CI MUST assert that the same recorded player view, replayed on machines of materially different speed, produces byte-identical order sets. A difference is an AI-415 violation and a release blocker.
11.3 Arithmetic at the boundary
AI-380 WASM arithmetic is bit-exact across compliant engines with three named exceptions that are not configurable when the engine belongs to the platform (AI-125). The host MUST enforce them by module validation before instantiation, refusing to load a module that: (a) declares or imports shared memory or the threads feature, or uses atomic instructions; (b) uses relaxed SIMD instructions — deterministic SIMD is permitted and, for an integer inference kernel, is the one place in this project where SIMD is both permitted and worth having; (c) imports any transcendental or otherwise engine-supplied math function. Such functions MUST be compiled into the module, so their implementation is fixed by the plugin binary rather than by whichever engine is running it. Refusal MUST name the offending feature or import in a user-visible message. Beyond validation, a plugin MUST NOT let NaN bit patterns influence any value it returns; that obligation is 07-modding-content.md MOD-600's and sits on the plugin. Shipped AIs MUST NOT produce a NaN in any computation whose result reaches an order, and MUST assert on one in debug builds.
AI-385 No floating-point value crosses the AI ABI. Every field of every submitted order MUST be
an integer, identifier or enum of the order catalog (03-architecture.md AR-270), and every numeric field
the view namespace returns MUST be delivered in the core's own integer or fixed-point representation
(AR-080 owns that representation and this document does not restate it) in the canonical encoding, never
rescaled, normalised or passed through a number conversion by the host's marshalling layer. This is the
AI-surface instance of 07-modding-content.md MOD-600's rule and the two MUST agree. Inside a plugin,
float arithmetic is permitted and this document does not ban it; the shipped Staff gives that permission
up under AI-1010, and a third-party plugin MAY do the same but is not required to.
Rationale: the host is written in a language with one numeric type, so a well-meaning marshalling helper that divides a per-mille value by 1000 to present a friendlier number is a live hazard. Keeping the boundary integer-only makes that class of bug a type error rather than a rounding difference that surfaces as a desync six months later. The boundary is also where the whole hazard lives: a float that never leaves the guest cannot desync a game, because what crosses into the log is an order, and an order is integers.
AI-390 The host MUST serve every AI random draw from a deterministic AI-private stream belonging to the calling seat alone. 03-architecture.md AR-370 owns the derivation normatively and this document MUST NOT restate it; what the AI framework guarantees on top of it is:
(a) Private per seat — no plugin can read, replay or influence another seat's draws (AI-340), and no
draw permits recovery of the game Seed, of any rules stream, or of another seat's stream (AI-195).
(b) Successive draws differ — repeated draws on the same key within one turn yield independent
values, so a plugin may draw as often as its budget allows without special-casing the key.
(c) Reproducible — the same AI, at the same seat and turn, taking the same sequence of draws, receives
the same values on every platform and every re-run. This is what makes AI-360 testable.
(d) Outcome-neutral — AI streams are independent of the rules streams that resolve combat and
production, so AI consumption never perturbs game outcomes, and AI stream state is not simulation state.
AI-195 The game root Seed MUST NOT be handed to any AI plugin, and no value passed to a plugin may
permit its recovery. The seed field a plugin receives at creation MUST be an AI-private seed: a
64-bit value one-way derived by the host from the game Seed, the seat id and the RNG version — a keyed
or cryptographic hash, not a rules-stream expansion — such that a plugin holding it cannot reconstruct
the Seed, any rules stream's state, or any other seat's streams. The same non-recoverability rule MUST
hold for the worldgen seed a generator plugin receives (03-architecture.md AR-400), otherwise an author
could recover the Seed by shipping a paired worldgen plugin and reading it out of the generation
request.
Rationale: AR-370 publishes the exact stream construction, so the root seed is equivalent to read access to every future combat roll and to unexplored map content. Handing it over would silently defeat AI-020, AI-030 and AI-300. The AI-private seed exists only so that a plugin preferring its own internal PRNG stays deterministic.
11.4 Advisory memory
AI-460 An AI seat's persisted memory blob MUST be stored as a separate save-container entry
outside hashed simulation state — ai/<playerId>.<OrderSeq>.bin, versioned and size-capped at the
instance memory limit — so that resuming a saved game restores AI intent: standing plans, target lists,
the force-accounting integrals, the switching-cost baseline. AI blobs MUST NOT be embedded in the initial
state, the order log or snapshots, MUST NOT contribute to any turn or state hash, and MUST be excluded
from snapshot verification (03-architecture.md AR-570). They are covered by the ordinary per-entry
integrity table like any other container entry.
AI-465 AI blobs MUST be droppable: a container stripped of its ai/ entries — for replay
distribution, bug-report bundles, or fog-safe transfer — MUST still verify and replay exactly, and
readers MUST treat an absent, unreadable or version-mismatched blob as "no AI memory" rather than as
corruption. Blobs are an optimisation, never authoritative: if restore fails or the blob is absent, the
Staff MUST continue from the current view alone, degraded but legal and competent — never a crash, never
a refusal. A writer MUST retain at least the newest entry per AI seat.
12. The AI interface
12.1 Two execution forms, one contract
AI-120 There MUST be exactly two forms an AI seat may take, and both MUST be seats under §3:
(a) The shipped Staff, an in-process module in the client, server and CLI, importing
@everylastcity/core directly and reaching the simulation only through the Order/View contract of
03-architecture.md AR-060.
(b) A third-party AI plugin, a sandboxed WASM module conforming to the plugin container, manifest, signing and sandbox rules of 07-modding-content.md and to the transport of MOD-660.
AI-122 Because the shipped Staff is not a plugin, the project MUST maintain a reference AI plugin — a complete AI built against the public ABI, shipped, playable, and covered by the same fairness gates (AI-1400) and Constraint-Floor gates (AI-1410) as the Staff. The published ABI MUST NOT be declared sufficient on any other evidence.
Rationale, and this is a decision this document makes and owns. The previous draft required every shipped AI to be a WASM plugin, on a dogfooding argument that was correct at the time. Three things since changed it. 03-architecture.md AR-850 took WASM out of the core, so a plugin now needs a core replica materialised per turn (AI-235) — real cost, unmeasured, and paid on every AI turn. 11-combat.md CB-2290 requires the AI to use the engine's own preview function rather than a cheaper approximation, and the Staff will call it tens of thousands of times per turn; marshalling that across an ABI is a worse contract than an in-process call and buys nothing. And AI-410's fuel instrumentation costs throughput precisely where the budget is tightest, on mobile. The dogfooding argument was never about the shipped AI specifically — it was about the ABI being provably sufficient — and a maintained reference plugin proves that at a fraction of the cost. What must not be lost is that both forms are bound identically by §3: the Staff has no privileged view, no privileged order kinds, and no exemption from any gate.
AI-125 The host MUST instantiate AI plugins through the standard WebAssembly API present in every target environment — a browser tab, the Tauri web view on desktop and mobile, and Node on the server. No embedded WASM engine may be a dependency of any build, and no platform may use an engine other than the one its runtime provides. The plugin host MUST be a single implementation shared by client and server (03-architecture.md AR-855, which owns the host constraints this document does not restate).
Rationale: the engine we would otherwise ship is already present, hardened, and continuously patched by every browser vendor, and the whole embedded-runtime layer with its per-platform build, size and CVE surface disappears. The cost is stated plainly and owned here: a platform engine takes no configuration, so the determinism switches and the fuel meter an embedded runtime gave for free must be reproduced by module validation (AI-380) and instrumentation (AI-410), and the engine is no longer one implementation we pin but every engine our platforms ship, which AI-700 must now test against.
12.2 ABI, manifest and options
AI-130 The AI interface MUST be versioned independently as empire:ai@X.Y.Z in the WIT form
07-modding-content.md MOD-580 owns, MUST be semver-stable within a major version, and the host MUST
refuse to load a plugin whose declared major version it does not support, with a user-visible error
naming both versions.
AI-140 The AI plugin manifest MUST declare at minimum: plugin id, display name, author, version; ABI
version; supported unit sets (any or an explicit list); capability flags including deterministic
(AI-370) and supportsResume; requested memory limit; and the options schema of AI-152.
AI-152 AI options MUST be declared as a typed schema in the manifest so the client can generate a
configuration UI without knowing the plugin. Supported types MUST include bool, int with a range,
enum, permille with a range, and perUnitClass tables keyed by 02-units-and-industry.md's closed
class enumeration (US-090). Each option MUST carry an id, a localisable label and description, and a
default. No option type MAY be a float (AI-385).
AI-160 Option configurations MUST be savable and loadable as named presets per seat, and the active configuration MUST be stored with the game so that a replay or a resumed game records exactly which options were in force.
AI-170 An AI seat's display name MUST be settable explicitly in options or drawn deterministically from a user-supplied name pool. A name pool MUST be a documented plain-text or JSON file, and the drawn name MUST be recorded in the game configuration so that a replay shows the same names the players saw.
12.3 Lifecycle and calls
AI-180 The plugin lifecycle MUST be exactly the one 07-modding-content.md MOD-660 owns:
create → start-game → (per turn) prepare-orders → game-over, with serialize and restore around
saves and loads, one instance per seat, memory-isolated from every other instance (AI-340). This
document MUST NOT specify a different lifecycle.
AI-190 The plugin's exports MUST be:
| Export | When called | Purpose |
|---|---|---|
abi-version |
load | The supported ABI version |
create |
game creation or load | Instance init: game configuration, ruleset, enabled Tracks, unit set, own seat id, options blob, and the AI-private seed of AI-195 |
start-game |
turn 0 | First-look setup from map metadata and own starting assets |
prepare-orders |
once per turn, during that seat's Orders phase | Produce the seat's whole order delta for the turn |
eval-task |
inside a parallel batch (AI-450) | A pure evaluation entry point for candidate scoring |
serialize / restore |
around save and load | The opaque versioned advisory blob of AI-460 |
game-over |
end | Final notification |
AI-200 The host imports an AI module may declare MUST be exactly the following namespaces and no others:
| Namespace | Functions (minimum) | Notes |
|---|---|---|
view |
map metadata; tiles in a rectangle; own units; own cities; own economy; the Contact Register; the observable event stream since the previous Reckoning; rules; unit set; Track status; public player data | The fog-filtered player view only (§5) |
orders |
submit an order record, returning a typed result; commit | The same order schema human clients use (AI-220) |
predict |
the exact Clash preview of 11-combat.md CB-2250 over the caller's knowledge view, with its pivot analysis | CB-2290 forbids a cheaper approximation |
project |
closed-form economy, Reach and Track projections over a hypothetical state | §22 records the contract this places on 12-economy.md and 14-victory.md |
rng |
draw from an AI-private stream | AI-390 |
par |
evaluate a batch of pure tasks | AI-450 |
mem |
save and load the advisory blob | AI-460 |
budget |
fuel remaining this turn | Fuel only — no wall-time field, quantised or otherwise (AI-210) |
diag |
log; record a decision explanation | AI-750 |
AI-210 The sandbox MUST deny AI plugins every ambient capability: no filesystem, no network, no clock of any kind, no threads, no non-deterministic WASM feature. WASI MUST NOT be exposed. On a platform engine the sandbox is not configured but constructed — an instance can reach only what the import object hands it — so denial MUST be enforced by import allow-listing at load: the host MUST reject any module declaring an import outside the AI-200 set, by name and namespace, before instantiation, and MUST NOT populate the import object with any binding not in that set.
No clock, and no reconstructible clock. No function in the AI-200 set may return wall-clock time, elapsed time, or any value from which elapsed time can be recovered by differencing successive calls: a quantised "time remaining" is a clock, because two readings are a duration. The budget query therefore reports fuel and nothing else, and fuel is a count of instrumented operations (AI-410), not of time. This is the same denial 03-architecture.md AR-855 requires of the import object and 07-modding-content.md MOD-590 requires of the sandbox. Any host-side glue between the ABI and the engine — marshalling shims, generated bindings, worker plumbing — is part of the ABI surface and MUST NOT close over ambient host capabilities, even transitively through a generated wrapper. Import vetting MUST run again on every load, not once at install, so that a plugin substituted after validation cannot slip a new import through.
AI-220 Order-surface parity. The set of orders an AI seat may submit MUST be exactly the set a human could legally submit in the same state, per the order catalog of 03-architecture.md AR-270 and the command objects of 13-command.md. An illegal order MUST be rejected at submission with the typed rejection of 10-turn-model.md TM-250 and MUST NOT crash or end the seat's turn. An order that is legal when issued and unachievable at activation MUST NOT be reported as an error at any point (TM-270).
AI-230 An AI seat MUST issue its orders during its Orders phase, against the board as it stands at the start of that phase, which 10-turn-model.md TM-340 guarantees is stable for the whole phase. The host MUST NOT invoke an AI between two units' activations, MUST NOT show it any Cascade result before the Reckoning completes, and MUST NOT offer any mid-Cascade decision point (TM-050). Where a decision genuinely depends on what happens earlier in the turn, it MUST be expressed as a conditional order evaluated at activation (TM-280) — which is the compensation the turn model was chosen for, and which AI-1250 requires the Staff to use harder than a human can.
AI-235 WASM imports are synchronous and AI-440 requires the instance to run in a terminable worker;
the host MUST reconcile the two without a synchronous cross-thread round trip, by co-locating a
@everylastcity/core replica in the worker that owns the instance, materialised from authoritative
state at the start of that seat's Orders phase. View and predict calls are then ordinary in-thread
calls, and what returns to the authoritative host is the seat's order records for the turn, which
the authority appends to the log and the authoritative core resolves. The host MUST NOT make the ABI
depend on SharedArrayBuffer with Atomics.wait, which would force cross-origin isolation on the web
client, nor on JavaScript Promise Integration, which is not available on every target engine. The
replica MUST be materialised only where the host already legitimately holds that state: in a
fog-enforced online game the AI turn runs server-side under AI-480, and a client MUST NOT materialise a
replica for a seat it does not own.
Rationale: event sourcing pays for this. Because orders, not state, cross the boundary, a replica core in the worker is not a second source of truth — it is a prediction the authoritative core re-derives, exactly as a client already does for human players.
12.4 Faults, tooling and distribution
AI-240 Fault containment. If an AI plugin traps, exceeds its memory limit, exceeds the hard cap
(AI-420), or fails to commit, the host MUST (a) log the fault; (b) issue a safe fallback for the
remainder of the turn — units keep their existing order stacks, which 10-turn-model.md TM-280 makes the
natural default, and cities keep their existing production; and (c) append those fallback orders to the
authoritative order log as ordinary logged orders of ordinary order kinds, in the envelope of
03-architecture.md AR-260 with the acting seat and an Issuer of authority-fallback, so that the replay
stays exact. Recording a fallback only as a derived event is insufficient, because events are a
re-derivable cache (AR-250) and an unlogged fallback would vanish on replay. Repeated faults — default
3 consecutive turns — SHOULD surface a user-facing option to replace the plugin with the shipped
Staff, keeping the game alive. This document owns fault and fallback behaviour; partner documents
cite AI-240 rather than stating a threshold or a substitution policy of their own.
AI-420 On hard-cap exhaustion the host MUST interrupt and apply the AI-240 fallback. Exceeding the soft target MUST NOT interrupt; it is reported through diagnostics and telemetry. A running WASM instance cannot be interrupted from outside by the standard API, so the host MUST have exactly two interrupt mechanisms and MUST NOT rely on any other: (i) the fuel trap of AI-410, which is deterministic — it fires at the same instrumented operation on every machine — and is the mechanism that enforces a budget; and (ii) termination of the worker holding the instance (AI-440), which is a non-deterministic watchdog against a wedged or infinite-looping instance and MUST be treated as a fault under AI-240, never as a normal budget outcome. A host MUST NOT use a wall-clock deadline as the budget in any context where AI-410 requires fuel, and MUST record which path applied. A plugin executing on the host's main thread with no fuel instrumentation is uninterruptible and MUST NOT be a shipped configuration on any platform.
AI-410 Wherever deterministic reproduction matters — server verification, farm runs, determinism spot-checks — plugin budget enforcement MUST be by metered fuel rather than wall clock, so that the cutoff falls at the same instruction on every machine. Fuel-per-turn limits MUST be part of the recorded game configuration. Because a platform engine meters nothing (AI-125), fuel MUST be produced by deterministic bytecode instrumentation of the plugin module; the transform itself is owned by 07-modding-content.md MOD-610 and this document neither restates nor varies it. What the AI framework requires of it: the transform MUST be semantics-preserving, and its id and version MUST be recorded in the game configuration alongside the fuel budgets (03-architecture.md AR-857), because fuel counts are comparable only between hosts running the identical transform. A host MUST refuse to treat a fuel-metered result as verification evidence when its transform version differs from the recorded one. In the one context AI-400 exempts — the local interactive row — the host MAY run the uninstrumented module and enforce the hard cap by the AI-420 watchdog, and the recorded configuration MUST state which enforcement actually applied so that a later reproduction knows whether the run is evidence.
AI-250 Developer hot-reload MUST be supported: in a local dev mode a modified plugin can be reloaded
between turns without exiting the game, calling serialize on the old instance and restore on the
new, falling back to create plus start-game with a warning on a restore failure. A reloaded module
MUST pass the same import vetting (AI-210), feature validation (AI-380) and, where the context requires
fuel, the same instrumentation as an installed plugin. Dev mode MUST NOT bypass any of the three, so
that a plugin which only runs under hot-reload is a plugin that would not load for a player.
AI-260 The SDK's language-template roster is owned by 07-modding-content.md MOD-670(a) and this
document MUST NOT name a different one. What the AI framework requires on top of it: every template
MOD-670(a) marks first-class MUST ship a complete minimal example AI that plays the Industry-1 subset of
the shipped unit set; every such template MUST ship generated ABI bindings, the plugin-source determinism
lint of AI-385, and fuel-profiling output against the AI-410 transform; and the SDK MUST ship a headless
harness that runs plugin-versus-plugin games from the command line, which MUST be the same code path as
MOD-670(b)'s harness rather than a second one. A template's documentation MUST state plainly what its
guest language is and is not — in particular that @everylastcity/core types are not importable into a
plugin, since the ABI's typed view records are what an author codes against — and what the template's
guest runtime costs in module size and in fuel per turn.
AI-265 A plugin's loadability MUST NOT depend on which toolchain produced it. Any module that conforms to the ABI (AI-130, AI-190, AI-200), passes import vetting (AI-210) and feature validation (AI-380), and carries a valid manifest (AI-140) MUST be loadable, whatever language it was written in and whatever standing that language has in the MOD-670(a) roster. The host MUST NOT require an SDK-produced module and MUST NOT reject a module for lacking an SDK marker.
Rationale: the point of a documented AI interface is that anyone can write against it, not that a blessed toolchain exists. Keeping loadability a property of the module rather than of its build is what preserves that, and it is why the roster question — however 07-modding-content.md answers it — can never be the thing that makes someone's AI unloadable.
AI-270 Third-party AI plugins MUST be distributable and discoverable through the in-game workshop (07-modding-content.md). Installing an AI MUST NOT require a compiler toolchain or manual file placement.
AI-275 AI plugins MUST execute locally on every supported platform, iOS and Android included. Server-side AI execution (AI-480) is a deployment option for cloud and server-authoritative games and MUST NOT be the mechanism by which any platform gets AI opponents at all: a solo or hot-seat game with AI seats MUST be fully playable offline on a phone. Three narrower risks remain and none of them may make plugins unavailable: web-view engine performance varies with the memory and code-generation state the OS grants the content process, which is a budget risk rather than a capability one; the web view's memory ceiling is shared with the whole client UI (AI-430); and distributing third-party executable plugins to a mobile app is a store-policy question, tracked as Open question 12.
13. Difficulty — the six Ranks
13.1 Weakness is a smaller world model, not a noisier one
AI-615 A Rank's weakness MUST be produced by exactly three mechanisms and no others:
(a) Omission. Each Rank's Assay feature set MUST be a strict superset of the Rank below, and the features a Rank lacks MUST be named in §13.2 and disclosed in the selector (AI-630).
(b) Latency. Each Rank carries a re-plan interval k and a commitment lock C: the Empire Stance
and Track portfolio are reconsidered every k turns, and an Operation is held for C turns after its
trigger has cleared.
(c) Attention. Each Rank carries a triage budget A — items examined per turn — and a staleness
tolerance S, the Contact age it will treat as current.
AI-617 The following MUST NOT occur at any Rank: random corruption of an order the Staff has already selected; any deliberate-misplay branch; any artificial delay in noticing a visible threat, since slowness lives in re-planning and never in perception; any provably pointless action, which 11-combat.md's exact predictor makes a computable predicate — an attack with zero break probability and a worse loss trade than not attacking; and any behaviour inconsistent with the Rank's own model, so that a Rank without a supply term must never accidentally do the supply-aware thing in a way a player will read as competence.
Rationale, and this is the decision the whole ladder rests on. The standard approach is utility noise, and it fails on its own terms: noise applied to a good evaluation produces mostly-good play punctuated by decisions with no possible rationale, and nobody has ever met a human who plays like that. A human novice plays consistently, from a model smaller than yours. They over-expand because their model has no term for occupation cost. They assault entrenched infantry because their model has odds in it but not resolve. They react late because they only look at a front when something has already gone wrong there. Every one of those errors is systematic, explicable and learnable-from, which is exactly what noise is not. Omission buys four things noise cannot: weak play that looks like weak human play because it is produced the same way; a difficulty selector that can tell the truth about what a Rank does not understand; a Debrief that can name the blind spot the player exploited, which turns a win into a lesson; and structural monotonicity, since adding a term can only fail if its weight is wrong, which is a tuning bug with a test rather than a design risk.
AI-618 For Ranks with k ≥ 3, the Staff MUST re-score its current plan at re-plan time against the
forecast it made k turns ago, not against a fresh forecast.
Rationale: omission alone produces an odd opponent — narrow but mechanically perfect, because the command layer executes flawlessly for it — and that is not what a beginner is either. Evaluating whether the plan is working against what you expected to happen, rather than against what did happen, produces the most human failure available: continuing a plan because it is close to the projection, when the projection was wrong. It costs one stored integer vector per theatre and it disappears at Colonel and above.
AI-619 A low Rank MAY additionally apply evaluation blur — an integer offset drawn from the seat's own seeded stream (AI-390), added to a candidate plan's score only. Blur MUST NOT be applied to legality, to the predictor's arithmetic, to any Constraint-Floor computation, or to any quantity a player would see. A blurred choice MUST be reproducible in a replay and explicable afterwards.
Rationale: a Rank that mis-scores a plan looks like a player with different judgement; a Rank that mis-computes odds looks like a bug. Because the draw is seeded, the Debrief can say "Lieutenant rated that assault 620 when it was 700; it went in and it lost," which is a small delight and an honest one.
13.2 What each Rank understands
The one-line descriptions are the difficulty selector's copy, and they are honest.
| Rank | It understands… |
|---|---|
| Cadet | its orders |
| Lieutenant | a fight |
| Captain | an economy |
| Colonel | a map |
| General | a clock |
| Marshal | you |
AI-612 The Assay features and corrections available at each Rank MUST be cumulative and MUST be exactly:
| Added at | Assay features | Corrections and behaviours enabled |
|---|---|---|
| Cadet | A1, A2, A3, A14, A18, A19, A26, A27 | The whole Constraint Floor (AI-560), including retreat-degree defence (A28 defensive half). Postures and Sanctions only; Decisive-Point budget 0 |
| Lieutenant | + A16, A20, A21 | The break check as distinct from the odds ratio, terrain cover, garrison sufficiency read against 12-economy.md EC-1170, observation-age discounting |
| Captain | + A7–A13 | The occupation economy: Integration, Unrest, the Cadre cost curve, garrison burden, Loyalty memory, the Works-to-Manpower ratio bands and the army mix they force, production payback, the Industry climb |
| Colonel | + A15, A22, A23, A24, A25, A29 | The map and the unseen: Reach and supply state, Depot-chain articulation, retreat-degree offence (A28 offensive half), disorder and rotation, combined arms, the belief filter — contact discs and unaccounted force |
| General | + A4, A5, A6, A30 | The clock: every enabled Track with its threshold and Vigil, the Ebb schedule read backwards from a date, the Tally and Warrant calendars, elimination arithmetic, Alarm entry priced as a decision, hold-at-threshold-minus-one |
| Marshal | full set, with per-opponent attribution on A25 | You: a per-seat opponent model inferred from its own observation stream, feint recognition, counter-Vigil timing, and second-order plans that advance nothing of its own and remove something of yours |
Read that as a description of six opponents rather than six settings, because that is what it is. A Captain will out-economy you and then attack a mountain. A Colonel will cut your road instead, and will still not notice that the Ebb reaches you on turn 178. A General will be there on turn 178.
Human novice errors, and the omission that produces each — the plausibility argument made concrete:
| The mistake | Produced by lacking |
|---|---|
| Expands past what it can hold; rear cities revolt around turn 80 | the Integration and Cadre terms (below Captain) |
| Assaults entrenched infantry and is thrown back | the break check (below Lieutenant) |
| Fights on the enemy's ground | cover and the role-by-terrain relationship (below Colonel) |
| Attacks a stale Contact that is no longer there | a low S (below Colonel) |
| Feeds reinforcements in piecemeal | arrival-synchronisation terms (below Colonel) |
| Never concentrates artillery, so bombardment accomplishes nothing | the combined-arms threshold (below Colonel) |
| Never cuts a supply line | the Reach terms (below Colonel) |
| Ignores an opponent three turns from a Vigil | the Track terms (below General) |
| Keeps pushing an offensive two turns after it stopped working | a high C (below Colonel) |
13.3 The knobs
AI-610 A Rank MUST be entirely defined by the following data, and MUST NOT fork code. Default Rank: Captain.
| Knob | Meaning | Cadet | Lieutenant | Captain | Colonel | General | Marshal |
|---|---|---|---|---|---|---|---|
Σ |
step budget (AI-405) | 1,500 | 6,000 | 25,000 | 80,000 | 160,000 | 250,000 |
K |
strategic seeds | 2 | 3 | 4 | 6 | 8 | 12 |
L |
local-search passes | 1 | 2 | 3 | 4 | 5 | 6 |
Y |
opponent hypotheses | 1 (Passive) | 1 (Continuation) | 2 | 2 | 3 | 3 + regret weighting |
D |
Sandtable depth, turns | 1 | 2 | 2 | 3 | 4 | 5 |
H |
forecast horizon, turns | 3 | 6 | 10 | 16 | 24 | to the Horizon |
P |
Decisive Points per turn (AI-060) | 0 | 1 | 3 | 6 | 10 | 16 |
A |
triage items examined | 3 | 5 | 7 | 12 | all | all |
k |
re-plan interval, turns | 8 | 5 | 3 | 2 | 1 | 1 |
C |
commitment lock, turns | 10 | 6 | 3 | 1 | 0 | 0 |
S |
staleness tolerance, turns | 12 | 8 | 5 | 3 | 2 | 2 |
S deserves a note because it produces the most recognisable weak-player behaviour available. A Cadet
at S = 12 treats a twelve-turn-old Contact as live and plans against a ghost. That is exactly what a
beginner does, it is entirely fog-honest, and it is one integer comparison.
P deserves a note because it is the top of the ladder and it is the right top. Cadet's
Decisive-Point budget is zero: it sets Postures and Sanctions and lets the Cascade run. It is still a
real opponent, because 13-command.md's command layer is good — its Screens spread, its Sanctions pick
off stragglers, its Requisitions keep production flowing, its Reflexes preserve its units — and it will
never win a battle it should have lost, because it never chooses one. Marshal's budget of sixteen is
spent where a strong human spends it: the assault that must be timed, the encirclement that must close,
the artillery that must be concentrated, the transport that must not be caught. Knowing when to leave
the command layer is genuinely the last skill a strong player acquires, so a Rank defined by that budget
is defined by the right thing.
13.4 The floors, and monotonicity
AI-620 At every Rank, including Cadet, the Staff MUST NOT: leave a city ungarrisoned when a visible enemy is within its threat radius and a garrison-capable unit is idle or in reach; leave a city's production empty; strand a unit by rule — an air unit beyond its endurance, a transport left in reach of a hunter with no escort, a Cadre moved adjacent to a known enemy; decline a genuinely free adjacent city; make a provably pointless attack (AI-617); leave a unit Idle for more than the turn in which it became Idle; or leave its Seat ungarrisoned when an enemy is within reach. A violation of any clause MUST be a release blocker, not a tuning metric (AI-1410).
AI-625 Monotonicity is a gate. Each Rank MUST beat the Rank below it with ≥ 60% win rate over ≥ 1,000 farm games across the benchmark suite (AI-720). Structural monotonicity makes this likely, not guaranteed — a newly added feature with a badly-tuned weight can make a Rank worse — so each newly added feature MUST be A/B tested at the Rank that introduces it before the ladder gate runs, and a feature that does not improve its own Rank MUST be re-weighted or not added.
AI-630 Rank definitions MUST be data files under the same versioning as weights, and the setup UI MUST describe each Rank in plain language: its one-line description, and the named blind spots it carries from §13.2.
13.5 The selector says the measured number
AI-635 Where the services platform holds enough games, the difficulty selector MUST show, for each Rank, its measured win rate against human players in the selecting player's own rating band, alongside the plain-language description and the named blind spots. A Rank whose measured rate has moved more than 8 points between releases MUST be a release-blocking alarm rather than a silently updated number.
Colonel — understands a map. Does not track victory conditions or plan around the Ebb. Wins 61% against players rated 1400–1600.
Rationale, since this is unusual and the commercial objection is obvious. Adjectival difficulty is an unfalsifiable promise, and the moment a player suspects it is inflated the whole ladder loses meaning. A number is falsifiable, and falsifiable is what makes a ladder worth climbing. It also solves calibration drift, which is the same failure 14-victory.md fears for its own length-estimate table. The honest cost is that some players will read "wins 61% against players like you" as discouraging; the mitigation is that the sentence above it names the blind spot, which reads as an invitation.
AI-640 A Rank whose claimed strength has not been measured MUST NOT appear in the selector. Where the top Rank has not yet demonstrated its stated win rate against the top human rating band, the selector MUST show the Ranks that have and MUST state plainly that a further Rank is being measured.
Rationale: no shipped strategy game has an AI that reliably beats strong human players at a fog-of-war 4X without material advantages, and we should not ship a difficulty called "beats strong humans" until it has beaten strong humans. AI-635's measured selector is what makes that promise checkable rather than rhetorical, and §21.4 states what is and is not being promised.
14. Personality
14.1 A priced, published offset from a tuned baseline
AI-800 Personality MUST be expressed as a signed offset from one neutral, self-play-tuned baseline, as data, never as a code fork. The baseline personality Aurel MUST exist and MUST carry no offsets: it is the answer to "I want a good opponent, not a character," and it is what gives every other personality a price.
AI-805 Every personality's Elo price — its rating loss against Aurel at the same Rank over ≥ 1,000 games — MUST be measured by the pipeline of §17 and published in the setup card. The price MUST fall in the band 10 to 60 Elo. A personality above the cap is a handicap wearing a name and MUST be re-tuned or retired; a personality below the floor is a cosmetic and MUST have its gates widened rather than its weights nudged.
AI-810 Personality dials MUST be frozen inputs to tuning: the pipeline tunes the shared feature definitions and Aurel's weights, and MUST NOT tune a personality toward the optimum, which is the same as deleting it. After every promotion, each personality's price MUST be re-measured and republished.
14.2 The dial vector
AI-815 A personality MUST be exactly the following fifteen dials, every one of which changes something a partner document specifies. None is a mood.
| Dial | Range | Aurel | What it changes |
|---|---|---|---|
caution |
0–1000‰ | 500 | The risk coefficient k of AI-1210 |
expansion |
0–1000 | 500 | A gate. Offensive Operations are illegal while unintegrated × 1000 > integrated × expansion |
cadre |
0–1000‰ | 120 | Share of Works budgeted to Administrative Cadre |
climb |
0–1000‰ | 180 | Share of Works budgeted to Industry upgrades |
engage |
1–999‰ | 700 | The Engagement threshold written into its Doctrines (13-command.md CM-770) |
prudence |
1–999‰ | 334 | The Risk Sanction's break-off threshold |
leash |
×⅓ – ×3 | ×1 | Multiplier on Posture-default Leash |
mass |
0–1000 | 500 | Preference for a concentrated Pace (13-command.md CM-1000) and the minimum battery count it will bombard with |
opportunism |
0–1000 | 500 | Weight on opportunity items and the Seize default it chooses (CM-700) |
grudge |
0–1000 | 200 | Target weight added per city a seat has taken from it |
predation |
−1000…+1000 | 0 | Positive: prefers weak targets. Negative: prefers the leader |
nerve |
0–1000 | 500 | Willingness to enter the Alarm band before it is airtight |
homeland |
0–1000 | 500 | Weight on retaking its own cities, where Loyalty memory restores Integration in full |
track[·] |
0–1000 each | 500 | Per-Track affinity across 14-victory.md's catalogue |
triage[·] |
−30…+30 | 0 | Per-class weights in the Staff's own triage (AI-1310), fixed and never adaptive |
Two of these are structurally different and that is deliberate. expansion is a gate, not a weight:
it makes whole Operations illegal, which is how a personality holds its shape when the numbers get
tempting instead of drifting to the optimum. predation is signed, so one dial produces two
opposite and equally coherent opponents — the one that finishes the wounded and the one that fights the
leader.
AI-820 The preference margin. A plan MUST be preferred over another only if it exceeds it by at least 50‰ of the leading score. Within the margin, the personality's declared tie-break list — at most four ordered clauses — MUST decide, and beyond that 13-command.md CM-170's terminal tie-break chain applies.
Rationale: personality expressed purely as weights has a failure mode where two plans score 1531 and 1529 and which one a "personality" picks is noise wearing a character's name. A one-point margin on a fifteen-hundred-point score is not a preference. Converting a fragile numeric knife-edge into a declared, legible preference is worth more than the precision it costs, and it means a personality's behaviour at the margin is stated rather than emergent — which is what makes it survive a re-tuning of the weights.
14.3 The shipped roster
AI-825 The shipped roster MUST be exactly the following seven, each shipping as data plus a setup card. Additional personalities MAY be added as data; each MUST carry a measured price (AI-805) and a signature test (AI-740).
caution |
expansion |
cadre |
climb |
engage |
prudence |
leash |
mass |
opportunism |
grudge |
predation |
nerve |
homeland |
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Aurel | 500 | 500 | 120 | 180 | 700 | 334 | ×1 | 500 | 500 | 200 | 0 | 500 | 500 |
| Corvain | 300 | 900 | 60 | 100 | 600 | 200 | ×2 | 350 | 800 | 150 | +500 | 750 | 250 |
| Vela | 750 | 200 | 320 | 300 | 850 | 450 | ×½ | 700 | 250 | 400 | −100 | 300 | 900 |
| Karsk | 650 | 400 | 200 | 220 | 800 | 300 | ×½ | 900 | 300 | 700 | 0 | 400 | 600 |
| Ostry | 350 | 550 | 140 | 160 | 650 | 250 | ×3 | 200 | 900 | 250 | +700 | 600 | 300 |
| Meridian | 550 | 450 | 240 | 260 | 750 | 350 | ×1 | 750 | 400 | 300 | 0 | 250 | 500 |
| Sabar | 450 | 500 | 200 | 200 | 720 | 334 | ×1 | 550 | 450 | 100 | −900 | 350 | 500 |
Tie-break lists, which is where a great deal of the character actually lives:
| Tie-break order | |
|---|---|
| Aurel | lower cost; then sooner; then lower entity id |
| Corvain | more cities gained; then sooner; then lower cost |
| Vela | lower cost; then higher yield; then nearer home |
| Karsk | better ground at the decisive tile; then lower cost; then sooner |
| Ostry | more targets of opportunity on the route; then sooner; then lower cost |
| Meridian | better prepared (higher combined-arms score); then closer to a scheduled date; then lower cost |
| Sabar | higher denial value; then sooner; then lower cost |
And the characters, which is what a player actually reads:
Aurel — the baseline. No preferences. The best play the tuning pipeline has found.
Corvain — the Mortgage. Takes more than he can govern, and dares you to punish it. expansion 900
with cadre 60 means he holds far more cities than he has digested and pays for it in garrison bill and
a Manpower crisis. predation +500 sends him at whoever is weakest. You will see: cities changing
hands fast, revolt countdowns in his rear from about turn 70, an army skewed by whichever
Works-to-Manpower band his starved Manpower still affords. Counterplay: do not fight his line. Raid
the Cadre column and retake your own cities, where Loyalty memory gives you everything back the turn you
walk in.
Vela — the Household. Small, dense, and impossible to kill at home. expansion 200 is a hard
gate: she will refuse profitable conquests while she has anything undigested. homeland 900 means every
city you take from her is immediately and expensively contested. She wins on economic Tracks and on
Tenure, which she accumulates while you are busy. Counterplay: she compounds, so you must be ahead
early and you must beat her on the clock, never in her homeland.
Karsk — the Anvil. Fights where the ground pays, and starves what he cannot storm. mass 900
means he will not bombard below the combined-arms threshold and will not attack without it. He chooses
defensive terrain, entrenches, and reaches for the supply cut rather than assaulting the cell that
resists everything. grudge 700: hurt him and he will finish that argument before starting another.
Counterplay: do not let him pick the ground, and race him — his tempo is his weakness.
Ostry — the Rasp. Attacks the machinery, not the army. opportunism 900, leash ×3, dispersed
Pace. His target weights are the design's soft spots: Cadre, Academy cities, Great Work sites, Depots,
and high-Industry rear cities. predation +700 strips a collapsing player for parts. Counterplay:
escort Cadre, garrison rear Industry, and give your Screens a real Leash.
Meridian — the Calendar. Turns up on the day, with everything. 14-victory.md publishes the Tally
rotation twenty-four turns ahead, Warrants five turns ahead, and the Ebb schedule from turn 1. Meridian
anchors its plan on the next scheduled event and times its March routes to arrive on the day, not
before. nerve 250 means it will not enter Alarm until it is airtight. Counterplay: read the same
calendar. It is public. This is the personality that teaches the victory system.
Sabar — the Balance. Fights whoever is winning, including you. predation −900. Sabar scores an
Operation by the leader's Track progress it removes rather than by what it gains, and will abandon a
profitable front to hit whoever entered Alarm. It is the reason a four-player game with AI seats does
not produce a runaway. Counterplay: do not lead visibly, which makes 14-victory.md's banded
visibility a live strategic concern. Honest cost: see AI-935.
14.4 Personality against Rank
AI-830 Personality MUST be orthogonal to Rank: a Cadet Karsk and a Marshal Karsk are both meaningful, because Rank is how well a seat executes and personality is what it wants. Where a dial references a feature the Rank does not have (§13.2), it MUST degrade to its nearest expressible proxy, and the proxy MUST be named on the setup card. Each personality MUST declare a full-expression Rank:
| Personality | Fully expressed at | Below that, dormant |
|---|---|---|
| Corvain | Captain | nothing important; he is a Cadet-legible character |
| Vela | Captain | homeland degrades to a target preference |
| Karsk | Colonel | starvation Operations and supply-cut targeting |
| Ostry | Colonel | Depot-chain targeting; Cadre interdiction arrives at Captain |
| Meridian | General | the calendar, the timing, the Vigil arithmetic |
| Sabar | General | leader identification degrades to "largest visible empire" |
Corvain and Vela being fully expressed at Captain — the default Rank — is not an accident: the two personalities that read most clearly to a new player are the two that need the least machinery.
14.5 Personality never authorises losing
AI-835 The Override. At any Seal where an opponent holds an active Vigil on a Track the Staff projects to complete before the Staff can complete one of its own, the Staff MUST allocate no less than one quarter of its uncommitted force to the plan with the highest denial value available to it, and MUST NOT allocate to any plan with zero denial value until that quarter is committed. Personality weights are otherwise untouched. The setup card MUST state that the Override exists and what it does.
Rationale, three ways. It forces a contribution, not a conversion — Vela still digests and Corvain
still eats his weakest neighbour, and neither becomes Sabar for a turn. It uses a quarter, which is
enough to matter and not enough to lose a front. And it operates on the projection rather than on
the Alarm banner, so it fires slightly before the banner for high Ranks and slightly after for low ones,
which is correct: noticing early is a competence. It is also the rule that makes 14-victory.md's Vigil
do the work that document wants. VC-670 and VC-690's asymmetry — the leader must be airtight for V
turns, the challenger needs one success — is the anti-snowball mechanism, and that argument is only true
if the challengers actually challenge. In a game with AI seats, the Override is what makes it true. The
honest cost is that it is a designer overruling a player's chosen opponent, once per game, which is why
the setup card must say so.
15. AI seats in multiplayer
15.1 Three levels of absence
AI-485 Absence MUST be handled at three levels, and the first MUST require no AI at all:
| State | Trigger | Who is playing | Mandate |
|---|---|---|---|
| Standing | a seat did not commit this turn | nobody — the command layer | whatever the seat's own Postures and Sanctions already authorise (13-command.md CM-2010) |
| Caretaker | 2–3 consecutive missed turns, or an explicit away setting | an AI, restricted | AI-492 |
| Substitute | the player has left; automatic after the declared count in ranked | an AI at a declared Rank and personality | full |
Rationale: Standing costs nothing and covers most cases, and that is a structural advantage of the turn model rather than a convenience. Because orders are policies evaluated at activation (10-turn-model.md TM-280), a player who misses a turn is not absent from the board — their Screens still spread, their Requisitions still fill, their garrisons still hold, their Reflexes still fire. In correspondence play, where a missed turn is a missed day, this is the difference between a mode that works and one that does not.
15.2 The Caretaker mandate
AI-492 A Caretaker MUST be unable to lose the seat's game for it and equally unable to win it. It MAY: keep production running, fill Requisitions, re-post reinforcements; respond defensively — reposition Screens, relieve a threatened city, entrench; take a city the seat's own Seize Sanctions already authorise; repair, rotate worn units, resupply; move Cadre along already-planned routes. It MUST NOT: change any Doctrine, Requisition target or Posting weight; initiate an offensive Operation of any kind; change a Seize Sanction or take a defended city; disband a unit, abandon a Garrison or raze a city; re-site or start a Great Work; enter a Vigil it is not already in; concede, capitulate, or vote in a Verdict (it MUST abstain, which 14-victory.md VC-2770 counts as playing on).
Rationale for the sharpest row: entering a Vigil hands every other player vision of your contributing sites for as long as it lasts (14-victory.md VC-2290). No absent player's game should acquire that on their behalf.
15.3 What makes a Substitute acceptable to the other humans
AI-494 A substitution policy — trigger count, Rank, personality, mandate, and the continuity window — MUST be part of the game's Terms at setup and visible to every seat before the game starts. Nobody may discover on turn 90 that the empire next door has become something else.
AI-496 A Substitute's strength MUST be a declared constant, defaulting to Captain, and MUST NOT be estimated from the departed player's play.
Rationale: you cannot estimate a player's strength from forty turns of a fog game with any reliability — the variance is enormous and position confounds everything — and an estimator that is wrong is worse in both directions: too strong and the substitution punishes the departed player's neighbours; too weak and it hands someone a free win.
AI-498 For the first 5 turns a Substitute MUST inherit rather than replace: it keeps the seat's Postings, Doctrines, Requisition rows and Formation structure and issues orders within them, beginning to re-plan at its own strategic level only afterwards. Its default personality MUST be Aurel.
Rationale: neighbours' plans are not invalidated overnight, and the transition is gradual rather than a
discontinuity in the middle of someone else's operation. Aurel by default because a Substitute carrying
predation or grudge kingmakes by preference — Ostry would strip the weakest neighbour, Sabar would
attack the leader — and either outcome redistributes a game the departed player did not agree to
redistribute. A neutral substitute cannot be fair; nothing can. It can at least be unmotivated. The
Staff's own switching cost (A27) then makes it conservative by default: it keeps the human's plan and
changes only what its search says is decisively better, so a returning player finds their army roughly
where they left it doing roughly what they told it to — and 05-multiplayer.md MP-1010 and
10-turn-model.md TM-590 already require the takeover not to alter any unit's order stack.
AI-490 A substituting AI MUST receive only that seat's fog-filtered view and its order history. It MUST NOT receive the human's chat, map annotations, notes, saved names, or anything the seat itself did not observe. On reclamation (10-turn-model.md TM-600) the returning player MUST receive the Intent Records the AI produced for the turns it ran (AI-750).
AI-480 In correspondence and server-authoritative games, AI turns MUST be executable by the server using the same code, the same budgets and the same fairness constraints, subject to AI-275: server execution is never the only way a platform gets AI. An AI seat MUST be executed by exactly one authority per game, and its version, weight version, Rank, personality and salt MUST be pinned in the game configuration.
Rationale for the last clause: two clients computing the same AI seat independently is a desync waiting for a version skew.
15.4 Kingmaking, stated rather than solved
AI-935 In a game with three or more seats, any AI seat's preferences redistribute the game. This
cannot be eliminated and MUST NOT be claimed to be. Three mitigations MUST apply: Sabar MUST be off by
default in any game with two or more human seats, with the setup screen stating why; predation MUST
be clamped to ±300 for AI seats in games with two or more human seats; and every AI seat's
personality MUST be named in the Terms, so that a coalition-shaped AI is at least a known one the human
players can plan around.
Rationale: an opponent that deliberately attacks whoever leads is a coalition-forming rule in a game whose direction explicitly has no diplomacy. In solo play it is a feature — it is the thing that stops a runaway and keeps the middle third of a game live. Between humans it is a thumb on the scale.
15.5 The Verdict vote
AI-940 14-victory.md VC-2810 requires AI seats to vote by a deterministic policy derived from their evaluation and the seed. That policy is here. An AI seat MUST vote to end the game if and only if all three hold, evaluated from that seat's own view using only its own state and the published information of VC-2200:
- For every enabled Track, its projected best progress at the Horizon — computed at its Rank's
Husing 14-victory.md's own ceiling arithmetic (VC-2600, VC-2610, VC-2620) — is below the leader's by more than the maximum it can still gain; and - its Standing has not increased in the last 8 turns; and
- it holds no city it projects it could convert into a Vigil within 20 turns.
Otherwise it MUST abstain, which VC-2770 counts as playing on. A Caretaker MUST always abstain. The policy MUST NOT be a function of current evaluation alone, and abstention MUST be the default rather than the evaluated outcome.
Rationale: VC-2810's wording — "derived from their evaluation and the seed" — invites exactly the wrong implementation, in which an AI concedes because a utility sum says it is behind. That is manipulable: a human can engineer VC-2750's trigger by attacking the runner-up rather than the leader to suppress the denominator, and win by scoreboard arithmetic without conquering anything. Requiring the elimination arithmetic to actually hold, plus a sustained decline, plus no reachable Vigil, makes the vote a conclusion rather than a mood — and it is deliberately conservative in the right direction, playing on whenever the arithmetic leaves a path, which is what makes the solo mop-up disappear without ending a game that was still alive.
16. Legibility
16.1 During play, without breaking fog
AI-752 The client MUST offer a per-opponent Dossier built only from the observing player's own observation log, and it MUST be available for human opponents on identical terms.
KARSK — 41 turns observed, 63 sightings, 9 engagements witnessed · Entrenched on 7 of the last 9 turns you observed him. · Has not initiated an attack on a tile you held with 2 or more units. · 6 of 9 engagements you witnessed were in Hills, Forest or Mountain. · Artillery seen: never fewer than 3 together. · Cities taken from you: 2 (Ashford t91, Rill Ford t104).
Rationale: every line is derived from the player's own log, nothing is revealed, and it turns two
hundred turns of scattered glimpses into the thing a general's staff exists to produce, which is a
pattern. It must be available for human opponents too — if it were AI-only, its presence would identify
an AI seat, which matters for substitution. And most of the work is already done for free by AI-050: the
AI has no private movement policy, so every enemy behaviour a player observes is a behaviour they can
name. A player watching an enemy unit shuffle sideways to keep a frontage in view is watching a
Screen, and they know it, because they have issued one.
AI-756 The setup option Opponents: Named / Anonymous MUST exist, defaulting to Named in solo
and skirmish and Anonymous in tournament play. Under Named, the setup screen shows each AI seat's
personality name, character line and full-expression note (AI-830). Under Anonymous, the player gets the
Dossier and nothing else. The existence of an AI seat is never concealed (AI-055).
16.2 The Intent Record and the Debrief
AI-750 Every AI seat MUST emit a structured Intent Record per turn carrying: the chosen plan, its score, its runner-up and that score, and the terms that separated them; each Operation assigned with its theatre, trigger and force allocation; the triage items examined, which were acted on, and for each declined item the reason — out of budget, below the AI-820 margin, forbidden by a gate, deferred by the commitment lock; every Decisive Point with the predictor inputs and outputs that justified it; whether the Override fired and what it forced; and the Assay decomposition of AI-1060. Intent Records MUST ride the advisory stream (13-command.md CM-190), MUST NOT contribute to any rules hash, MUST be re-derivable from a replay, and MUST NOT affect replay. Sampling level MUST be configurable per context: enabled by default in solo play, disabled by default in ranked play, always on in the farm.
AI-754 At game end the player MUST be able to read every AI seat's Intent Records in full. During the game they MUST be able to read a redacted version limited to facts they themselves observed — which for a well-scouted theatre is most of it and for an unscouted one is nothing, which is correct. The Debrief MUST be able to distinguish being outplayed from exploiting a named blind spot:
Turn 148 — Sable Reach. Your encirclement worked. Colonel evaluates supply Reach, so it saw the road being cut; it committed anyway because its projected relief force arrived on turn 149 and the pocket broke on 148. Turn 91 — Ashford. Your encirclement worked because Lieutenant does not evaluate supply Reach at all. Against Colonel that move does not work twice.
Rationale: that is teaching. It names what happened, distinguishes competence from a gap, and sells the next Rank honestly rather than by adjective. It exists only because §13.2 names the blind spots.
AI-758 The client MAY offer a Second Opinion: post-game and solo only, the player picks a past turn, changes one of their own orders, and watches what the AI does in response. It MUST be labelled precisely as the AI's response to a changed world, never as a claim about what would have happened, because every other seat re-derives too.
17. Getting strong: self-play, tuning, and the line between engineering and research
The organising discipline of this section is one line drawn through the middle. Above it is engineering: known cost, known schedule, known outcome shape. Below it is a research bet, where the honest answer is "we do not know, and here is the cheapest experiment that would tell us." Levels 0, 1 and the Rehearsal search of AI-585 are above the line. Policy learning at scale is below it.
| Level | What it is | Verdict |
|---|---|---|
| 0 · Tuning surface | Every AI number is a versioned integer in a manifest (AI-1020) | Prerequisite. Nothing else is possible without it |
| 1 · Offline weight tuning | A noise-tolerant optimiser over ~200 integer weights, driven by self-play tournaments | Engineering. The largest single strength gain available for the money |
| 1.5 · Rehearsal | AI-585's forward simulation of the Staff's own compiled turn | Engineering, and the best value here. The turn model makes it nearly free |
| 2 · Learned evaluation | A small quantised integer network predicting final placement from a fog-filtered position | Engineering, with a real chance the payoff is small. Sequenced third |
| 3 · Learned policy at scale | Policy prior plus tree search over information sets | A bet. AI-688's probe decides it; not a shipping dependency |
| 4 · Human game logs | Opt-in replay corpus | Engineering, for the right purpose. Diversity, benchmarks and calibration — never strength |
17.1 The pipeline
AI-650 The project MUST maintain an offline self-play tuning pipeline on the headless farm (03-architecture.md AR-970) comprising: (1) the parameter manifest of AI-1020 with declared ranges; (2) experiment configurations covering opponent mix, unit sets, rule presets, map generator seeds, game counts and budgets; (3) massively parallel headless execution with content-addressed, re-runnable jobs (AI-475); (4) metric extraction — win rate, rating against a reference pool, game length, steps consumed, personality signatures, and the balance vector of AI-690; (5) a pluggable optimiser; and (6) a promotion gate (AI-660).
AI-652 Every farm job MUST be seat-paired: issued twice on the same map seed and the same start positions with the arms swapped between seats. Map and start-position variance is the largest variance component in a game where a high-Industry city with a strong trait might be three tiles from one capital and thirty from the other; pairing removes that component rather than averaging over it. A farm that does not pair is discarding roughly a third of its compute.
AI-654 The optimiser's search signal and the promotion gate's signal MUST be different, and MUST NOT be interchanged. The search MAY use a continuous outcome — final Tenure share, mapped to per-mille — because it carries far more information than a binary outcome and a bad direction is corrected next iteration. The gate MUST use binary win and loss, because the gate is the thing that ships.
Rationale: optimise Tenure share directly and you get an AI that plays for score rather than for the win — hoards cities, avoids the decisive risky attack, and loses to a player who takes the Vigil. That is Goodhart's law with a specific address, and the split is the cheap defence.
AI-656 Farm games MUST be adjudicated by proof, not heuristic. 14-victory.md's mathematical elimination (VC-2610, VC-2620) and Capitulation are exactly correct as adjudicators — zero bias, not small bias — and the Ebb plus the Horizon guarantee termination. The farm MUST additionally kill any game with no state-changing event for 20 consecutive turns and file a minimised replay, because a stall is a bug in the AI or the rules and never a legitimate outcome. Because aggressive adjudication biases the corpus away from endgame positions, the farm MUST also maintain a small endgame corpus — positions checkpointed near the Horizon and played out with adjudication off — at roughly 5% of volume.
AI-658 The farm MUST defend against self-play convergence with all of: map seeds that never repeat within a run; a ruleset matrix of at least six combinations of Industry ceiling, Track set and map size; opening temperature over the first 8 turns drawn from the seat's own seeded stream (AI-390), so that opening variety and reproducibility coexist; a share of games against anchors several generations old; a share of games against deliberately off-centre manifests; and a seat-count spread that runs mostly head-to-head with a meaningful minority at four and six seats.
AI-659 Strength MUST be ranked head-to-head on symmetric two-seat maps. Multi-seat results MUST be measured separately, MUST use mean normalised placement rather than win rate, and MUST be used as a health veto rather than as a ranking: a candidate that gains materially head-to-head while losing materially on multi-seat placement MUST NOT promote, and MUST open an investigation.
Rationale: rating systems model two-player zero-sum games and this is not one. In a free-for-all a candidate's win rate depends on the composition of the whole table, on seat position relative to map geography, and — most corrosively — on the fact that 14-victory.md's Watch and Alarm make everyone able to see who is close to winning, so a stronger AI attracts more attacks and can measure as weaker. That is not a bug in the AI; it is a real property of the game that a naive metric reads backwards.
17.2 The gates
AI-660 Promotion MUST require all four: (a) a statistically sound head-to-head win against the incumbent — a sequential test at α = β = 0.05 with an 8-Elo lower bound, seat-paired, across the ruleset matrix, or an equivalent fixed-N test of ≥ 1,000 games at p < 0.05 and ≥ 55%; (b) no regression beyond 10 points against any Antagonist (AI-1330); (c) no regression against any league member — the incumbent, the previous three releases, and the off-centre manifests of AI-658; and (d) no regression on the exploit-specific behavioural tripwires of §19.
Rationale for (b): condition (a) alone is necessary and nowhere near sufficient, because self-play against a single incumbent overfits to the incumbent. Condition (b) is the one that catches "we improved the evaluation and accidentally deleted the reaction-valuation term."
AI-662 The project MUST maintain a frozen anchor ladder: Anchor 0 is the hand-set baseline, its manifest frozen forever and never re-tuned; Anchors 1..n are the promoted versions, retained; and where human games exist, Anchor H is a fixed set of human positions scored by agreement with strong players' choices rather than by rating. A candidate that beats the incumbent but not the median of the anchor sample MUST NOT promote.
Rationale: self-play rating drifts. An AI that beats last month's AI 60% of the time may be worse against a human, because both have specialised into a shared blind spot. Anchor H is the only non-self-referential instrument in the pipeline and it is worth more than its size suggests. The single fastest diagnostic available is Anchor 0's win rate and Anchor H's agreement rate plotted together over every promotion: the first should rise and saturate, the second should rise, and if the first rises while the second is flat, the AI is getting better at beating its own ancestors and no better at playing the game — and every other number in the report is noise.
AI-664 Tuning and shipping budgets MUST be reconciled. After every tuning run the top candidates MUST be re-ranked at the shipping step budget over a paired match before the promotion gate runs; if the ranking at the shipping budget differs from the ranking at the tuning budget, the tuning budget MUST be raised.
Rationale: tuning at a shallow budget and shipping at a deep one is tuning one agent and shipping another — a shallow searcher benefits from cautious weights that compensate for its blindness, and those same weights make a deep searcher timid. This check is the difference between a tuning pipeline and a tuning pipeline that works.
17.3 What ships, and what does not
AI-670 Tuned weights MUST ship as versioned content data with release notes, and every game MUST record the exact AI version, manifest hash, model hash, Rank, personality and salt in its configuration so that replays, bug reports and farm reproductions pin the same behaviour. A weight update MUST NOT change AI behaviour in an in-progress game unless the player opts in. Superseded manifests and models MUST remain retrievable for as long as reproduction of games that used them is offered.
AI-680 No online learning. A shipped AI MUST NOT self-modify weights during or between player games, on player machines or on servers. The single exception is AI-1235's adaptive mixing width, which changes how much the Staff mixes and never what it believes. A clearly labelled experimental mode MAY allow local tuning runs using the same tooling.
AI-685 A learned evaluation MAY replace or augment the Assay's weighted sum only under all of:
inference is integer-only, with int8 or int16 weights, int32 accumulators, clipped activations,
and rescaling by arithmetic right shift — never a divide, never a multiply by a reciprocal; the build
proves accumulator bounds rather than hoping, refusing to publish a model whose per-layer bound can
overflow; no transcendental function appears on the inference path, so the output is a raw integer score
that is ranked and never converted to a probability except through a shipped integer lookup table; the
feature vector is scale-free, expressed as per-mille of a map total or as a ratio, so that a model
trained on one map size transfers to another; the instruction count of an evaluation does not depend on
the data, so that a fuel-metered plugin completes the same amount of search on two hosts with the same
budget; and the quantised model scores ≥ 47% against its own full-precision parent over ≥ 2,000
paired games. Training MUST live outside the core in a separate package, in whatever arithmetic is
convenient, and MUST never be imported by the core or shipped.
Rationale, and the reason the linear Assay ships first regardless: a tuned linear evaluator over well-chosen features is a serious opponent, the gap between "no model" and "linear model" is much larger than the gap between "linear model" and "small network", and the linear form is the only one whose decisions can be explained in a sentence — which AI-750's Intent Record needs anyway. Ship the linear Assay first even if a network is planned, because it is the baseline that tells you whether the network was worth it. The float boundary is not a promise but a structure: the AI's output is an order, orders are integers in the log, and replay never re-invokes AI code (AI-350), so a model change cannot invalidate a saved game. What it can do is produce a false divergence report in farm reproduction and desync arbitration, which is why AI-360's bit-exactness is required anyway.
AI-687 Learning from human game logs MUST be treated as a diversity and calibration instrument, never as a strength target. Behaviour cloning MUST NOT be used to produce the top Ranks: it caps an agent at the average of its corpus and inherits that corpus's systematic errors. It MAY be used to produce a low Rank, where playing like an average human is exactly the goal and fails plausibly by construction. Collection MUST be opt-in, explicit, per-game and revocable; MUST require every seat's consent, since a multiplayer replay is one artifact containing every seat's orders; MUST strip player-authored strings — chat, unit names, map annotations, Doctrine and Posting names — client-side before upload; MUST collect only completed games, asserted terminal before upload, because a mid-game container holds every seat's hidden information; and MUST record, in each shipped model's provenance, the corpus version it was trained from, so that a deletion request can be answered honestly.
Rationale on volume, because the hopeful version of this does not survive arithmetic: a niche turn-based strategy game reaching tens of thousands of owners, at realistic opt-in rates and games per player, produces a corpus the farm can generate in half a day. Human logs are not a volume play. Their entire value is in being different from self-play — Anchor H, opening diversity, and the inhumanity detector that finds positions where the AI's evaluation and a strong human's choice disagree most, which is the cheapest source of "the AI does not understand X" insight that exists.
AI-688 Before any commitment to policy learning at scale, the project MUST build a small-instance lab: a genuinely-same-rules configuration — a small map, two seats, few cities, Industry ceiling 1, one Track, a short Horizon — small enough that a full learning loop is affordable in days rather than months. The lab MUST answer, cheaply: whether a joint action over command objects factorises usefully; whether determinisation under this fog density is tolerable; whether decoupled search is adequate at this simultaneity depth; and whether a learned agent beats the tuned Staff on the small instance. If it does not win there, it will not win on the full game, and the answer cost two weeks instead of two years.
The lab MUST be built regardless of whether the research question is asked, because it is also a fast regression corpus for the whole pipeline, where a full tuning run takes an hour instead of a day.
AI-690 The tuning pipeline, its formats and its metrics MUST be documented and usable by modders against their own AI plugins on self-hosted hardware (00-overview.md pillar 4). The farm MUST additionally emit a balance metric vector from every game, diffed against a rolling baseline, covering at minimum: Stance distribution and stance-fallback rate; kill share from the top Initiative decile; unit-class usage entropy and Works share by class; mean turns from capture to Integration 50, against 12-economy.md EC-570's 25–35 turn payback target; comeback rate after heavy loss; game-length distribution and cause of ending; Track win share; presented-attention-item count against unit count (13-command.md CM-090); and stalled-unit count (CM-1440).
AI-692 A balance finding derived from AI games MUST NOT be acted on without a scripted probe: a hand-written agent that uses the questioned mechanic competently, played against the tuned Staff. If the farm reports that a unit class is never built, "the class is underpowered" and "the AI does not know how to use it" are indistinguishable from the metric alone, and only the probe separates them. Balance flags MUST additionally be re-checked at the release step budget before any number in a design document is changed.
18. The adversarial programme
18.1 Why this section exists
Self-play measures relative strength, and blind spots are shared. Two agents that both never encircle, never cut supply, never secure their rear and both stop attacking will produce a perfectly balanced 50% win rate, healthy game lengths, a clean ladder and green dashboards. AI-625's monotonicity gate is satisfied trivially by a ladder of equally-blind agents differing only in step budget. And every balance metric in this specification set measures whether the game is working, not whether the AI is good. That gap is the whole problem, and an AI that fails silently is the worst outcome available.
18.2 The predicted exploits, named
AI-1300 The following exploit classes MUST be treated as predicted failures with owned mitigations and owned detections. An implementer MUST be able to test for each by name.
| # | Exploit | The mechanism | Mitigated by | Detected by |
|---|---|---|---|---|
| E1 | The Blindfold — one cheap Recon held at range disarms screens and deadlocks surveys, permanently, because an unobserved strength predicts conservatively (13-command.md CM-160, 11-combat.md CB-2260), a conservative prediction fails the Cautious test (CM-690), and a Survey excludes the whole region | AI-1132's 3-turn escalation; AI-1130's reconnaissance obligation; AI-1305 | AI-1400 rows 1–2 | |
| E2 | The Scarecrow — parking an expendable unit adjacent to a column halts it for the activation under 13-command.md CM-1340's Opportunity |
AI-1307 | AI-1400 row 3 | |
| E3 | The Decoy — CM-610 selects the target with the highest predicted per-mille, so a crippled unit placed beside a valuable one absorbs the attack forever | AI-1308 | modal target value per engagement | |
| E4 | Threshold surfing — every Sanction is an integer threshold with a published default and the predictor is exact and shown to the human, so a player can compute the decision boundary and build permanent walls or permanent baits one per-mille either side | AI-1309 | Antagonist A10 | |
| E5 | Ford squatting — Initiative terms are public and Contacts reveal Stance, so a cheap fast unit dropped on a tile an Operation depends on invalidates it | AI-1250's conditional orders | AI-1420 | |
| E6 | Requisition steering — sustaining losses on the highest-weight Posting keeps it perpetually eligible under CM-1190's deficit round-robin, starving every other front | AI-1306 | shortfall variance across fronts | |
| E7 | Contact flooding as compute denial — more Contacts mean more candidates, more predictor calls, more plan invalidation, so a human generating cheap contacts directly reduces the AI's search depth and sets its difficulty from inside the game | AI-1306 | AI-1440 | |
| E8 | The Gravedigger — retreat destinations are a published deterministic formula shown in the preview (CB-1310, CB-1370), so pre-placing one unit on the last exit converts a marginal attack into the destruction of a whole stack | AI-1160, AI-1165 | AI-1400 row 8 | |
| E9 | The Kite — a withdrawing screen with depth behind it trades space forever, and an AI whose plan is "advance to objective" wins every engagement while gaining one tile per turn | AI-580's fixing-force representation | tiles gained per attack initiated | |
| E10 | The artillery threshold — bombardment has a minimum viable concentration below which it accomplishes nothing, so a per-unit evaluator builds guns, deploys them in ones and twos, and achieves exactly nothing at full cost, forever | AI-1304 | modal batteries in range per siege turn | |
| E13 | The Clerk — hunting Cadre and Depots, which are the anti-snowball engine and the supply graph's articulation points, and are the softest targets in the game | A29, AI-1302, AI-1310 | Cadre and Depot loss rates, AI versus human | |
| E14 | The Ratchet — raid a high-Industry rear city, degrade it, abandon it; recapture does not restore Industry, and a level-only evaluator sees twelve small negatives rather than a collapsed industrial base | A30 | AI-1400 row 11 | |
| E15 | The Ferryman — trading the same border city back and forth, exploiting Loyalty memory, which returns the city to its original owner at full value | AI-1215 | capture-and-loss cycles per city | |
| E16 | Loser's buttons pressed while winning — options whose correctness depends on remaining game length or on losing | AI-1180 | emergency-measure use while leading | |
| E17 | The Bellringer — pushing across a threshold publishes the addresses of your own garrisons (VC-2280, VC-2290); one raid resets the Vigil; repeat | AI-1303 | AI-1400 row 12 | |
| E18 | The Herring — feints at Landmarks and Warrants, which are magnets, abandonable at no cost, and arrive on a published metronome | AI-1301 | committed-versus-claimed gap | |
| E19 | Ascendancy ambush — the calendar says where and when, and deterministic pathfinding (AR-750) says by which route, computable to the tile | AI-1240 | route-diversity metric | |
| E21 | Verdict manipulation — engineering VC-2750's trigger by suppressing the runner-up rather than attacking the leader, and winning by vote | AI-940 | Antagonist A14 |
18.3 The mitigations this document owns
AI-1301 The Staff MUST value a non-terminal objective — a Warrant, a Tally, a contested site —
at payout × P(win the contest) − cost of the detachment's absence, MUST have an explicit
withdraw-from-contest decision when observed opposing commitment exceeds a threshold, and MUST
hard-cap the fraction of its mobile force committed to non-terminal objectives at 25%.
AI-1302 The Staff MUST maintain a rear-security Posting whose Requisition scales with the count of Cadre in transit and the number of Depot articulation points, and MUST value a rear city at replacement cost — the upgrade cost plus the turns to rebuild — rather than at current output.
AI-1303 The Staff MUST price entry into the Alarm band as a cost, reducing its estimated hold probability by a term proportional to observed enemy mobile strength within reach of the sites that would be published (VC-2290), and MUST have a hold-at-threshold-minus-one mode that accumulates force without progressing the objective until it can hold the Vigil.
Rationale: the correct play is frequently to sit just below the threshold and accumulate, deliberately not progressing. That is profoundly counter-intuitive for a progress-maximising evaluator and will not emerge from tuning; it has to be a mode the planner can choose.
AI-1304 The Staff MUST represent a mechanic with a minimum viable concentration as a group asset with a minimum size, not as N independent units, and MUST NOT commit it below threshold.
Rationale: this failure has the worst evaluation properties of anything in this document. Self-play eventually fixes it, because the population discovers the threshold; human review never does, because the build ratios look correct in aggregate while the deployment is wrong in every instance. It registers as an AI that builds a reasonable-looking army and never takes cities, which the team will attribute to almost anything else.
AI-1305 Where the Staff's avoidance behaviour and its attack authorisation would consume the same conservative prediction, the Staff MUST distinguish them: attack authorisation MUST use the pessimistic reading of an unobserved field and avoidance MUST use the realistic one. 11-combat.md CB-2330 already evaluates over the full domain of an unobserved input, so both readings are available from one call, and this document places the corresponding contract on 13-command.md in §22.
AI-1306 The Staff's per-turn cost MUST NOT scale with contact count. It MUST cluster Contacts before reasoning about them, cap the number individually reasoned about per turn at a constant, and MUST NOT let plan re-validation cost scale with contact count. It MUST additionally damp Requisition shortfall by counting deliveries over a trailing window, and MUST hold a central reserve Posting whose weight rises with the variance of shortfall across fronts.
Rationale for the reserve: greedy allocation across many fronts is the classic "everywhere weak" failure, and it is the default behaviour rather than an accident. E6 and E7 are the same attack seen from two sides — one steers the AI's production, the other steers its search depth — and both are the opponent setting the AI's difficulty from inside the game.
AI-1307 For an AI seat, an engine interruption that would halt a unit MUST resolve by the seat's pre-committed policy rather than by halting and banking movement. An AI seat is by definition always absent from the Cascade, so a halt-and-ask interruption is a halt with no ask.
AI-1308 Where the Staff hand-orders a target (AI-060), it MUST select by integer expected value — gain weighted by predicted success against loss weighted by failure, cross-multiplied — and MUST NOT select purely by highest predicted win probability. §22 records the corresponding recommendation to 13-command.md, which would fix the same problem for a human player's automated units.
AI-1309 The Staff's own decision thresholds MUST NOT be the shipped Sanction defaults, and MUST carry a per-game secret offset drawn from the salt of AI-1225.
Rationale: moving a threshold moves the boundary; it does not remove it. Any agent whose behaviour is a threshold function of a predictor the opponent also holds is exploitable at the boundary, and the predictor is exact and shown to the player by design (11-combat.md). A per-game secret offset is the only structural answer, and it costs nothing.
AI-1310 The Staff's internal triage MUST be a separate function with its own terms and MUST NOT be 13-command.md's Dispatch Urgency score. The Staff MAY read Attention Events as change signals (AI-545) and MUST NOT depend on them for unit behaviour (CM-1630).
Rationale: the Dispatch is sitting right there and is exactly the shape of a triage, which is what
makes this the most tempting shortcut in the project. Its terms are tuned for human working memory — a
bounded item count, a capped stake term, tempo deliberately outweighing distant stake because a distant
item will resurface. Every one of those calibrations is correct for a person and wrong for an agent
whose constraint is compute rather than attention. The concrete damage is E13: CM-1720 caps the
UnitLost stake at 40 regardless of unit cost, so borrowing it tells the Staff that losing an
Administrative Cadre and losing the cheapest infantry are the same event. §22 records the corresponding
recommendation to 13-command.md for the human-facing half of that problem.
18.4 The Antagonist roster
AI-1330 The project MUST maintain a roster of Antagonists: fixed, deliberately narrow scripted agents, one per exploit class, each doing one thing and nothing else, run nightly against every Rank. The pass condition MUST NOT be "the AI wins"; it MUST be:
winRate(AI vs Antagonist_i) ≥ winRate(AI vs mirror) − 10 points, over ≥ 1,000 games per cell.
A gap larger than that names the exploit, because the Antagonist only knows how to do one thing. The roster MUST be at minimum:
| ID | Antagonist | What it does, and nothing else |
|---|---|---|
| A1 | Blindfold | Parks cheap Recon at range from enemy screens and survey regions; never closes; never fights |
| A2 | Scarecrow | Parks expendable units adjacent to enemy columns and staging tiles; squats key crossings with high-Initiative units |
| A3 | Kite | An all-withdraw screen with depth behind it; trades space forever; never counterattacks |
| A4 | Gravedigger | Computes enemy retreat destinations from the published formula and pre-blocks them; wins only by no-retreat destruction |
| A5 | Clerk | Hunts Cadre and Depots exclusively; never engages a line unit; lives in the enemy rear |
| A6 | Ratchet | Raids high-Industry rear cities and abandons them immediately; never holds ground |
| A7 | Ferryman | Deliberately loses and retakes the same border city forever, exploiting Loyalty memory |
| A8 | Bellringer | Waits for the enemy's Alarm, strikes exactly one published site, resets the Vigil, withdraws |
| A9 | Herring | Feints toward Landmarks, Warrants and Tallies; never commits; ambushes computed approach corridors |
| A10 | Threshold | Presents targets calibrated one per-mille either side of the published Sanction defaults |
| A11 | Decoy | Always places a worthless safe target adjacent to a valuable one |
| A12 | Flood | Generates the maximum number of cheap contacts; measures the victim's achieved search depth |
| A13 | Auditor | The previous release's AI, unchanged — pure regression detection |
| A14 | Solicitor | Attacks the runner-up to engineer the Verdict trigger (VC-2750); never the leader; wins by vote rather than by war |
AI-1332 A new Antagonist MUST be added whenever a human playtester finds a repeatable exploit. Without that rule the roster ossifies at fourteen and the fifteenth exploit ships.
AI-1334 The project SHOULD run an offline exploit miner over uploaded replays: an n-gram over
(AI action class, opponent action class, outcome) sequences, flagging sequences whose conditional
human win rate is anomalously high. Every hit becomes a candidate Antagonist.
Rationale: this is the only mechanism in the plan that finds the exploits nobody predicted, including the ones §18.2 has missed. Event-sourced games are not merely training data; they are an exploit detector, and this is what that property is for.
19. Tripwires
AI-1400 The following metrics MUST exist, MUST be computed from the event-sourced log, and MUST be reported against their thresholds by the stated milestone. Rows marked gate are release blockers rather than metrics with a band. Several exploit the deterministic core to run counterfactual replays, which is a testing asset most projects do not have and this one should use aggressively.
| # | Metric | Target | Catches | Exists by |
|---|---|---|---|---|
| 1 | Withdraw-style reflexes triggered by a conservative unobserved prediction, as a share of all | < 20% | E1 | first playable |
| 2 | Survey regions with zero reachable candidates for N turns | ≈ 0 | E1 deadlock | first playable |
| 3 | March activations ending in an interruption halt | < 5% | E2 | first playable |
| 4 | AI stance-fallback rate versus the human median | below human | E5; conditional vocabulary unused | first AI build |
| 5 | AI conditional-order rate on contestable orders | ≈ 100% | same | first AI build |
| 6 | Tiles gained per attack initiated, 10-turn window | ≫ 1 | E9 | first AI build |
| 7 | Modal batteries in range per AI siege turn | bimodal at 0 and ≥ 3; near-empty 1–2 bucket | E10 | first AI build |
| 8 | Share of AI losses from no-retreat destruction, as victim, versus as perpetrator | both inside 11-combat.md's stated band | E8 | first AI build |
| 9 | Cadre and Depot losses per game, and mean Cadre lifespan, AI versus human | comparable | E13 | first AI build |
| 10 | Works lost to Cadre and Depot kills as a share of Works produced | low single-digit percent | E13 | first AI build |
| 11 | AI mean Industry level, 20-turn delta, while city count is flat or rising | not monotone declining | E14 | first AI build |
| 12 | AI Vigil break rate versus human | comparable | E17 | first AI build |
| 13 | Warrants committed to versus Warrants claimed | small gap | E18 | first AI build |
| 14 | Emergency-measure uses while leading on Tenure | ≈ 0 | E16 | first AI build |
| 15 | Turns since the AI initiated an attack of three or more units; AI mobile force as a share of total | share ≥ 25%, no rising staircase | the turtling fixed point (§21.2) | before first tuning run |
| 16 | Achieved plan depth versus contact count | slope ≈ 0 | E7 | mobile performance pass |
| 17 | Steps consumed per turn, p50 and p99, by Rank and scale | at or under the Rank's budget | budget regression | first AI build |
| 18 | Median formation size at contact; share of engagements at frontage saturation | no upward drift | doom-stacking; AI-570 not biting | first tuning run |
| 19 | Assay spread across independent local-search restarts on one Docket | ≤ 15% | rugged landscape; AI-550 mis-specified | first tuning run |
| 20 | Share of turns with zero offensive Operations assigned, midgame | ≤ 40% | caution mistuned high | first tuning run |
| 21 | Share of assaults committed below 400‰ predicted | ≤ 10% | caution mistuned low | first tuning run |
| 22 | Personality identifiability: a classifier over observable-only behaviour from the first 60 turns naming the personality | ≥ 70% at Colonel | personality is cosmetic | before roster ships |
| 23 | Personality Elo price versus Aurel | 10–60 (AI-805) | too expensive or too cheap | before roster ships |
| 24 | Win rate of a scripted opponent that holds indefensible cities to inflate the unaccounted-force estimate | ≤ 55% | belief estimator exploitable (AI-1120) | first tuning run |
| 25 | Any Caretaker action outside the AI-492 mandate | 0 — gate | Caretaker overreach | before substitution ships |
AI-1410 Gate — the Constraint Floor. Violations of any clause of AI-560 or AI-620, per 1,000 unit-turns, at every Rank: zero. A single violation at Cadet is a defect, not a difficulty setting.
AI-1405 Gate — the fog leak. Mutate any element of world state invisible to seat P; re-run
the Staff for seat P on the resulting state; the emitted order set MUST be byte-identical. This MUST
run in CI over the benchmark corpus. Any byte difference is a release blocker. A second, weaker gate
MUST run alongside it: a mechanical assertion that Staff code never reaches the true-state API at all,
in the same way the determinism lint forbids ambient randomness.
Rationale: this is the most important test in the document. A fog leak in the AI is invisible, devastating to trust, and the single easiest bug to introduce while building an opponent model. It is cheap to run, it fails loudly, and it is the only mechanism that keeps a hundred small opponent-modelling changes honest over a project's lifetime.
AI-1420 Gate — determinism. The same recorded view on two machines of materially different speed MUST produce byte-identical order sets (AI-375), and the same game replayed on desktop, mobile and the farm MUST produce bit-identical order logs. Any mismatch is an AI-415 violation and a release blocker.
AI-1430 Full-re-plan rate MUST sit at or below 20% of turns in steady state (AI-458), and long routes computed per turn MUST stay inside the platform's route budget, since route caching (13-command.md CM-1470) is a precondition rather than an optimisation.
AI-1440 Achieved plan depth MUST NOT correlate with contact count (AI-1306).
AI-1450 The belief estimator's exploitability MUST be measured by tripwire row 24 and damped if the equilibrium proves degenerate rather than interesting.
AI-1460 Gate — graceful degradation. The same build's win rate at the mobile step budget versus at the desktop step budget MUST differ by no more than 10 points. A larger gap means a cliff rather than a slope, and the mobile build MUST NOT ship until it is closed (AI-457).
AI-1470 Two qualitative measurements MUST be run even though they cannot be automated, because they are the ones that decide whether the AI is worth playing rather than merely strong: a blind panel shown anonymised AI turn summaries against human ones from a matching rating band, which should be no better than 65% accurate at Colonel and above; and a legibility test in which a player shown the Dossier mid-game is asked what the opponent is trying to do, which should be ≥ 70% correct by turn 80.
Rationale: a strong AI that plays like a spreadsheet is a different failure from a weak one, and it is not one a metric catches. It is caught by a person sitting down and saying "that was a real war," and nothing here substitutes for that.
20. Quality gates and CI
AI-700 Determinism regression tests MUST run in CI, for each shipped AI and reference plugin × unit set × representative rule preset: re-run recorded games from seed and assert bit-identical order logs. The matrix MUST span WASM engines, not only operating systems, because the engine is the platform's rather than one we pin (AI-125): at minimum Node's engine on the supported host platforms, plus a headless run in each browser engine the client targets, plus one mobile web view per mobile platform. An order-log divergence between engines MUST be a release blocker and MUST be reported against the engine and the module together, since by AI-380 a conforming module cannot legitimately diverge. Where a headless harness for an engine is impractical, that engine MUST be recorded as unverified rather than dropped from the matrix.
AI-710 Budget-compliance tests MUST assert that the Staff meets its step budget at every Rank and its wall-clock calibration target at Captain on REF-HW (03-architecture.md AR-700) for the benchmark maps, and that hard-cap interruption produces a legal logged fallback (AI-240, AI-420). The suite MUST use 03-architecture.md's normative map tiers by name and MUST include a Standard-tier case and a Large-tier case matching the reference performance fixture (AR-760). Mobile and single-worker runs MUST be held to the same step budgets, with wall-clock measured and reported rather than enforced, and MUST be measured with AI-410 instrumentation active wherever fuel enforcement applies.
AI-715 Nightly the farm MUST run, and each of the first four MUST block on failure: a determinism leg with full hashing across the engine matrix; a sanity leg asserting zero crashes, zero stalls, zero illegal orders and zero Constraint-Floor violations at every Rank; a budget leg (AI-710); and a command-layer health leg asserting 13-command.md CM-090's presented-item bound holds against an AI-driven board from 20 to 400 units and that CM-1440's stalled count stays at zero. It MUST then run the promotion gate (AI-660), the anchor leg (AI-662), a multi-seat health leg (AI-659), the Antagonist roster (AI-1330), and the balance vector (AI-690).
AI-717 The farm MUST support a sampled hashing policy for ranking and tuning runs — hashing periodically rather than every turn — and MUST use full hashing for determinism legs and for any run whose result is evidence in a dispute. A divergence under sampling is still caught, just later, and the minimised-replay bisector closes the gap.
Rationale: this is a place where a plausible-looking default — hash everything, it is safer — would silently cost the project a large share of its farm throughput, quite possibly exceeding all the simulation and all the AI thinking put together. It is worth a line in the configuration and a comment explaining why.
AI-720 A standard benchmark suite — maps, seeds, rule presets, the shipped unit set and at least one custom set — MUST be versioned in-repo and used for tier monotonicity (AI-625), the promotion gate (AI-660), and release-to-release non-regression: a release's Captain MUST score ≥ 45% against the prior release's Captain.
AI-725 A strength regression test — a sequential test with a non-regression band — MUST run weekly and per-release against changes not intended to gain strength, such as a refactor or an engine optimisation. Correctness regressions (desync, illegal order, crash) MUST be caught by the nightly determinism and sanity legs and are never negotiable; behaviour regressions — the AI is no weaker but has become unpleasant to play against — MUST be caught by the balance vector against its rolling baseline, and are the class no single gate can express.
AI-730 The project MUST maintain a rated human ladder with a fixed benchmark AI build as the anchor, so that AI strength is measured in the same units as human strength and a regression is visible as rating movement rather than as an impression. It MUST additionally track the uncomfortable metric: the fraction of human wins against the top Rank in which the human made a repeated, identifiable mistake. If a human beats the top Rank while playing badly, the AI is bad in a specific, findable way, and the replay names it.
AI-735 Determinism CI is not strength CI, and this document states it so that nobody has to learn it expensively: a fully green determinism board proves nothing whatsoever about play quality.
AI-740 Personality-signature tests MUST quantify each personality's character as a measurable difference from Aurel at the same Rank — median turns from contact to first attack, un-integrated city count, entrench rate, share of Operations targeting rear assets, arrival timing relative to a published schedule — and MUST run in the promotion gate. A personality whose signature is statistically indistinguishable from Aurel MUST be re-tuned or cut, never shipped as flavour text.
AI-745 Fault-injection tests MUST cover: trapping plugins; infinite loops and fuel exhaustion; memory-limit breaches; malformed orders; failed restore; hot-reload; a module declaring a disallowed import or a banned feature, refused at load with the named diagnostic (AI-210, AI-380); a worker terminated mid-turn yielding the AI-240 fallback and a replayable log; a memory-growth attempt past the declared maximum trapping rather than being silently satisfied (AI-430); and a fuel-transform version mismatch refused as verification evidence rather than accepted (AI-410).
AI-760 Telemetry, opt-in and subject to 08-services-platform.md's privacy rules, SHOULD aggregate anonymised AI win rates by Rank, personality and unit set to inform tuning priorities and to feed AI-635's measured selector.
21. How strong will this actually be?
An over-promised AI that ships weak is the worst outcome available, so this section is written to be falsifiable rather than encouraging.
21.1 High confidence
The Constraint Floor (AI-560). Garrisons, Cadre routing, Depot chains, lift, endurance, production continuity, no idle unit, no stranded formation, retreat degree. These are arithmetic against specifications that already exist in closed integer form, and they are precisely where opponents in this genre visibly fail. An AI that is perfect here will be perceived as strong before it has made a single interesting decision.
Fog-honest belief (§8) and deadline-driven objectives (AI-525). Both are structurally easy in this game and structurally hard in most others, because 14-victory.md publishes a calendar of what matters and 01-game-rules.md gives belief a real data structure.
Economic reasoning (AI-530, AI-533). 12-economy.md gives exact payback formulas and 02-units-and-industry.md gives an Industry payback. The Staff performs arithmetic the designers already did, and it will make these decisions better than most humans simply because most humans will not do the sums.
21.2 Moderate confidence
Operational assignment by portfolio plus local search. The technique is sound and §6.2's landscape argument is plausible, but "Operations are mostly separable" is an assumption. Tripwire row 19 is the test; if independent restarts scatter, the landscape is rugged and the answer is more restarts or simulated annealing rather than a redesign — but the cost goes up.
Risk-weighted plan choice (AI-1200, AI-1210). The mechanism is elegant and k will need real
tuning; a badly set caution coefficient produces either a suicidal or a catatonic opponent, and both are
worse than a mediocre one. Tripwire rows 20 and 21 bracket it.
Not becoming a turtle. The specific shape collapse is most likely to take, and it will not look like collapse: an AI holding many cities with perpetually short Requisitions and production largely consumed by garrison units finds that every candidate offensive scores below the defensive value of holding, and stops. It becomes a defensive machine that never loses a battle and never wins a game — and it will look healthy in self-play, because both sides do it and the games are balanced and long. AI-1180's horizon estimate is the structural answer: the victory system is the planner's schedule, not a term in its sum. An AI that treats victory as a term will turtle; an AI that treats it as a deadline computes "I hold 22, the floor reaches 25 at turn 190, I need three more cities" and generates an offensive because it has to. Tripwire row 15 detects it, and the counterfactual replay that settles it is cheap: re-run AI-versus-AI games with the Ebb disabled, and if game length is unchanged, the AI was never responding to the clock in the first place.
21.3 Low confidence — the one place this ships weak
The Sandtable is the risk. If its ranking of plans is noise, the entire L2 layer is decoration — an expensive greedy heuristic with a random tiebreaker — and every step spent above the Constraint Floor is wasted. This is exactly the failure mode where an AI is announced as advanced and plays like a script.
AI-1490 The plan-ranking skill measurement MUST be built as a first-class farm job before the Sandtable is optimised: sample 200 turns from farm games; take the top 5 plans by Sandtable score; play each forward in the real engine for 5 turns against a fixed opponent policy; record the true Assay delta; and compute the rank correlation between Sandtable rank and true rank. The response MUST be:
- ρ ≥ 0.5 — the Sandtable earns its cost. Invest in depth.
- 0.3 ≤ ρ < 0.5 — marginal. Hold depth at 2 and spend the budget on local search instead.
- ρ < 0.3 — the Sandtable is not working. Replace it with a one-ply Assay delta, cut hypotheses to one, and ship the greedy-plus-local-search Staff.
Rationale, and the reason this design is comfortable proposing the Sandtable at all: the fallback is still a competent opponent. Greedy assignment plus local search on a static evaluation, over a good Docket, on top of a perfect Constraint Floor, is roughly what the better shipped strategy AIs are. We would lose the multi-turn concentration and the risk-weighted strategic dilemma, which are the two things this design most wants, but we would not lose the product. Building the measurement first is what tells us whether to optimise the Sandtable at all.
21.4 The honest ceiling
This design aims to beat most players and lose to experts. It will not be superhuman, and the gap against a strong human will be exactly where §21.2 says: choosing the decisive axis and timing a concentration, where human pattern recognition over a hundred games is worth more than a quarter of a million integer steps. What the Staff will have that a strong human will not is that it never gets tired, never leaves a city empty on turn 140, always does the Cadre arithmetic, and always notices the Alarm on the turn it fires.
Two further honest notes. The Staff has no long-horizon commitment beyond the switching cost: it re-derives its plan at every trigger, while a strong human plays a forty-turn plan. Fixing that properly needs plan persistence with an explicit commitment ledger, and it is deliberately out of scope for the first version, because a half-built commitment mechanism produces an AI that stubbornly pursues a dead plan — which is worse than one that re-plans too often. Open question 7 states the shape.
And: self-play makes the AI good at playing itself. AI-658's diversity mechanisms mitigate this and do not eliminate it. The honest expectation is that the Staff will have a characteristic style, that strong human players will find its weaknesses within a few dozen games, and that patching those weaknesses is an ongoing content activity rather than a one-time training run. Plan for AI updates as a live activity, or accept that the AI is at its strongest on release day and declines relatively thereafter. AI-352 is what makes that affordable: an AI change breaks no replay and needs no rules version.
21.5 What this design is deliberately not doing
- No full-game tree search over the real engine. A full Cascade at scale is far too expensive for the thousands of simulations a Monte Carlo method needs; the forward model has to be abstract, which is why the Sandtable exists. Tree search over the Sandtable was considered and rejected for the shipping configuration: the tree is shallow in turns rather than moves, the leaf evaluation is deterministic so an exploration bonus has little to buy, and random rollouts would put PRNG consumption on the decision path. The condition under which it becomes right is specific — a value function with genuine uncertainty estimates, or opponent hypotheses as a sampled distribution rather than three fixed cases — and this decision should be revisited then.
- No neural network in the shipped client at version one. AI-685 states the gate.
- No per-unit tactical search. Delegated entirely to the core (AI-575).
- No online learning beyond AI-1235's mixing width.
- No cheating in any form. §3, and AI-1405 makes the claim mechanically checkable rather than merely asserted.
- No coordination between AI seats (AI-340).
- No modelling of human psychology. No bluffing model, no tilt detection, no adaptive difficulty inside a game. Tempting, and a different project.
22. Contracts on other documents
Obligations this document places on subsystems it does not own, recorded so that a change on either side is detectable (00-overview.md OV-060).
| From | What is needed |
|---|---|
| 10-turn-model.md | Initiative computable by a seat from its own committed state, and the seat's own relative activation order readable before commit (TM-380), with the global order remaining withheld (TM-1120). Rolling planning (TM-2550) opened to AI seats on the same terms as human clients. A forked Cascade over a candidate order set, without mutating the live world — AI-585's Rehearsal depends on this and on nothing else. |
| 11-combat.md | The exact predictor over a fog-limited knowledge view (CB-2250, CB-2300) at the cost CB-2590 states, remaining the AI's only predictor (CB-2290). The pivot analysis of CB-2340 exposed as a callable that names the dominant unobserved field, so the Staff can generate reconnaissance against it (AI-1130). The full-domain evaluation of CB-2330 exposed as a pair — the pessimistic and the realistic reading — so that attack authorisation and avoidance can use different ones (AI-1305). The aggregate and support shape used by AI-570, so the Sandtable's arithmetic and the engine's do not diverge. |
| 12-economy.md | Effective Works, Levy, Integration, Unrest, Reach propagation, supply state and the Cadre cost curve exposed as pure functions over a hypothetical state, callable outside the turn pipeline, so the Sandtable's economy is exact rather than approximated (AI-565). The garrison requirement by class and Integration (EC-1170) queryable per city. An incremental Reach query (AI-1170). |
| 13-command.md | Everything, unchanged: the Staff writes Postures, Sanctions, Formations, Groups, Postings, Consignments, Requisitions, Doctrines and Tasks, and reads them back. Four requests, all small. (a) A read API for a seat's own Attention Event stream, which CM-1610 already requires to be emitted, so the Staff can use it as a change detector (AI-545). (b) Confirmation that CM-100's "identical for every AI seat" means the AI uses the same core command layer, which §6.2 rests on. (c) Recommended amendment: CM-610's target selection by highest predicted per-mille has no term for target value, so an automated unit always eats the safest available target rather than the most valuable — an unlimited-duration tempo sink for a human player's automation as well as for an AI. AI-1308 states the Staff's own rule; the human-facing half belongs to 13-command.md. (d) Recommended amendment: CM-1720 caps the UnitLost stake at 40 regardless of unit cost, so the Dispatch tells a player that losing an Administrative Cadre and losing the cheapest unit are the same event. AI-1310 stops the Staff inheriting that; the player-facing half belongs to 13-command.md. |
| 14-victory.md | Per-Track progress and threshold functions evaluable at a hypothetical state, which VC-350's uniform shape already promises the AI evaluator. The banded values as a seat sees them, with band edges, so AI-1120's force accounting uses published information and nothing more. The Ebb closed form, the Tally rotation and the Warrant schedule as forward-readable data. The AI Verdict policy VC-2810 asks for is supplied in AI-940. The calibration table of VC-3210 needs a Rank column, because a game against a top-Rank AI is a materially shorter game than one against the default Rank, and a length estimate that ignores that is one of the lies that document is worried about. |
| 01-game-rules.md | Chokepoints from map generation where derivable, or the terrain data to derive them once at load (AI-520). Region membership per city and the abstract chunk graph the Atlas is built on (AI-515). |
| 02-units-and-industry.md | Capability fields and the closed flag vocabulary (US-380, US-470) sufficient that the Staff never branches on a unit's identity (AI-590). Industry upgrade costs and outputs for the payback computation. The per-player Industry cap as the handicap lever of AI-105. |
| 03-architecture.md | Hierarchical pathfinding callable for abstract node-to-node distance (AR-750). A worker to run the Staff off the UI thread (AR-860's fallback included). The AI-private stream derivation (AR-370) and the one-way worldgen seed (AR-400). The PluginRuntimeConfig record (AR-857). An ai/ row in the container table, optional and outside the state hash (AR-560, AR-570). The fog-leak property test extended to include an AI seat (AI-1405). A measured games per core-hour figure for the standard tuning game published alongside the benchmark suite, because every cost in §17 rests on unmeasured budgets until it exists. |
| 05-multiplayer.md | The substitution transport and consent flow (MP-1010), which this document supplies the mandates for (AI-485 through AI-498). The ranked-play policy for third-party AI seats, which AI-370 constrains but does not settle. |
| 07-modding-content.md | The plugin container, sandbox, signing, transport (MOD-660) and SDK roster (MOD-670(a)), and the fuel-metering transform (MOD-610, MOD-615), all cited rather than restated. MOD-1290's three findings are resolved here: the deleted-requirement citations are gone, AI-230 is restated against Orders and the Cascade, and AI-600 no longer contemplates executable content in a unit set. |
| 08-services-platform.md | The farm as a service at the scale §17 needs; the rating pool that feeds AI-635's measured selector and AI-730's ladder; the nightly regeneration gate; and version pinning of AI build, manifest and model in every game configuration and replay header (AI-670). |
| 04-ui-ux.md | The difficulty selector with its measured number and named blind spots (AI-630, AI-635, AI-640); personality setup cards including the full-expression note (AI-830) and the Override warning (AI-835); the Dossier (AI-752); the Debrief and the Second Opinion (AI-754, AI-758); the Terms disclosure of substitution policy and every active handicap (AI-100, AI-494); and how a replay viewer distinguishes an authority-issued fallback order (AI-240) from a seat-issued one. |
Open questions
Is the Sandtable earning its cost? AI-1490 is the measurement and it must be built before the Sandtable is optimised. Everything in §6.4 and §6.5 is contingent on its answer, and §21.3 states the fallback.
Is the plan-and-compile separation (AI-580) affordable at version one? It is the red team's sharpest correction and it is also the largest single piece of architecture in this document. The cheap version — plan in the order vocabulary and accept the ceiling — is what most projects ship and it is why most strategy AIs cannot conceive a feint. The decision must be made before anything else is built, because it is the shape of the system rather than a feature of it.
Should
AI Full Vision(AI-330) be withdrawn? 00-overview.md OV-110 requires it to exist as a labelled, disclosed, recorded, off-by-default option, and AI-330 provides it. The argument for withdrawing it entirely and shipping only AI-150's Foreknowledge is in AI-330's rationale and this document finds it persuasive: full vision does not make a harder opponent, it makes a different and worse one. This is a change to OV-110 and therefore not this document's to make.How many opponent hypotheses, and are they the right ones? Passive / Continuation / Best reply is a guess. A fourth — an opportunist that assumes the opponent takes whatever is left undefended — may be worth more than Best reply at a tenth of the cost. The farm can settle this by ablation and should before the top Ranks are tuned.
Is the marginal forked Cascade cheap enough for the Rehearsal (AI-585)? The estimate that a copy-on-write fork with activation memoisation brings a candidate Cascade to a small fraction of a full one is the single load-bearing unmeasured assumption in this document. It is measurable as soon as the Cascade exists and it should be measured before anything else.
Is trigger-based re-planning (AI-545) safe, or does it produce a lazy AI? The saving is large and the eight-turn anti-staleness floor is a backstop, but a slowly deteriorating position that never fires a trigger is exactly the case where re-planning matters most. The Assay-gradient trigger is in AI-545 and its threshold is not yet chosen.
Long-horizon commitment. §21.4 names this as the main strategic weakness. The shape of a fix is a commitment ledger, in which an Operation the Staff has invested
Nturns in accrues a decaying bonus to its own continuation. The danger is obvious: a badly-tuned ledger produces an AI that pursues a dead plan into a wall, which is a far worse failure than re-planning too often. It needs a designed decay curve and a hard abandonment override.Commit-reveal for the mixing salt (AI-1225). In ranked AI-versus-human play where replays must verify, the salt's hash must be published at game start and the salt at game end. The mechanism belongs to 05-multiplayer.md and is not yet specified there.
Does the Staff's own triage need its own attention model, or is a ranked list of Constraint-Floor obligations plus Docket value enough? AI-1310 forbids borrowing the Dispatch's Urgency score but does not specify the replacement's terms.
Fuel calibration under instrumentation (AI-410). The transform makes fuel counts portable, but the fuel-to-wall-clock ratio still varies by engine and device, so a budget generous on the reference host may be tight in a mobile web view. Pin one fuel figure per context and accept the spread, or calibrate a per-platform multiplier at install from a startup benchmark — which is a wall-clock input and so MUST NOT be allowed to change the recorded budget in any verification context. Either way the benchmark result is host-side only: with no clock in the ABI, plugin code cannot observe it, which is the property that keeps AI strength independent of hardware.
The memory caps of AI-430 and AI-435 are estimates, not measurements, and the question got harder rather than easier: on a client the AI aggregate, the AI-235 core replica and the whole UI share one process with an OS-imposed ceiling. Do the caps belong here permanently, or should they migrate into a plugin-memory row of 03-architecture.md's budget table once measured — and does that row then need to be a client-process budget rather than a per-subsystem one?
App-store policy for workshop-installed AI plugins on mobile (AI-275). Code executed by the web view's own engine is the sanctioned exception to the rule against downloadable executable code, but a plugin fetched from our workshop is an untested framing of it. Ship workshop AI on mobile, restrict mobile to shipped personalities, or seek a review determination first? A policy question, not a technical one, but it decides whether AI-270 is platform-complete.
Ownership boundary for the plugin host. 03-architecture.md AR-060 names AR-855 as the host requirement, and this document specifies instantiation (AI-125), import vetting (AI-210), fuel instrumentation (AI-410), worker isolation (AI-440) and memory caps (AI-430). Two of the five now have an answer to record — the import object's contents are AR-855's to constrain with AI-200 as the AI-specific instance, and metering is deterministic fuel with wall clock demoted to the AI-420 watchdog — and the remaining three need a single owning identifier each, agreed before implementation begins.
Engine-diversity policy when AI-700 finds a real divergence. WebAssembly's semantics say a conforming module cannot diverge between conforming engines, so the honest options are to block the release, ship with the affected engine excluded from verification contexts (AI-370), or carry a plugin-side workaround. Decide the policy before the first divergence rather than under release pressure.
Is a zero-Decisive-Point Cadet too strong? The command layer is good enough that an AI which merely sets sensible Postures may be a harder first opponent than a beginner should meet. The fix if so is worse Sanctions — a higher engagement threshold so it rarely fights, a tighter Leash so it rarely arrives — which is still competence-shaped weakness but is a second weakness mechanism, and two is one more than this design wants.
Do Captain and Colonel feel different to a player who does not understand supply? The features that separate them are the ones a strong player values most and a casual player notices least. If the middle of the ladder is flat, something other than omission has to differentiate it, and it is not clear what.
Does personality survive repeated tuning? AI-810 freezes the offsets but not their meaning: when the baseline moves, every offset points somewhere slightly different, and after several promotions a personality may be something nobody designed. Re-measuring the price (AI-805) catches the magnitude of the drift but not its direction, and periodic hand review is not a system.
Is Sabar a good addition to a multiplayer game or a rigged one? AI-935 turns it off by default above one human seat and clamps
predation. In solo it is clearly good — it is what stops a runaway and keeps the middle third of a game live. Between humans it is genuinely unresolved.What does an AI seat do about hidden per-player objectives? It must not act as though it knows another seat's concealed objective. Inferring one from unexplained behaviour is legitimate and is exactly what the top Rank's opponent model is for — but the line between "inferred from observed behaviour" and "read the game state" is one bad import away, and it needs an explicit test rather than an assurance. AI-1405 is the shape of that test; the specific fixture does not exist yet.
Can a fog-honest AI ever stop looking like a cheat? The Debrief answers it after the game; nothing answers it during. The likely real answer is a short in-game explanation attached to any AI action that surprised the player — "it did not see your transport; it was already screening that ford" — but that is an information channel and it needs a fog review this document has not done.