Add a new modular LLM ability: space program — nations launch satellites into orbit for a durable prestige/stability bonus.
Design
TurnResult field space (required, default { launch: [], deorbit: [] }):
SatelliteLaunchOp = { by, regionKey, type } — by = nation ref (id first, then unique name via resolveNationRef); regionKey = region the satellite is launched from / anchored to; type in recon|comms|navigation|weather.
SatelliteDeorbitOp = string — the stable satellite id to bring down.
GameState field satellites: Satellite[] (durable, persists in SQLite):
Effects (applied in applyTurnResult, in ABILITIES order):
deorbit first: remove satellites with matching ids (absent id no-op).
launch: resolve by; validate regionKey is a valid key owned by by (launch from own territory); add a satellite with fresh sN id. Unknown/ambiguous by, unowned or invalid regionKey dropped, never thrown.
Per-turn (every committed turn, incl. empty space): each active satellite grants its owner +1 stability (prestige), clamped 0-100, mirrored to every region the owner holds, then the owners derived stats re-derived (same 0-region/no-entry guards as sea/industry). A claim whose nation no longer exists is skipped.
Constraints: at most 1-2 launches per turn, each narrated as a scientific/cultural event; deorbits narrated as military/political.
Payload: always emits satellites (like sea), so the model knows what is in orbit.
Durable: yes -> stateFields: [satellites]; db migration automatic. New Satellite type in shared/types.ts.
shared/types.ts — GameState.satellites + Satellite type
server/abilities/space.ts — new ability module
server/abilities/index.ts — import + append to ABILITIES + re-export helpers
server/abilities/space.test.ts — unit tests
Regenerate goldens if system prompt changes (REGEN_GOLDENS=1 npx vitest run server/abilities/registry.test.ts)
Convention
Follow the existing ability pattern exactly (see server/abilities/sea.ts). New abilities are APPENDED last to ABILITIES — never reorder.
Fixes: none pre-filed; this issue is the tracker.
Add a new modular LLM ability: space program — nations launch satellites into orbit for a durable prestige/stability bonus.
## Design
TurnResult field space (required, default { launch: [], deorbit: [] }):
- SatelliteLaunchOp = { by, regionKey, type } — by = nation ref (id first, then unique name via resolveNationRef); regionKey = region the satellite is launched from / anchored to; type in recon|comms|navigation|weather.
- SatelliteDeorbitOp = string — the stable satellite id to bring down.
GameState field satellites: Satellite[] (durable, persists in SQLite):
- Satellite = { id: s1|s2|..., by, regionKey, type, launchedTurn, launchedDate }.
Effects (applied in applyTurnResult, in ABILITIES order):
1. deorbit first: remove satellites with matching ids (absent id no-op).
2. launch: resolve by; validate regionKey is a valid key owned by by (launch from own territory); add a satellite with fresh sN id. Unknown/ambiguous by, unowned or invalid regionKey dropped, never thrown.
3. Per-turn (every committed turn, incl. empty space): each active satellite grants its owner +1 stability (prestige), clamped 0-100, mirrored to every region the owner holds, then the owners derived stats re-derived (same 0-region/no-entry guards as sea/industry). A claim whose nation no longer exists is skipped.
Constraints: at most 1-2 launches per turn, each narrated as a scientific/cultural event; deorbits narrated as military/political.
Payload: always emits satellites (like sea), so the model knows what is in orbit.
Durable: yes -> stateFields: [satellites]; db migration automatic. New Satellite type in shared/types.ts.
## Files to touch
- shared/protocol.ts — TurnResult.space + SatelliteLaunchOp/SatelliteDeorbitOp shapes
- shared/types.ts — GameState.satellites + Satellite type
- server/abilities/space.ts — new ability module
- server/abilities/index.ts — import + append to ABILITIES + re-export helpers
- server/abilities/space.test.ts — unit tests
- Regenerate goldens if system prompt changes (REGEN_GOLDENS=1 npx vitest run server/abilities/registry.test.ts)
## Convention
Follow the existing ability pattern exactly (see server/abilities/sea.ts). New abilities are APPENDED last to ABILITIES — never reorder.
Fixes: none pre-filed; this issue is the tracker.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Add a new modular LLM ability: space program — nations launch satellites into orbit for a durable prestige/stability bonus.
Design
TurnResult field space (required, default { launch: [], deorbit: [] }):
GameState field satellites: Satellite[] (durable, persists in SQLite):
Effects (applied in applyTurnResult, in ABILITIES order):
Constraints: at most 1-2 launches per turn, each narrated as a scientific/cultural event; deorbits narrated as military/political.
Payload: always emits satellites (like sea), so the model knows what is in orbit.
Durable: yes -> stateFields: [satellites]; db migration automatic. New Satellite type in shared/types.ts.
Files to touch
Convention
Follow the existing ability pattern exactly (see server/abilities/sea.ts). New abilities are APPENDED last to ABILITIES — never reorder.
Fixes: none pre-filed; this issue is the tracker.