Citadels¶
Status: 🚧 Partial — citadel progression model documented; full grid/building runtime partially wired (see SYSTEMS/citadel-grid.md). (re-verified 2026-08-21 vs Sectorwars2102
46bce720. Tip delta from prior0b1a42efstamp is PC #741 / LEG-537 — named citadel upgrade prereq buildings + failed-upgrade GS 400 detail surface.)
The fortified structure that is a colony — population, storage, defenses, and a secure vault. Citadel level drives the colony's phase, capacity, and what defensive buildings unlock.
Citadel level is grid-derived¶
✅ Shipped (CRT-1/2/3). The citadel level is derived authoritatively from the buildings placed on the planet's structures grid — the grid is the source of truth, and
citadel_levelis a cached scalar kept in sync with it.citadel_service.derive_citadel_level(planet.structures)is the faithful inverse of the level ladder; the upgrade path runs place → derive → cache: an upgrade places the required grid buildings, re-derives the level from the grid, and caches the derived value onPlanet.citadel_level(citadel_service.py:586-647). Grid player-management endpoints and a SpaceDock-style grid UI let owners arrange the lattice.
The colony grid is landscape-driven¶
📐 Design-only. Gated on ADR-0091. Prescriptive spec:
../../SYSTEMS/citadel-grid.md.
A planet has one playable grid per colony, materialized at settle from the at-launch expedition result's landscape shape, not from planet size alone. The shape is one of five natural classes plus one engineered class; each is a multiplier on the planet-size slot envelope.
| Shape class | Mult on B |
Topology | Max footprint | Trade |
|---|---|---|---|---|
| COMPACT | 0.85× | dense near-square | 2×2+ | smallest, most efficient upkeep, lowest ceiling |
| TERRACED | 1.00× | stacked tiers | 2×2+ | the neutral baseline shape (the anchor) |
| LINEAR | 1.10× | 1–2-wide strip | 2×1 only (no 2×2) | edge bonuses, cannot host large footprints; caps citadel at L4 regardless of slot count |
| IRREGULAR | 1.15× | disjoint clusters | 2×2+ (gappy) | mixed terrain, fragmented, clearing cost |
| SPRAWLING | 1.30× | large loose footprint | 2×2+ | highest ceiling but highest per-slot upkeep + baseline power draw (the sprawl tax) |
| ENGINEERED | 1.00× | near-square | 2×2+ | ARTIFICIAL + the always-valid safe default/fallback |
📐 Design-only
[P]. SPRAWLING carries a live sprawl tax even without combat: per-slot upkeep and baseline power draw scale with footprint size, so the biggest grid is not a free maximum. Capacity is measured as usable contiguous footprint, not raw slot count: LINEAR's 2×1 cap means a high-count strip is not strictly better than a packable COMPACT.
Slot formula¶
📐 Design-only
[P].
B = 4 + 2·size # planet-size envelope, ∈ [6, 24]
usable_slots = clamp(round(mult · B), 6, 32) # round-half-up; cap raised 30 → 32
| size | B | COMPACT 0.85 | TERRACED 1.00 | LINEAR 1.10 | IRREGULAR 1.15 | SPRAWLING 1.30 |
|---|---|---|---|---|---|---|
| 1 | 6 | 6 | 6 | 7 | 7 | 8 |
| 5 | 14 | 12 | 14 | 15 | 16 | 18 |
| 10 | 24 | 20 | 24 | 26 | 28 | 31 |
A size-5 planet yields 12 (compact) to 18 (sprawling) slots by site — a ~50% swing in ceiling. That swing is why discovery exists.
Capacity cap (landscape-driven)¶
📐 Design-only. This section supersedes the size→max-level cap (the
DECISIONS.md citadel-size-captable) on acceptance of ADR-0091. Usable slots — not size — caps the maximum citadel level, because footprints are multi-cell and shape determines how much the grid can physically hold.
The cap uses a three-channel model (the authoritative resolution of the H[L] arithmetic correction):
C_site = min( C_slots , C_footprint , C_practical )
C_hard = min( C_slots , C_footprint ) # permanent, site-bound (R3)
-
C_slots(hard):max L: usable_slots ≥ CITADEL_MIN_CELLS[L]— verified againststructures.py. TERRACED 1.0× reproduces the current size→level cap exactly by construction (same function, same slot count at mult = 1.0). -
C_footprint(hard, NEW — code-grounded): topology gates the ceiling independently of slot count. Footprint ladder (verified against shipped key buildings): L1–L3 need 1×1; L4 needs a 2×1 (SPACEPORT); L5 needs a 2×2 (ADMIN_SPIRE). Therefore LINEAR (2×1 max, no 2×2) structurally tops out at L4 despite its higher slot multiplier — the canonical "more slots ≠ higher ceiling" case.C_footprintis a validated property of each template, asserted by the build-time harness, not assumed from the class label. -
C_practical(honest achievable floor, resolves Q5):max L: usable_slots ≥ CITADEL_MIN_CELLS[L] + H[L], withH[L]the spare cells a standard build needs to clearFLOOR_AREA[L]/HOUSING[L]at achievable building levels. ProvisionalH = {1:0,2:1,3:2,4:3,5:4}[P], calibrated by the build-time harness — not asserted.H[L]is a cell-count input to the inverse function, never an addend to a level. Note: H[L] lives in the honest floor (C_practical), not in the hard cap — adding H[L] to the hard-cap threshold would lower the current size→level cap on small planets (verified: size-1 6-plot = L3, butMIN_CELLS[3]+H[3]=7>6would give L2).
📐 Design-only. The headline at-settle display is
C_practical(the guaranteed achievable floor);C_hardappears only as a clearly-labeled "potential ceiling — requires densification investment" secondary, never the advertised number (M5). This closes the "advertised L5-capable, actually capped lower, discovered only after settle" gotcha.
Population stays a separate gate. HOUSING is a population requirement satisfied by the
existing population→phase ladder (see colonization.md, untouched), not
by slots. Site choice sets the spatial ceiling; population gates independently exactly as today.
T1 excavation (M7): players can raise a site's starting ceiling upward with effort (T1 ships
in v1). R3 is reframed: site sets the starting ceiling + the cost-curve to raise it, not an
immovable cap. T2 orbital annex: design-only/v1-optional. T3 landscape re-template: ⚑ DEFERRED
(destructive migration of a populated colony's planet.structures).
Hidden grid & progressive reveal¶
📐 Design-only
[P]. The full grid is seeded server-side at settle bystructures.py(single writer), but cells are fogged (visibility, not absence). The grid is hidden until the citadel reveals it tier by tier.
- The L1 founding tranche reveals instantly at settle.
- Each subsequent tranche unfogs atomically when the L(N-1)→LN upgrade completes — reusing the
existing
upgrade_hoursbuild timer (see citadels.md upgrade workflow). No new timer, and no fog↔timer rollback edge case: a cancelled/failed upgrade leaves no fog in a half-state. - Reveal schedule
[P](cumulative fraction unfogged by citadel level): L1 35% · L2 55% · L3 70% · L4 85% · L5 100%. - Soft-lock guard:
revealed(L)is always ≥ the cells level L genuinely needs to build — its key-building footprint plus theH[L]spare cells to clearFLOOR_AREA[L]/HOUSING[L]at achievable building levels. Monotonic. - Frontier reveal (M14): radiate outward from the citadel core along the connectivity graph; severed clusters stay dark until reached or bridged. Player-directed reveal is DEFERRED.
- Reclaimable / CLEARABLE cells are shown separately from the headline usable-slot count (M16).
The grid GET returns revealed cells fully and fogged cells as silhouette-only (position + "unrevealed"), so the Grid Manager renders the shape outline with locked cells.
Floor guarantee — validated template library¶
📐 Design-only. No site is a trap. Grids are generated from a constrained shape-template library: each (shape class, size-bucket) maps to a small set of pre-validated silhouette templates whose packing and per-level reveal tranches are validated offline, once, to guarantee the key buildings + the FLOOR_AREA/HOUSING economy fit at the shape's allowed max level.
The template library is the pool from which the at-launch expedition roll draws its result — the planet's profile (type, size, hazard, terrain) weights which templates are more likely to be drawn. This is a generation-time draw from a validated pool, not a pre-stored per-planet map. Traits overlay terrain/hazard/deposit onto cells without altering the validated topology. There is no runtime bin-packing solver — the floor guarantee is a build-time test over a finite library. ENGINEERED is the always-valid fallback. A bad roll is bland, never bricked.
Already-colonized planets¶
📐 Design-only. Already-colonized planets keep their existing size-derived near-square grid and their existing cap — untouched. Only newly-settled sites use the landscape generator. ENGINEERED is the reconciliation home for the current near-square shape.
Levels and capacities¶
Authoritative source: services/gameserver/src/services/citadel_service.py:CITADEL_LEVELS.
| Level | Name | Max population | Safe storage (cr) | Drone capacity | Upgrade cost (cr) | Upgrade hours | Resources required |
|---|---|---|---|---|---|---|---|
| 0 | No Citadel | 0 | 0 | 0 | — | — | — |
| 1 | Outpost | 1,000 | 100,000 | 10 | 0 (free establish) | 0 | — |
| 2 | Settlement | 5,000 | 500,000 | 25 | 50,000 | 48 | 500 fuel_ore + 200 equipment |
| 3 | Colony | 15,000 | 2,000,000 | 50 | 150,000 | 72 | 1,500 fuel_ore + 500 organics + 800 equipment |
| 4 | Major Colony | 50,000 | 10,000,000 | 100 | 500,000 | 120 | 5,000 fuel_ore + 2,000 organics + 3,000 equipment |
| 5 | Planetary Capital | 200,000 | 50,000,000 | 200 | 2,000,000 | 240 | 15,000 fuel_ore + 8,000 organics + 10,000 equipment |
Per-level upgrade costs, durations, and resource requirements are defined in the CITADEL_LEVELS constant in citadel_service.py. The constant is the source of truth — this table mirrors it for reference.
L0 storage is a distinct mechanic from the raw stockpile cap. This table's "Safe storage (cr)" column is the citadel's credit-denominated safe vault — 0 cr at L0 because there is no citadel structure to hold a vault. It is separate from the per-commodity raw stockpile cap (uncapped-goods storage a planet holds regardless of vault access), which is 10,000 units/commodity at citadel level 0 per ADR-0093 item 36 — see
./production.md§ Storage capacity for the full per-level cap table.📐 Design-only — Levels 6–10. The full citadel progression runs to level 10. Levels 6–10 (continuing the lifecycle progression toward larger Capital and post-Capital phases) are design-pending: numeric costs, capacities, and names need a balance pass. Code currently ships levels 1–5; the cap in
citadel_service.CITADEL_LEVELSshould expand once the level-6+ table is finalized.✅ Shipped — level naming.
citadel_service.CITADEL_LEVELSships the lifecycle progression above (Outpost / Settlement / Colony / Major Colony / Planetary Capital), matching the target spec.
Per-level passive bonuses¶
| Level | Production bonus | Notes |
|---|---|---|
| 1 | +5% all production | Establishes basic colony multiplier. |
| 2 | +10% | |
| 3 | +15% | |
| 4 | +20% | |
| 5 | +25% | Capped here; matches the cap in ../../SYSTEMS/planetary-production-tick.md. |
✅ Shipped (2026-06-14) — citadel production bonus.
planetary_service._calculate_production_ratesapplies(1 + 0.05 × citadel_level)to fuel/organics/equipment output. Proven live: a planet's output at L0 → L1 → L5 scaled 1000 → 1050 → 1250 (+5%/level). See FINDINGS.md.
Defensive buildings unlocked by citadel level¶
citadel_service.DEFENSE_BUILDINGS:
| Building | Min citadel | Max count by level | Cost (cr) | Build hours | Effect |
|---|---|---|---|---|---|
| Orbital Defense Platform | 4 | L4: 1, L5: 3 | 500,000 | 168 | 2-sector range, 500 dmg/round |
| Long-Range Scanner Array | 2 | L2: 1, L3: 1, L4: 2, L5: 2 | 75,000 | 48 | 2-sector detection |
| Automated Turret Network | 3 | L3: 2, L4: 4, L5: 6 | 150,000 | 72 | 3 anti-drone kills/round |
Plus shields, drones, rail guns, and the defense grid documented in defense.md.
Upgrade workflow¶
An upgrade is gated by population, resources, and defensive prerequisites, runs over a construction timer, and on completion places the tier's grid buildings and re-derives the new citadel_level from the grid (the cached value is the grid-derived level, clamped by the size cap).
- Meet population requirement — current pop must hit max for current level.
- Stockpile resources — credits + commodities on the planet (or in the safe).
- Meet defense prerequisite — specific defensive buildings must be present and operational, enforced in
citadel_service.start_upgrade:
| Citadel level | Required defensive buildings (all must be operational) |
|---|---|
| L1 Outpost | None (issued at colonization) |
| L2 Settlement | None (auto-progression by population) |
| L3 Colony | Defense Grid L1 OR Automated Turret Network |
| L4 Major Colony | Defense Grid L2 AND Automated Turret Network AND Shield Generator L4 |
| L5 Planetary Capital | Defense Grid L2 AND Orbital Defense Platform AND Rail Gun Battery AND Shield Generator L8 |
The check scans Planet.defense_buildings; missing/offline buildings fail the upgrade with prerequisite_building_missing or prerequisite_building_offline (✅ citadel_service.start_upgrade; origin/feat 46bce720). ✅ tip-PRESENT @ 46bce720 (#741 / LEG-537 MERGED): CitadelManager.tsx CITADEL_PREREQS preflight names the canon buildings (L3 Defense Grid L1 or Automated Turret Network; L4 Defense Grid L2 + ATN + Shield Generator L4; L5 Defense Grid L2 + Orbital Defense Platform + Rail Gun Battery + Shield Generator L8) — not stale "planetary defense level 2+/5+/8+" copy. Failed upgrade surfaces the gameserver 400 detail sentence naming the missing building (pinned by CitadelManager.upgrade.test.tsx for Shield Generator L4). GS re-validates on POST; do not invent a client-side formula beyond the documented table above.
- Initiate upgrade — credits and resources consumed immediately, construction timer starts.
- Wait — citadel remains functional during build; population cap stays at current level until done; partial defensive bonus (+50% of the next level's passive-defense delta) during construction.
- Complete —
check_upgrade_completionapplies the new level when the timer elapses. The same prerequisite check runs again; if a required building was destroyed mid-upgrade, the timer cancels and the player is notified.
Build time & the construction indicator¶
Citadel upgrades are time-based (lazy advance-on-read via check_upgrade_completion, the same pattern as terraforming/market regen — no scheduler). Per-level durations are canon in citadel_service.CITADEL_LEVELS:
| Upgrade | Duration |
|---|---|
| L0 → L1 Outpost | instant — the founding act is the construction (issued at colonization) |
| L1 → L2 Settlement | 48 h (2 days) |
| L2 → L3 Colony | 72 h (3 days) |
| L3 → L4 Major Colony | 120 h (5 days) |
| L4 → L5 Planetary Capital | 240 h (10 days) |
✅ Shipped — live construction indicator (2026-06-14). While an upgrade is in progress the landed-console "Citadel Defense Systems" panel renders a live construction readout: an amber marching-stripe progress bar, a per-second countdown, an absolute ETA, and the target level ("→ Settlement"). It ticks in real time off
citadel_upgrade_started_at/citadel_upgrade_complete_at(both already returned byGET /planets/{id}/citadel) and auto-reveals the finished level when the timer elapses. A compact build beacon (🏗️ NN% · Nd Nh) also shows in the minimized-surface strip so progress is visible when the surface vista is collapsed. The server timer was already in place; this surfaces it in the primary surface with real-time precision. See FINDINGS.md.✅ Shipped — time-based defense-building construction (2026-06-14). Defense buildings now construct over time instead of instantly, using the canon
build_hours(Long-Range Scanner Array 48 h, Automated Turret Network 72 h, Orbital Defense Platform 168 h). The mechanic mirrors the citadel upgrade:build_defense_buildingappends a{type, started_at, complete_at}entry to adefense_build_queueinplanet.active_events(no migration), andget_available_buildingslazily settles finished builds on read (self-committing on GET) — finished entries move into the operationaldefense_buildingscounts. Capacity counts operational + in-progress, so a pending build reserves its slot. The landed console renders a per-building countdown + marching progress bar and a+N🏗️badge; the ops clock ticks while any build is in progress. Proven live: scanner queued (credits −75 k, operational count unchanged,complete_at+48 h), DB held the queue entry, lazy-settle on read completed it to{scanner_array: 1}. See FINDINGS.md.✅ Shipped — mid-upgrade partial defensive bonus (WO-G6), defensePower + combat. While
Planet.citadel_upgradingis true,citadel_service.citadel_passive_defense_ratingreturns the current level's full passive value plus 50% of the next level's passive-defense delta (0.5 × (defense(next) − defense(current)), where passive defense is the level'sdrone_capacity).planetary_service.update_defensesfolds that rating into the returneddefensePower. ✅ Combat consumes the same helper (LEG-164 / PR #652f41de8d8):_calculate_planetary_defense_reductionaddscitadel_passive_defense_rating(planet)intoeffective_fightersfor_resolve_planet_combat. Population cap and other non-defense level effects stay at the current level until the timer completes.
Mid-upgrade cancellation flow (per ADR-0059 N-F3 / N-V5). When a prerequisite-loss event fires during an active upgrade:
- The in-progress upgrade is cancelled in the same transaction as the prerequisite-loss state change.
- All credits + resources committed to the upgrade refund to the player's wallet (full refund, not 50% — the loss event was external, not a player-initiated cancel).
- Realtime event
citadel.upgrade_cancelledpublishes onpersonal:{owner_user_id}:{ "planet_id": "<uuid>", "cancelled_upgrade": "<target_level>", "reason": "prerequisite_building_offline", "lost_building": "<building_name>", "credits_refunded": <int>, "at": "<iso8601>" } - ARIA narrates: "Your
<target_level>upgrade was cancelled —<lost_building>is offline. Rebuild it to resume the upgrade."
The existing citadel level stays when a prerequisite goes offline — passive defense bonuses persist. Only future-progression friction is felt; rebuilding the prerequisite restores upgrade access without forcing a re-acquisition cycle. (N-F3 folded from ADR-0059, re-verified 2026-08-07)
Player-initiated cancellation follows the 50%-refund schedule (the loss is voluntary; the partial refund covers irreversible setup work).
Corrected 2026-08-04. This section previously claimed N-D4's specific-building scan was still unbuilt (flat
Planet.defense_levelscalar only). Stale — the shippedcitadel_service.start_upgradecheck (§ above, step 3) already scansPlanet.defense_buildingsagainst the per-level required list, matching the design intent. N-D4 is shipped. N-F3 (automatic prerequisite-loss cancellation) shipped alongside it this session — see § Mid-upgrade cancellation flow above, now live viaCitadelService.handle_prerequisite_loss. (N-D4 folded from ADR-0059, re-verified 2026-08-07)
The safe vault¶
Every citadel has a secure storage area that survives even if the citadel is destroyed.
| Citadel level | Safe capacity (cr-equivalent) |
|---|---|
| 1 | 100,000 |
| 2 | 500,000 |
| 3 | 2,000,000 |
| 4 | 10,000,000 |
| 5 | 50,000,000 |
Commodity valuation¶
Stored commodities count against the safe's single cr-equivalent capacity, valued at the economy's base trade prices (ADR-0082):
| Commodity | Base price (cr/unit) |
|---|---|
| fuel_ore | 15 |
| organics | 18 |
| equipment | 35 |
Safe contents: - Credits (direct). - Any commodity that fits in cargo (ore, organics, equipment, etc.). - Special resources (Quantum Shards, Lumen Crystals, Prismatic Ore). - Genesis Devices. - Ship upgrades / equipment.
Properties: - ✅ NOT lost on citadel destruction. - ✅ Attackers cannot steal from the safe. - ✅ Transfers with planet ownership. - ✅ Only the planet owner can deposit/withdraw.
Usage: - Deposit/withdraw when docked at the planet. - Optional auto-transfer of planetary production into the safe. - Emergency evacuation: pull all safe contents to ship cargo (subject to cargo capacity).
Citadel destruction consequences¶
When citadel hull hits 0 in combat: - Population dies. - Production facilities destroyed. - Planet reverts to uncolonized — anyone can re-colonize it. - All defensive structures (drones, shields, platforms, rail guns) lost. - Safe contents preserved — recoverable by the previous owner.
Strategic patterns¶
- Multiple Level 2–3 citadels > single Level 5 for most players: distributed risk, distributed production, multiple safe storage locations.
- Level 5 is for prestige and fortresses — 50M-credit safe, near-impregnable defense, team headquarters potential.
- Resource pre-stockpiling is critical — long upgrade timers mean the resources sit unused for days during construction.
Player-facing affordances¶
- ✅ Citadel panel shows current level, next level requirements, progress bars on each requirement (
CitadelManager.tsx; origin/feat46bce720). ✅ tip-PRESENT named-prereq copy (CITADEL_PREREQSDefense Grid / ATN / Shield Generator levels) + failed-upgrade GS 400 detail surface — #741 / LEG-537 MERGED tip ancestor; see Upgrade workflow step 3. - Safe vault UI with deposit/withdraw, auto-deposit toggle, content list. (✅ credit deposit/withdraw shipped; ✅ commodity storage shipped 2026-06-14 — fuel ore / organics / equipment move planet-stockpile ↔ safe, valued at base trade prices against the single cr-equivalent cap per ADR-0082, with a Stored Goods content list in the safe UI; auto-deposit toggle + special-resource/Genesis/upgrade storage remain 📐 design-only.)
- ✅ Live construction indicator — real-time progress bar + countdown + ETA in the landed console, plus a build beacon in the minimized-surface strip (see "Build time & the construction indicator").
- ✅ Cancel an in-progress upgrade —
POST /planets/{id}/citadel/cancelrefunds 50% of the credits paid (resources are not returned) via a two-step Cancel button in the construction indicator (2026-06-14). ✅ Automatic prerequisite-loss cancellation (ADR-0059 N-F3, shipped 2026-08-04) —CitadelService.handle_prerequisite_lossfully refunds credits+resources, clears upgrade state, publishescitadel.upgrade_cancelled, and triggers the ARIA narration above; citadel level is preserved. No producer in the codebase yet destroys/disables a defense building (nothing callshandle_prerequisite_losstoday) — the mechanism is a tested, ready API waiting on that future caller (e.g. a combat-damage or siege path). This is also why grief-detection consumption ofcitadel.upgrade_cancelled(ADR-0059 N-V5's second half) remains unbuilt: it is dependently blocked on this producer, not an independent gap — with no code path that ever fires the event, there is no real signal for an anomaly-detection surface to observe or build against yet. - ✅ Defense building queue — defense buildings construct over time (canon
build_hours: scanner 48 h, turret 72 h, orbital platform 168 h) via a JSONB construction queue lazy-settled advance-on-read; landed console shows a per-building countdown + progress bar; a pending build reserves its capacity slot (2026-06-14). See "Build time & the construction indicator". - ✅ Upgrade pre-flight checklist — the citadel-upgrade confirm lists the credit + population gates with ✓/✗ so the player sees blockers before committing (2026-06-14).
- ✅ Safe quick-fill presets — the safe deposit/withdraw form offers 25/50/75% presets beside Max (2026-06-14).
Source map¶
| Topic | Path |
|---|---|
| Citadel service & level table | services/gameserver/src/services/citadel_service.py |
| Mid-upgrade passive-defense rating (WO-G6) | citadel_service.citadel_passive_defense_rating → planetary_service.update_defenses (defensePower) and combat_service._calculate_planetary_defense_reduction (effective_fighters; LEG-164 / PR #652) |
| Planet citadel fields | services/gameserver/src/models/planet.py |
| Defense building constants | services/gameserver/src/services/citadel_service.py:DEFENSE_BUILDINGS |
| Combat consequences | services/gameserver/src/services/combat_service.py:_resolve_planet_combat |
| Genesis-derived starting citadel | services/gameserver/src/services/genesis_service.py |
Status: 🚧 Partial —
Planet.citadel_*columns,citadel_service.py(level table, time-based upgrade workflow with lazy completion, safe credit deposit/withdraw), the standaloneplanetary/CitadelManager.tsx, and the live construction indicator in the landed console (pages/GameDashboard.tsx, 2026-06-14) are in place. Shipped 2026-06-14 (NEON citadel pass): ✅ +5%/level production bonus, ✅ population gate before upgrade, ✅ upgrade cancel + 50% refund, ✅ time-based defense-building construction (queue + lazy settle), ✅ upgrade pre-flight checklist, ✅ safe quick-fill presets. Outstanding gaps: ✅ specific-building prerequisite scan (ADR-0059 N-D4, already shipped — a prior audit's flat-scalar claim was stale), ✅ automatic prerequisite-loss cancel +citadel.upgrade_cancelledevent (ADR-0059 N-F3, shipped 2026-08-04 — no code producer yet triggers it), ✅ shield-generator construction timer (time-based,level × 6 h, ADR-0086, shipped + proven live 2026-06-16: credits charged up front, level/strength advance on completion via lazy settle, concurrent upgrade rejected), ✅ +50% mid-upgrade passive-defense rating ondefensePowerand combat (WO-G6 /citadel_passive_defense_rating; LEG-164 / PR #652 wires the same helper into_calculate_planetary_defense_reduction), ✅ safe commodity storage (cr-equivalent cap, ADR-0082, 2026-06-14), ✅ ADR-0076 per-unit defense pricing (seedefense.md), ✅ Defense Grid drone-damage modifier (WO-F3, shipped — catalogued + buildable AND wired into_calculate_planetary_defense_reduction, re-verified 2026-08-07, a prior audit's "unwired" claim was stale), and ✅ Rail Gun Battery (catalogued + buildable inDEFENSE_BUILDINGS; raw-burst combat-damage injection wired via_calculate_rail_gun_bonus_damage, re-verified 2026-08-12 — a prior "still unwired" claim was stale — seedefense.md).