Data Field Schema Alignment — Omega War

Review artifact for the upcoming Deployment Plan prototype field migration. Created 2026-06-23; documentation only.

review schema naming deployment plan no data mutation

Purpose: identify stale prototype field names, map them to the canonical schema targets, and recommend a safe migration order before any fixture or runtime rename begins.

This page uses JS-facing camelCase migration names such as matchPhase, deploymentPhase, unitType, and traitTags. The canonical schema source currently spells one persisted field as card_class; this artifact recommends replacing that target with unit_type / unitType before migration.

Source Record

The Deployment Plan prototype currently uses a compressed fixture/runtime shape. The canonical schema separates authored Card data, deck/decklist card-entry data, and runtime tactical state.

SourceAlignment relevance
research/unthinkable/unit-data-schema.mdDefines Card, Deck, Decklist, recommended DecklistUnitEntry naming, match_phase, deployment_phase, current card_class naming proposed here as unit_type, trait_tags, weapon_slots, transport options, and decklist-entry cardCount invariants.
docs/decklist-rules-alignment.mdReconciles army organization, deck, decklist, phase labels, facility gates, cardCost / cardCount / unitRequisitionCost tuning boundaries, transport boundaries, trait governance, and fixture audit notes.
prototypes/unthinkable/tactical-battle/deployment-plan-first/js/data.jsDefines GAME_DATA.units as the player fixture source and derives roster views, detail objects, and prototype cost/count lookups that map to cardCost/cardCount later.
prototypes/unthinkable/tactical-battle/deployment-plan-first/js/enemy-data.jsDefines read-only ENEMY_UNITS with the same compressed per-card shape plus enemy transport and passenger companion data.
prototypes/unthinkable/tactical-battle/deployment-plan-first/js/state.js, model.js, roster.js, queue.jsCarry runtime names such as selectedBand, bandFromMeta, data-add-band, serialized band, and selectedBand build-order payload fields.

Context / Purpose

current Prototype shape

GAME_DATA.units and ENEMY_UNITS pack authored identity, deck availability, prototype count/cost aliases, display details, physical render type, tactical role hints, weapons, transport, and companion state into one object per card name.

The derived views are useful for the prototype, but the field names now hide which layer owns each value.

target Canonical layers

The schema target keeps authored Card identity separate from deck/decklist placement. The tactical battle state owns the current matchPhase, deployed unit position, damage, suppression, current veterancy progress, and other battle facts.

The migration should name fields by ownership before moving values into separate stores.

Terminology Alignment

naming

Use the agreed production vocabulary in player-facing, design-facing, and schema-facing docs. Retire CardRosterEntry as a production schema term and rename that concept to DecklistUnitEntry.

TermLocked meaning
ArmyOrganizationThe larger historical force pool a player draws from for a scenario or campaign.
DeckReusable playable force package built from an army organization.
DecklistSpecific configured version of a deck for a player, scenario, AI force, saved loadout, or fixture.
DecklistUnitEntryOne configured unit/card entry inside a decklist.
rosterDerived UI projection only, such as category -> phase -> cards. Do not use as a persisted schema object.

DecklistUnitEntry owns deploymentPhase, selected loadout, transport/passenger/equipment choices, cardCost, cardCount, unitRequisitionCost, wonder eligibility, and command-post availability metadata. These are configured entry values, not authored unit/card identity.

Phase Model

urgent

Do not keep expanding band. The current prototype band field is stale because it conflates the tactical battle state's current phase with the deployment-plan / deck availability axis. Stored phase values still remain A, B, and C.

AxisLayerMeaningMigration note
matchPhase
battle state field
Runtime tactical battle stateThe active tactical battle phase: the current in-match escalation window that advances from A to B to C.Use only when the field answers "which phase is this match in right now?" If a later card-specific phase floor is needed, name it requiredMatchPhase or phaseFloor, not matchPhase.
deploymentPhase
schema: deployment_phase
DecklistUnitEntry / Deployment Plan dataThe out-of-battle decklist-entry and deployment-planning phase bucket that governs phase-based gameplay interactions before tactical battle entry.Use when the field answers "which deck/planner phase bucket contains this configured entry or unlock surface?" It is availability metadata, not the active battle clock.
A, B, CStored valuesThe compact phase values stay stable. Player-facing labels can remain Phase A/B/C in deck building and scenario-specific in tactical announcements.Rename the field family, not the stored values.
command-post boundary

Command-post upgrades do not trigger phase progression. The tactical battle advances matchPhase; that phase progression unlocks or grants command-structure upgrades, which can then change availability for deploymentPhase-bucketed decklist entries.

Unit Type

current type is the useful prototype axis

The current prototype type values are infantry, weapon-team, vehicle, tank, aircraft, and structure. They drive popover rendering, stat defaults, selection rows, and visual/type badges while staying broad enough for current design churn.

target unitType replaces cardClass

Use unitType for this axis because cards are individual decklist entries or offerings of units. unitType describes what kind of unit the card produces without locking the schema into premature tactical leaf classes.

recommendation

Rename the prototype's type field to unitType and preserve the current broad values. Do not add a granular cardClass / physicalType split until there is a proven content or UI need; if a finer tactical role axis appears later, add it separately as tacticalRole, roleTags, or an equivalent explicit field.

Mismatch Inventory

Current prototype field or useCanonical targetPriorityRecommended migration action
band on units, queue items, roster cards, and enemy cardsdeploymentPhase on DecklistUnitEntry; matchPhase only on tactical battle stateurgentIntroduce deploymentPhase in fixture and decklist-entry data, derive legacy band during compatibility, and reserve matchPhase for the active tactical battle state after entry.
selectedBand, bandOptions, bandFromMeta, data-add-bandPhase-named equivalents such as selectedDeploymentPhase, deploymentPhaseOptions, deploymentPhaseFromMeta, and data-add-deployment-phaseurgentRename the UI/runtime family with build-order versioning or alias decoding. This is serialized in build-order payloads, so migrate with backward compatibility.
typeunitTypeurgentRename the existing prototype field to unitType and keep the current broad values. Do not add granular cardClass role values until the content model proves a separate axis is needed.
traits string liststraitTags / schema trait_tagsmediumNormalize to arrays of stable tag IDs. Keep display labels in the trait registry rather than comma-separated card strings.
weaponSlots, weaponLayout, and overloaded special slotsDerived display projection from the resolved unit loadoutlaterThe schema should define the loadout shape; authored/server data should hold the possible loadout records; player/deployment state should hold the selected loadout for each unit or decklist entry. weaponSlots and weaponLayout are then loaded as card-face / popover projections from that resolved loadout, not treated as the source loadout schema itself. The current prototype stores the projection directly because each card effectively has one resolved loadout.
details mixed card-face stringsExplicit fields over time: requirements, abilities, transport options, framing notes, unlock text, keyword tagsmediumSplit high-value prefixes first: Requires:, Abilities:, Transport:, Unlocks:, and Keyword:. Keep derived card-face copy terse.
countcardCount on DecklistUnitEntrymediumMap current prototype count to cardCount: total copies/cards of that unit entry available in the decklist. Resolve effective count from selected loadout, equipment, transport/passenger, veterancy, trait, and balance modifiers. Keep the invariant that playable entries resolve to at least one deployable unit instance.
costcardCost on DecklistUnitEntrymediumMap current prototype cost to cardCost: tactical cost to deploy one card/unit entry. Resolve final tactical cost from selected-configuration deltas.
Future deck-builder budget / slot priceunitRequisitionCost on DecklistUnitEntrymediumUse unitRequisitionCost for the deck-building cost to include the unit in a decklist in a given phase/configuration. Keep it separate from tactical cardCost.
tow and transportTransport options plus equipment mount/carry modelmediumSeparate optional lift choices, required tow baselines, and equipment mount/carry capability. Preserve current eligibility derivation while naming the relationships explicitly.
Enemy desantPassenger / passengerOptions namingmediumRename to passenger language shared with the player-side rider modal and queue item shape. Keep "tank-desant" as historical display copy, not as the schema field name.

Mismatch Feedback

Use these fields to record approval notes, exceptions, blocking concerns, or required edits for each mismatch before the migration pass begins.

Recommended Migration Order

1 Phase family first

Rename and conform band, selected phase state, DOM data attributes, and build-order payload aliases before moving deeper schema fields. This reduces the highest-risk ambiguity.

2 Rename type to unitType

Keep the prototype's broad type values and migrate the field name directly. UI code can then migrate incrementally without forcing premature tactical role classes.

3 Split decklist entries

Move deploymentPhase, selected loadout, transport/passenger/equipment choices, cardCost, cardCount, unitRequisitionCost, wonder eligibility, and command-post unlock metadata out of authored unit/card identity and into DecklistUnitEntry.

4 Normalize support vocab

Convert traits, equipment, transport, passenger, and display-detail strings into named structures once the phase/type ownership split is stable.

scope boundary

This artifact does not implement the migration and does not rename any prototype field. It is the review map for a later data/runtime compatibility pass.

Prototype field mapping for that later pass: cost -> cardCost, count -> cardCount, future deck-builder budget / slot price -> unitRequisitionCost. Derived roster maps remain UI views, not persisted schema.

A later code migration should add compatibility aliases before changing serialized build-order payloads or fixture field names.