feat: expand ISAC content modeling
Validate and deploy production / validate (push) Canceled after 0s
Validate and deploy production / deploy (push) Canceled after 0s
Validate and deploy staging / validate (push) Successful in 28s
Validate and deploy staging / deploy (push) Successful in 1m3s

This commit is contained in:
jb
2026-08-03 01:23:20 -04:00
parent d9924a95b9
commit 57068b61cd
90 changed files with 9635 additions and 1270 deletions
+110 -31
View File
@@ -1572,13 +1572,42 @@ an icon in every option.
### Skill Chip data console
Skill Chip editing uses the dense ISAC staged-definition pattern: identity and
icon, 2-piece numeric bonus, mutually exclusive primary and secondary roll
pools, then 3-piece talent. Superior blue and High-end yellow identify the
supported qualities; reserve orange for actions and the current interactive
state. A four-step segmented preview shows the linear zero-to-three High-end
interpolation without duplicate values. At narrow widths, stack roll-pool and
talent columns, use a two-by-two preview grid, and retain 44-pixel targets.
Place two shared configuration cards above the Skill Chip definition registry.
The `SHARED PRIMARY PROFILE` card contains the fixed Skill Duration, Skill
Radius, Skill Cooldown Recovery, and Skill Intensity rows, with direct minimum
and maximum fields for Standard, Specialized, Superior, and High-end. Its
summary shows the configured count for each quality and the `NOT YET DEFINED`
calculation state. The `SHARED SECONDARY POOL` card contains repeatable
searchable Attribute rows with direct minimum and maximum fields for
Specialized, Superior, and High-end. Its summary shows each quality's fixed
capacity and the shared option count. Each card opens its own editor and closes
that editor after a successful save. Validation keeps the affected editor open
with its values intact. Successful saves append
`game_data/skill_chip_primary_profile.updated` or
`game_data/skill_chip_secondary_pool.updated`.
State the fixed secondary capacities in the pool card and editor: Standard zero,
Specialized one, Superior two, and High-end two. Skill Chip fields never show an
item-level control or level-based preview. Quality labels use the global green,
blue, purple, and yellow treatments; orange remains reserved for actions and
selection. On narrow screens, profile summaries stack, endpoint matrices scroll
inside their cards, and actions retain 44-pixel targets.
Definition editors follow the dense staged pattern: ability assignment, identity
and icon, one per-set 2-piece bonus, then the optional 3-piece Talent. Place the
Talent assignment control before one disclosure that contains the entire Talent
workspace: identity, description, quality-mix preview, and
`MechanicProgramEditor`. The disclosure summary shows the configured Talent name
or `TALENT WORKSPACE`, the quality-scaled outcome count, and an explicit
`EXPAND` or `COLLAPSE` action. Existing Talents start collapsed when an operator
opens a definition. Assigning a Talent or receiving a Talent validation error
opens the workspace. Native disclosure semantics expose the expanded state, keep
draft state mounted while collapsed, and provide a 44-pixel mobile target.
Every equipped chip quality counts toward the two-piece threshold. The set-bonus
preview uses four steps for zero through three equipped High-end chips and the
formula `minimum + (maximum − minimum) × h / 3`; only High-end chips increase
`h`. Do not duplicate calculated values as editable fields.
### ISAC record identity controls
@@ -1808,6 +1837,15 @@ same `weaponBaseRange` curve as the builder; never label the configured base
endpoints as level-50 values. Weapon Talent 1 and Talent 2 pools use separate
clickable icon rails and the standard Talent quick view.
Show each weapon's named Mod slots and slot pictograms between its performance
facts and Talent pools. Native T0 weapons display the complete T1/T2 slot set.
Mark the slot that is absent at T0 with the blue information state and an
explicit `T1+` label so the unlock does not rely on color alone. Other slots use
the neutral telemetry treatment. If ISAC has no slot data, show
`MOD SLOT DATA NOT CONFIGURED`. Do not show the weapon-category bonus count as
`BASE BONUSES`; that identical count does not help players compare weapon
definitions.
Record cards may end with contextual actions that connect related public
registries. Actions use the compact orange tactical-button treatment and encode
their destination filter in the URL. Brand cards provide a “find Gear” action
@@ -1970,18 +2008,26 @@ mode with weapon icons and retained accessible names. Show configured versus
required slot counts in text. Disabled tiers remain visibly unavailable and must
not submit slot assignments.
Quality-scaled registry editors use a compact matrix when the same numeric shape
repeats across all four quality levels. Apply global quality colors only to the
quality labels, retain textual quality names, and keep numeric fields neutral.
On narrow screens the matrix may scroll horizontally while its surrounding
editor and previews stack.
Regular Weapon Mod definitions use a compact Level 1 and Level 20 primary-range
matrix for Standard, Specialized, Superior, and High-end quality. Apply global
quality colors only to the quality labels, retain textual quality names, and
keep numeric fields neutral. On narrow screens the matrix may scroll
horizontally while its surrounding editor and previews stack. Primary core type
remains builder-selected and appears as the three always-available core icons
rather than a persisted ISAC choice. Individual regular Weapon Mod editors also
retain triggerless Mod Effects with one or two Attribute references and fixed
per-quality values.
When two item slots draw from the same canonical option pool, edit that pool
once rather than rendering two duplicated selectors. Weapon Mods use a
repeatable secondary-attribute row: one searchable attribute reference plus four
quality range pairs. Show that the builder selects two distinct options from the
pool. Primary core type is likewise builder-selected and is displayed as the
three always-available core icons rather than a persisted ISAC choice.
Configure one global secondary Attribute pool above the Weapon Mod registry.
Each repeatable row contains one searchable Attribute reference and Level 1 and
Level 20 minimum and maximum fields for Specialized, Superior, and High-end.
Values between those endpoints use linear interpolation. Do not render Standard
range fields because Standard has no secondary slot. State the fixed capacity in
the pool editor and builder: Standard zero, Specialized one, Superior two, and
High-end two. The builder requires distinct selections. Individual Weapon Mod
editors must not repeat or submit pool data. A successful pool save uses the
standard shared-profile lifecycle and creates the dedicated
`game_data/weapon_mod_secondary_pool.updated` audit event.
Exotic Weapon Mod status is a separate single-icon toggle using the exotic icon
and the standard pressed, focus-visible, and selected states. Selecting it must
@@ -1993,12 +2039,20 @@ state panel visible so the change in data semantics is unmistakable.
### Gear Mod registry
Gear Mods reuse the compact quality matrix, level preview, and pooled
secondary-attribute rows established by Weapon Mods. Do not render exotic,
Gear Mods reuse the compact Level 1 and Level 20 primary-range matrix and level
preview established by regular Weapon Mods. Do not render exotic,
weapon-category, slot-type, or Mod Effect controls in this simpler editor.
Present the five primary options as an always-visible informational band because
the actual primary is selected on the build instance, not persisted on the
canonical definition.
the build instance selects the primary; the canonical definition does not store
that selection.
Configure the Gear Mod family’s global secondary Attribute pool above the
registry, separate from individual Gear Mod editors. Use the same three-quality
endpoint rows, linear interpolation, and distinct-selection rule as the Weapon
Mod pool. Capacity is zero for Standard, one for Specialized, and two each for
Superior and High-end. Individual Gear Mod edits must not repeat or submit this
pool. A successful pool save creates the dedicated
`game_data/gear_mod_secondary_pool.updated` audit event.
Use explicit textual tier capacity wherever Gear tier is summarized:
`1 MOD SLOT` for T0 and `2 MOD SLOTS` for T1/T2. On narrow screens the identity
@@ -2325,6 +2379,16 @@ applied to the stored value. Restoration outcomes also expose an `INSTANT` or
field and describes the configured value as the total delivered across that
duration; switching back to instant clears the duration.
Target-scoped direct-damage outcomes offer `HIT-TARGET EXPLOSION` in the Area
Targeting control. Selecting it creates an event-target-centered enemy area with
a five-meter starting radius, reveals the required radius field, and shows a
text readout for the center, valid-target policy, inclusive boundary, and
runtime evidence requirement. Only `ON EVENT` and `AFTER EVENT` remain available
for this mode; selecting it from another phase moves the outcome to
`AFTER EVENT`. Changing the outcome kind or target scope clears an incompatible
area definition. Keep `ENEMIES IN RADIUS · LEGACY` visible for saved descriptive
radius metadata, but do not present that mode as calculated explosion fan-out.
Action Family recipes are optional authoring starters. Present the recipe
catalog as a searchable assignment with only the parameters required by the
selected family. `ADD RECIPE BRANCH` copies typed branches into the current
@@ -2511,10 +2575,11 @@ conditional Talent outcomes, weapon and Skill DPS, encounter assumptions,
activation profiles, rotations, and simulation behind explicit `COMING SOON`
panels.
Loadout schema version 4 retains `maximum`, `custom`, conditional state,
encounter-assumption, and per-ability activation fields for compatibility. The
current player UI ignores those fields. When player simulation ships, one
required two-option `SegmentedChoice` will use these visible labels:
Loadout schema version 5 retains `maximum`, `custom`, conditional state,
encounter-assumption, and per-ability activation fields. Version 4 is obsolete
prototype data rather than a compatibility format. The current player UI ignores
the simulation fields. When player simulation ships, one required two-option
`SegmentedChoice` will use these visible labels:
- `MAXIMUM POTENTIAL` calculates a configured ceiling. It applies conditional
effects at peak state and treats selected abilities as firing on cooldown
@@ -2566,7 +2631,11 @@ Focus sets the primary Attribute, progression tree, and three ordered abilities.
Its identity combines Specialization artwork and the primary Attribute mark.
Each ability panel contains three fixed Skill Chip positions. A chip picker
shows definitions assigned to that ability and excludes definitions assigned
elsewhere.
elsewhere. Skill Chips have no item-level control. The editor uses the shared
quality profiles for direct rolls. It labels the four ability-scoped primary
values `NOT YET DEFINED` and excludes them from current Agent and combat totals.
Secondary capacity is Standard zero, Specialized one, Superior two, and High-end
two; each equipped chip uses distinct selections from the shared pool.
The focus tree groups nodes by row and uses segmented rank controls. Disabled
ranks remain visible with their lock state. The builder permits a row after the
@@ -2581,11 +2650,11 @@ enabled ability. Future Skill result cards will show activation count,
single-target DPS, total-target DPS, and a combined summary. They will state
that Skills can critically hit and multi-shot but cannot headshot.
Saved loadouts store focus, node ranks, nine Skill Chips, conditional modes,
Version 5 loadouts store focus, node ranks, nine Skill Chips, conditional modes,
encounter assumptions, and per-ability activation profiles. The builder accepts
only the current complete structure for compatibility. Current player pages
ignore the simulation fields. Invalid local drafts are discarded; invalid server
records are removed through a backed-up database migration.
only the current complete structure. Current player pages ignore the simulation
fields. The builder discards version 4 local drafts; a backed-up database
migration removes version 4 server records.
### Calculation revision controls
@@ -2650,3 +2719,13 @@ asset and states that the change is permanent. For assigned icons, the
confirmation names the owning entity type. ISAC clears that source icon
assignment before it removes the shared file. General library uploads retain the
`ICON` or `IMAGE` state.
In the Weapon Mod registry, operators manage shared artwork for all eight
code-defined slots. The compact panel labels each slot `ICON REGISTERED` or
`ICON REQUIRED`. Selecting a slot opens the standard icon upload control. Keep
the slot name visible in ISAC after an operator uploads artwork.
On public weapon cards, a configured slot chip shows only its uploaded icon.
Keep the slot name in screen-reader and hover text. Retain the visible `T1+`
marker and blue information treatment for slots unlocked at Tier 1. When artwork
is missing, show the slot name instead of an invented glyph.
+139 -55
View File
@@ -431,11 +431,13 @@ reference.
# OS Protocol progression
OS Protocols use dedicated normalized tables because their talent progression
has six calculated states (base plus five upgrades) rather than the shared
two-tier talent model. Each protocol owns one `os_protocol_primary_effects`
record and one `os_protocol_talents` record. Each protocol Talent owns its
mechanic program through the shared conditional-effect tables.
OS Protocols use dedicated normalized tables because an assigned Talent has six
calculated states: its base value plus five upgrades. Each protocol owns one
`os_protocol_primary_effects` record and may own one `os_protocol_talents`
record. The optional Talent owns its mechanic program through the shared
conditional-effect tables. ISAC keeps the Talent workspace collapsed until an
operator assigns or opens it, and removing an existing Talent requires explicit
confirmation.
Dedicated profile tables normalize the three secondary attributes. One
`os_protocol_secondary_profiles` record exists for each configured quality +
@@ -460,6 +462,15 @@ compatible base weapon categories through `weapon_mod_compatible_categories`;
eligibility requires both a category match and the slot to exist on the equipped
weapon at its selected tier.
The eight code-defined slot types have stable UUIDs and one shared icon each.
Operators manage the artwork in the Weapon Mod registry through the game-data
icon pipeline. Each upload or removal appends a
`game_data/weapon_mod_slot_icon.updated` audit event, and contributors may send
the same action to Data Oversight. Public weapon cards use icon-only slot chips
when artwork exists, with the slot name available to screen readers and on
hover. Cards show the name when artwork is missing and retain the visible `T1+`
marker for slots unlocked at Tier 1.
Exotic Weapon Mods instead reference one `exotic_weapon_id`. They do not carry
regular category compatibility. The builder treats them as permanent equipment
and lets the user change only their level. They do not use quality profiles,
@@ -469,16 +480,21 @@ values in `weapon_mod_exotic_attributes`; intermediate values use linear
interpolation.
All regular Weapon Mods permit Firepower, Toughness, or Engineering as a
builder-time primary choice. `weapon_mod_quality_values` stores the shared
level-1 and level-20 primary roll endpoints for each quality; primary values use
linear interpolation from levels 1–20.
builder-time primary choice. `weapon_mod_quality_values` stores each
definition's level-1 and level-20 primary roll endpoints for each quality;
primary values use linear interpolation from levels 1–20.
`weapon_mod_secondary_options` is the shared pool from which a build selects two
distinct secondary attributes. Every option owns a minimum and maximum at each
quality through `weapon_mod_secondary_quality_values`; secondary availability is
not tied to a numbered slot in canonical data. Mod Effects are triggerless, hold
one or two attribute references, and store fixed per-quality values in
`weapon_mod_effect_quality_values`.
`weapon_mod_secondary_options` stores one global secondary Attribute pool for
all regular Weapon Mods. Each Attribute has Level 1 and Level 20 minimum and
maximum ranges for Specialized, Superior, and High-end quality through
`weapon_mod_secondary_quality_values`; values at intermediate levels use linear
interpolation. Secondary capacity is fixed by quality: Standard has zero,
Specialized has one, Superior has two, and High-end has two. A build selects
distinct Attributes from the pool up to that capacity. Individual Weapon Mod
records do not own secondary options or ranges. Pool updates append a
`game_data/weapon_mod_secondary_pool.updated` audit event. Mod Effects remain
triggerless, hold one or two Attribute references, and store fixed per-quality
values in `weapon_mod_effect_quality_values`.
### Gear Mods and tier slot capacity
@@ -488,42 +504,68 @@ Specialized, Superior, and High-end quality at Levels 1 and 20. Values between
those endpoints use linear interpolation. A build instance selects one primary
attribute from Firepower, Toughness, Engineering, Health, or Armor.
The two secondary slots draw distinct attributes from one shared option pool.
Each available secondary attribute stores its own minimum and maximum for all
four qualities. Gear tier determines capacity without per-item configuration: T0
gear has one Gear Mod slot; T1 and T2 gear have two.
One global Gear Mod secondary Attribute pool serves every Gear Mod definition.
Each Attribute has Level 1 and Level 20 minimum and maximum ranges for
Specialized, Superior, and High-end quality through
`gear_mod_secondary_quality_values`; values at intermediate levels use linear
interpolation. Secondary capacity is fixed by quality: Standard has zero,
Specialized has one, Superior has two, and High-end has two. A build selects
distinct Attributes from the pool up to that capacity. Individual Gear Mod
records do not own secondary options or ranges. Gear tier still determines mod
slot capacity without per-item configuration: T0 gear has one Gear Mod slot; T1
and T2 gear have two.
The `gear_mods`, `gear_mod_quality_values`, `gear_mod_secondary_options`, and
`gear_mod_secondary_quality_values` tables store canonical data. Successful
mutations use `gear_mod.created`, `gear_mod.updated`, `gear_mod.archived`, and
`gear_mod.unarchived` audit actions. Contributor submissions use the `gearmods`
proposal module and remain non-canonical until approved by Oversight.
The `gear_mods` and `gear_mod_quality_values` tables store individual definition
data. `gear_mod_secondary_options` and `gear_mod_secondary_quality_values` store
the family-wide pool. Pool updates append a
`game_data/gear_mod_secondary_pool.updated` audit event. Individual definition
mutations retain the `gear_mod.created`, `gear_mod.updated`,
`gear_mod.archived`, and `gear_mod.unarchived` audit actions. Contributor
submissions use the `gearmods` proposal module and remain non-canonical until
approved by Oversight.
# Skill Chip quality scaling
Skill Chip sets support Superior and High-end chip instances. Each set owns one
2-piece bonus, distinct primary and secondary stat-option pools, and one 3-piece
Talent with a typed conditional rule. Primary and secondary options reference
active Attributes that define Skill Chip minimum and maximum roll values. A
configured chip rolls one primary and two distinct secondary stats from those
pools.
Each Skill Chip definition belongs to one specialization ability. Each set owns
one 2-piece bonus and may own one 3-piece Talent with a typed conditional rule.
ISAC keeps the complete Talent workspace, including its description and mechanic
program, inside one collapsible optional section.
Each active Skill Chip definition belongs to one active specialization ability
through `skill_chip_sets.specialization_ability_id`. An ability has capacity for
three active definitions. The save and restore actions enforce that capacity,
and the schema requires the foreign key for each row. A specialization focus is
All definitions use one fixed primary profile. The profile contains Skill
Duration, Skill Radius, Skill Cooldown Recovery, and Skill Intensity, with
direct minimum and maximum values for Standard, Specialized, Superior, and
High-end. Primary values apply to the assigned ability rather than the Agent.
Builder and shared Build pages label them `NOT YET DEFINED` and exclude them
from current Agent and combat totals.
All definitions also use one shared secondary Attribute pool. Each pool entry
stores direct minimum and maximum values for Specialized, Superior, and
High-end. Standard chips have no secondary slot, Specialized chips have one, and
Superior and High-end chips have two. A configured chip selects distinct
secondary Attributes up to its quality's capacity. Skill Chips have no item
level, so neither profile uses level interpolation.
Active definitions reference an active specialization ability through
`skill_chip_sets.specialization_ability_id`. An ability has capacity for three
active definitions. The save and restore actions enforce that capacity, and the
schema requires the foreign key for each row. A specialization focus is
builder-ready only when each of its three assigned abilities has all three
active Skill Chip definitions. Skill Chip mutations refresh readiness for
focuses that reference both the previous and resulting ability.
Both set-bonus progression systems use the number of equipped High-end chips as
the interpolation step. For `h` High-end chips, where `h` is zero through three,
a configured minimum and maximum resolve as
`minimum + (maximum − minimum) × h / 3`. Zero High-end chips therefore produce
the minimum, while three produce the maximum. The editor stores endpoints and
previews all four states, preventing duplicated tier data from diverging. The
`game_data` audit stream captures Skill Chip mutations, owned relationships, and
safe icon metadata.
Every equipped quality counts toward the two-piece threshold. After the loadout
meets that threshold, only equipped High-end chips increase the interpolation
step. For `h` High-end chips, where `h` is zero through three, a configured
minimum and maximum resolve as `minimum + (maximum − minimum) × h / 3`. Zero
High-end chips resolve to the minimum, while three resolve to the maximum. The
editor stores endpoints and previews all four states.
ISAC presents the fixed primary profile and secondary pool as two shared
registry/editor cards above the definition registry. Successful profile saves
append `game_data/skill_chip_primary_profile.updated` and
`game_data/skill_chip_secondary_pool.updated`, respectively. Definition
mutations continue to capture their owned bonus, optional Talent, ability
relationship, and safe icon metadata in the `game_data` audit stream.
# Mechanic programs and loadout state
@@ -577,7 +619,23 @@ state, source, movement, and nearby counts travel as typed event values. The
event registry publishes authoritative field metadata where branches need a
bounded contract. For those events, the mechanic editor derives its event-field
controls from that metadata. For example, `weapon_hit.values.headshot` is a
boolean that distinguishes headshots from body shots.
boolean that distinguishes headshots from body shots. `enemy_killed` and
`assist` may carry `values.assignedAbilityActive`; a Skill Chip Talent uses that
boolean to restrict a kill or assist trigger to its assigned ability's active
period. `skill_deployed` and `signature_ability_deployed` may carry
`values.assignedAbilityDurationSeconds` to start assigned-ability state. The
runtime expires that state before it evaluates another event at the same
timestamp.
`weapon_hit.values.aiming` records whether the Agent was aiming down sights when
the hit resolved. A producer omits the field when it lacks authoritative aiming
state; the runtime does not replace missing evidence with a scenario assumption.
Predicates compare this field explicitly with `true` or `false`; negation and
inequality cannot turn missing evidence into a match. A weapon-hit event may
also include an event-target-centered area sample. The bounded sample lists up
to 256 valid ally and enemy entity IDs with their distances from the hit target
and includes that target as an enemy at zero meters. Duplicate IDs, negative
distances, or a missing center target invalidate the evaluation.
`extra_health_changed` is Agent-scoped. Normalized timeline producers emit it
when the Agent receives an Extra Health grant, when the remaining amount
@@ -612,7 +670,10 @@ The program graph uses three child tables:
durations, intervals, or derived values. Mutations can set, add, consume,
clear, derive, or transfer state. A mutation may bind a target-scoped pool to
the current event target, event actor, or another typed entity selector. Each
target owns an independent value and expiry timer.
target owns an independent value and expiry timer. A clause may require active
assigned-ability state and carry `procChancePercent`. The runtime evaluates
that chance after predicates and cooldown checks, before reducers, mutations,
and outcomes.
- `conditional_effect_outcomes` applies Attribute modifiers, direct damage,
restoration, resource costs, or markers. Each outcome names its target scope,
value basis, optional resource or Attribute, combat timing, optional state
@@ -621,15 +682,37 @@ The program graph uses three child tables:
required by the owning source. The common value models are static values, live
Attribute values, percentage-normalized Attribute values, event-field values,
reducer output, source-defined scenario values, and OS Protocol upgrade
scaling. Restoration outcomes may deliver their total immediately or
scaling. An outcome may carry `probabilityPercent`; each eligible outcome
rolls separately. Restoration outcomes may deliver their total immediately or
continuously over an explicit duration.
Target-scoped direct damage may use `event_target_area` targeting for an
explosion around its event target. This targeting selects valid enemies and
stores a positive radius in meters. It is valid only for `on_event` or
`after_event` outcomes. The legacy `within_radius` shape remains descriptive
targeting metadata and does not select runtime entities.
The generic runtime in `src/lib/calculations/mechanic.ts` processes combat
events in timestamp order. Predicates decide whether an event enters a clause.
Reducers convert event streams into activations or derived values. The runtime
applies state mutations, enforces pool bounds and expiry, emits outcomes in
phase order, and records telemetry for each activation.
When `event_target_area` damage activates, the runtime requires the triggering
event's authoritative area sample. It includes valid enemies whose distance is
less than or equal to the configured radius, sorts them by entity ID, and emits
one equal damage outcome for each entity. The outcome chance resolves once
before fan-out. A missing sample invalidates the evaluation instead of producing
single-target damage or treating the area as empty.
Custom evaluation uses a Mulberry32 stream seeded by `randomSeed`; an omitted
seed resolves from the stable mechanic program ID. The returned evaluation
reports the seed. Maximum mode resolves every nonzero clause or outcome chance
as successful. `extend_duration` changes only an active assigned ability's
remaining duration. `start_cooldown_on_max` writes an expiring Agent cooldown
pool only when an earlier mutation in the same clause transitions a capped stack
pool to its maximum.
Each write to an expiring pool refreshes its timer. When a pool expires,
`on_exit` outcomes evaluate stack thresholds and per-stack expressions against
the final value before reset. The runtime records the bound target on emitted
@@ -793,17 +876,17 @@ applicable, default value, and best-case value. ISAC retains these definitions
for continued mechanic authoring. Current Builder and shared Build pages do not
render or evaluate them. Their calculation panels display `COMING SOON` instead.
Loadout schema version 4 stores one focus, selected tree ranks, nine Skill
Loadout schema version 5 stores one focus, selected tree ranks, nine Skill
Chips, a unified conditional-effect state map, encounter assumptions,
per-ability activation controls, and `calculationMode`. Runtime readers accept
the exact version 4 structure. The schema retains its simulation fields for
compatibility, but the current player UI ignores them. A backed-up prototype
migration removes drafts, saved builds, and calibration snapshots that use
incompatible payloads.
the exact version 5 structure. The schema retains its simulation fields, but the
current player UI ignores them. Version 4 is obsolete prototype data. A
backed-up prototype migration removes version 4 drafts, saved builds, and
calibration snapshots instead of translating them.
## Planned player calculation modes
Loadout v4 defines `maximum` and `custom` modes for the planned simulation UI:
Loadout v5 defines `maximum` and `custom` modes for the planned simulation UI:
- Maximum mode supplies each scenario input's best-case value, selects peak
conditional-effect state, and runs selected abilities on cooldown against
@@ -925,11 +1008,12 @@ does not scale.
# Game-data icon storage
Talents, brand sets, OS Protocols, and Skill Chips reference uploaded artwork
through the polymorphic `game_data_icons` metadata table. The shared server
pipeline accepts transparent SVG, PNG, WebP, and AVIF sources, rejects active
SVG content and external references, and uses Sharp’s native worker pool to
rasterize and normalize each accepted icon to a transparent 256 × 256 WebP.
Talents, brand sets, OS Protocols, Skill Chips, Specializations, and shared
Weapon Mod slots reference uploaded artwork through the polymorphic
`game_data_icons` metadata table. The shared server pipeline accepts transparent
SVG, PNG, WebP, and AVIF sources, rejects active SVG content and external
references, and uses Sharp’s native worker pool to rasterize and normalize each
accepted icon to a transparent 256 × 256 WebP.
Normalized files live beneath the ignored `data/game-icons/` directory. The
validated `/icons/game-data/[type]/[id]` endpoint serves them with immutable