feat: defer advanced build calculations
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 27s
Validate and deploy staging / deploy (push) Successful in 54s

This commit is contained in:
jb
2026-08-02 03:07:12 -04:00
parent c61b9832dd
commit d09b6220ee
19 changed files with 1485 additions and 1267 deletions
+74 -58
View File
@@ -353,13 +353,13 @@ equipment opens the searchable real-data catalog and its compatible
configuration controls. Do not display a prototype option that the current
loadout schema cannot save.
Calculation readiness belongs at the point of resolution. Mark an incomplete
Equipment readiness belongs at the point of resolution. Mark an incomplete
matrix cell with a compact red text indicator and status rail, then let the cell
open the editor that resolves it. The live calculation rail summarizes blocked
output in one compact row. Do not repeat every missing slot in a large error
panel. Keep system-owned blockers, such as an unpublished calculation profile,
visible in that compact summary because the player cannot resolve them from a
loadout cell.
open the editor that resolves it. The live totals rail summarizes deterministic
equipped-item totals. Separate panels label conditional Talent outcomes, weapon
and Skill DPS, encounter assumptions, activation profiles, rotations, and
simulation as `COMING SOON`; they do not report calculation-profile blockers as
current player errors.
The builder uses three workbench columns on wide screens, moves the live summary
below the matrix and editor at intermediate widths, and stacks all three regions
@@ -1707,10 +1707,10 @@ cards and augment editor cards reduce to a single column while retaining
The builder is a three-rail tactical workbench: compact equipment positions on
the left, the currently selected item editor in the center, and a sticky live
calculation summary on the right. At medium widths the summary becomes a
full-width lower rail; on mobile all three rails stack, with equipment first,
editing second, and results third. Equipment positions remain explicit even when
empty so loadout completeness is always visible.
totals summary on the right. At medium widths the summary becomes a full-width
lower rail; on mobile all three rails stack, with equipment first, editing
second, and results third. Equipment positions remain explicit even when empty
so players can see loadout completeness.
Use the shared `BuilderPicker` for builder catalogs and Attribute pools. It
combines an always-visible current selection with a searchable overlay, icon or
@@ -1721,11 +1721,11 @@ such as the single-exotic-weapon rule are explained rather than hidden.
Numeric instance values display their authoritative minimum and maximum beside
the field and clamp to that range on completion. Always-on item rolls, fixed
bonuses, inherited profiles, enabled augments, and activated set bonuses feed
the live totals immediately. Conditional mechanics state their calculation mode
and readiness. Maximum Potential uses their best-case state; Custom Scenario
uses the source-defined advanced assumptions saved with the loadout. Exclude a
mechanic that lacks a required assumption and label it `REQUIRES ASSUMPTIONS`.
This distinction must remain clear without relying on color.
the live totals immediately. Current Builder and shared Build pages stop at
these deterministic equipped-item totals. Conditional Talent outcomes, weapon
and Skill DPS, encounter assumptions, activation profiles, rotations, and
simulation remain planned. Render those capabilities as separate `COMING SOON`
panels, with visible text rather than color alone.
Loadout summaries name selected Talents, Attributes and their exact values,
nodes, and Skill Chips. Do not replace these selections with configured item
@@ -2309,14 +2309,14 @@ source program, where authors may edit its exposed branch, state, and outcome
controls. The recipe label records provenance only. `REPLACE PROGRAM` requires
an inline confirmation that states all existing branches will be discarded.
Builder Controls define source-specific advanced scenario assumptions. Authors
choose toggle, slider, or numeric input and provide a label, Agent guidance,
default value, best-case value, and numeric bounds when applicable. Group these
controls behind the builder's advanced scenario surface. Maximum Potential uses
best-case values. Custom Scenario uses saved Agent values. A required cadence or
environmental value with no supplied assumption keeps the mechanic out of the
calculation and displays `REQUIRES ASSUMPTIONS`; the editor and runtime never
invent a cadence.
Builder Controls define source-specific scenario assumptions for the planned
player simulation. ISAC authors choose toggle, slider, or numeric input and
provide a label, Agent guidance, default value, best-case value, and numeric
bounds when applicable. The current player UI does not render these controls or
read their saved values. It uses an explicit `COMING SOON` panel for the future
advanced scenario surface. The authored contract still requires the runtime to
report `REQUIRES ASSUMPTIONS` when a required cadence or environmental value is
missing; the editor and runtime never invent a cadence.
Use `--shd-model-surface` and `--shd-model-border` for mechanic programs,
calculation revisions, and field calibration. The blue information rail marks
@@ -2482,9 +2482,16 @@ anchor scrolling and sticky-state transitions.
#### Builder calculation modes
The loadout builder places one required two-option `SegmentedChoice` above
combat assumptions. The persisted `maximum` and `custom` values use these
visible labels:
The current Builder and shared Build pages do not expose calculation modes or
combat assumptions. They show deterministic equipped-item totals and reserve
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:
- `MAXIMUM POTENTIAL` calculates a configured ceiling. It applies conditional
effects at peak state and treats selected abilities as firing on cooldown
@@ -2492,40 +2499,42 @@ visible labels:
- `CUSTOM SCENARIO` exposes encounter assumptions and source-defined advanced
controls for a player-defined scenario.
New loadouts select `MAXIMUM POTENTIAL`. The interface labels Maximum results as
a modeled ceiling so players do not read them as typical encounter performance.
Maximum hides granular assumption fields without deleting their saved values.
Returning to Custom restores those values.
The planned interface selects `MAXIMUM POTENTIAL` for new loadouts and labels
its results as a modeled ceiling. Maximum will hide granular assumption fields
without deleting their saved values. Returning to Custom will restore those
values.
Custom mode gives each unlocked conditional effect three state controls:
The planned Custom mode gives each unlocked conditional effect three state
controls:
- `OFF` excludes the effect.
- `PEAK` applies its configured maximum stacks.
- `ENCOUNTER` models stack buildup and expiry from weapon RPM, magazine size,
reload time, hit rate, firing activity, and encounter duration.
Users may override encounter assumptions on one effect without changing the
global Custom profile. Open the advanced scenario surface to show only the
toggle, slider, and numeric controls defined by that effect's owning source. The
effect card shows uptime, activation count, and applied stack state beside the
mode. A mechanic that needs an undefined cadence or another missing scenario
input displays `REQUIRES ASSUMPTIONS`; the builder withholds its calculated
contribution until the author or player supplies that input.
The planned advanced scenario surface will let users override one effect without
changing the global Custom profile. It will show only the toggle, slider, and
numeric controls defined by that effect's owning source. The effect card will
show uptime, activation count, and applied stack state beside the mode. A
mechanic that needs an undefined cadence or another missing scenario input will
display `REQUIRES ASSUMPTIONS`; the simulation will withhold its contribution
until the author or player supplies that input.
Maximum and Custom use radio semantics, an explicit selected label, keyboard
arrow navigation, and the standard orange selected rail. Results repeat the
active calculation mode in text. On mobile, the global mode control and Custom
assumption fields stack into full-width targets of at least 44 pixels. Mode
changes use the standard pressed feedback; reduced-motion preferences remove
transitions without hiding the state change.
The future Maximum and Custom control will use radio semantics, an explicit
selected label, keyboard arrow navigation, and the standard orange selected
rail. Results will repeat the active calculation mode in text. On mobile, the
global mode control and Custom assumption fields will stack into full-width
targets of at least 44 pixels. Mode changes will use the standard pressed
feedback; reduced-motion preferences will remove transitions without hiding the
state change.
Combat result panels show normal, critical, headshot, and critical-headshot
values with burst, sustained, and encounter DPS. Conditional stack telemetry
lists the mode, uptime, activations, average and peak stacks, ending stacks,
buildup time, and maintained state. A result with missing equipment, Attribute
bindings, rules, or assumptions displays `INSUFFICIENT DATA` and a concrete
remediation list. The interface withholds combat numbers until it has the
required inputs.
The future combat result panels will show normal, critical, headshot, and
critical-headshot values with burst, sustained, and encounter DPS. Conditional
stack telemetry will list the mode, uptime, activations, average and peak
stacks, ending stacks, buildup time, and maintained state. A result with missing
equipment, Attribute bindings, rules, or assumptions will display
`INSUFFICIENT DATA` and a concrete remediation list. Until this interface ships,
the player pages show `COMING SOON` instead of combat numbers.
### Specialization loadout composer
@@ -2541,16 +2550,19 @@ ranks remain visible with their lock state. The builder permits a row after the
user buys every available Rank 1 and Rank 2 in preceding rows and enforces the
49-point limit. Cost telemetry lists Credits and components beside each rank.
Each ability panel exposes one compact activation control: Off, On Cooldown, or
Custom Rate. Custom Rate adds uses per minute. Every enabled ability has its own
target count. Skill result cards show the ability name, activation count,
single-target DPS, total-target DPS, and a combined summary. They state that
Skills can critically hit and multi-shot but cannot headshot.
Player ability panels currently expose equipped definitions and deterministic
item contributions. Planned simulation panels display `COMING SOON` instead of
activation controls or Skill DPS. The future interface will offer Off, On
Cooldown, or Custom Rate, with uses per minute and a target count for each
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,
encounter assumptions, and per-ability activation profiles. The builder accepts
only the current complete structure. Invalid local drafts are discarded; invalid
server records are removed through a backed-up database migration.
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.
### Calculation revision controls
@@ -2581,6 +2593,10 @@ revision identity and before the manual stage and profile controls. Reuse the
language, identifies the active or edited base revision, and previews changes to
stages, weapon profiles, and Skill profiles.
ISAC keeps revision editing, calibration, assisted suggestions, publication, and
the calculation AI assistant available for continued model authoring. The
current Builder and shared Build pages do not consume their output.
Agents without `ai.calculation.generate` see the collapsed `PERMISSION REQUIRED`
state. Agents with the permission may request and apply a draft, but the panel
leaves every manual calculation control available. Applying a draft fills the
+53 -34
View File
@@ -25,6 +25,13 @@ The team builds the project in vertical slices.
Server code checks authorization for each mutation. UI visibility has no effect
on server authorization.
Builder and shared Build pages currently expose only deterministic totals from
the equipped items, selected rolls, fixed bonuses, inherited profiles, augments,
and active set bonuses. Conditional Talent outcomes, weapon and Skill DPS,
encounter assumptions, activation profiles, rotations, and simulation remain
planned. Explicit `COMING SOON` panels identify those player-facing
capabilities.
Weapon and gear range calculations must preserve decimal endpoints and follow
the tested progression rules in
[`STAT_LEVEL_SCALING.md`](STAT_LEVEL_SCALING.md). Leveling is linear rather than
@@ -174,9 +181,11 @@ stores only its domain-separated hash. Repeated anonymous activity requires a
Turnstile result. Guide reports reference the exact published revision so a
report against an older revision cannot hide newer work.
The Builder stores loadout data only. It has no summary or Guide body. An owned
Build page links to `/guides/new?build=<id>`, where the server verifies
ownership and initializes a removable Build block in a new private Guide.
The Builder stores loadout data and displays deterministic equipped-item totals.
It has no Guide body. Shared Build pages use the same player-facing calculation
boundary. An owned Build page links to `/guides/new?build=<id>`, where the
server verifies ownership and initializes a removable Build block in a new
private Guide.
## Public data corrections and discussion
@@ -490,10 +499,11 @@ Talent, OS Protocol Talent, Skill Chip Talent, or Specialization tree rank. The
`source_type` and `source_id` pair identifies that owner. No standalone Trigger
record or shared Trigger relationship participates in execution.
The builder supplies normalized timeline events to each equipped mechanic.
`movement_snapshot.values.state` is `immobile`, `moving`, or `sprinting`; the
mechanic's moving and sprinting scenario controls select that state, with
sprinting taking precedence. Enabled Skill activation profiles emit
The mechanic runtime accepts normalized timeline events for each equipped
mechanic. Current player pages do not construct this timeline or invoke the
runtime. `movement_snapshot.values.state` is `immobile`, `moving`, or
`sprinting`; the mechanic's moving and sprinting scenario controls select that
state, with sprinting taking precedence. Enabled Skill activation profiles emit
`skill_deployed` events on the same cadence as Skill calculations and identify
the deployed ability. An `on_event` Skill modifier applies to that activation
until the ability's next deployment or the encounter ends.
@@ -502,7 +512,7 @@ Each source supplies a fixed value-variant contract:
- Standard Talents require Tier I and Tier II values. Exotic Talents require
Tier I and may omit Tier II until contributors document its game values.
Builder calculations use Tier I while an equipped exotic Talent has no Tier II
Runtime calculations use Tier I while an equipped exotic Talent has no Tier II
mechanic variant.
- OS Protocol Talents store a base value. An outcome may use an expression that
reads `equipment.protocolTalentUpgrades`, from zero through five, so selected
@@ -622,10 +632,11 @@ uses `requires_assumptions`, identifies the missing input, and stays out of the
calculation until an operator or builder scenario supplies it.
The runtime derives a read-only pseudo-language listing from the typed program.
ISAC and the builder use that listing to explain events, predicates, reducers,
state changes, phases, and formulas. No route accepts the generated text as
input, and no server process executes it. Operators edit structured fields; the
formatter regenerates the listing after each change.
ISAC uses that listing to explain events, predicates, reducers, state changes,
phases, and formulas. Planned player calculations can reuse it when those pages
consume mechanic outcomes. No route accepts the generated text as input, and no
server process executes it. Operators edit structured fields; the formatter
regenerates the listing after each change.
## AI-assisted mechanic drafting
@@ -732,7 +743,8 @@ clarification requests. It does not grant revision mutation or publication.
Applying a result changes the open revision form in the client. The operator
must review and save that draft through the existing revision action. The
separate `calculation.publish` permission and activation confirmation remain
mandatory before the saved draft affects loadout results.
mandatory before the saved draft becomes the active authored model. Current
player pages do not consume that model.
Successful calculation-generation requests append sanitized events under
`ai_assistance`. These events use calculation-specific actions, identify the
@@ -741,23 +753,23 @@ token-usage, result, and secret-exclusion rules as mechanic-assistance events.
Applying a draft creates no server event. Existing `calculation_configuration`
events remain the evidence for revision saves and activation.
Source authors define the builder controls required by their mechanic as typed
toggle, slider, or numeric scenario inputs. Each input records its label,
guidance, bounds when applicable, default value, and best-case value. These
controls appear only in advanced scenario configuration. Maximum mode supplies
best-case values. Custom mode uses the values saved with the loadout. A mechanic
with an undefined required assumption remains excluded and reports
`REQUIRES_ASSUMPTIONS`.
Source authors define planned player scenario controls as typed toggle, slider,
or numeric inputs. Each input records its label, guidance, bounds when
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
Chips, a unified conditional-effect state map, encounter assumptions,
per-ability activation controls, and `calculationMode`. Runtime readers accept
the exact version 4 structure. A backed-up prototype migration removes drafts,
saved builds, and calibration snapshots that use incompatible payloads.
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.
## Calculation modes
## Planned player calculation modes
The builder offers `maximum` and `custom` modes.
Loadout v4 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
@@ -767,9 +779,10 @@ The builder offers `maximum` and `custom` modes.
rates, target counts, and other supported assumptions. A missing required
input produces `REQUIRES_ASSUMPTIONS` rather than a fabricated value.
Saved and shared loadouts preserve the selected mode. Calculation results label
the mode so readers can distinguish a best-case ceiling from a scenario-based
estimate.
Saved and shared loadouts preserve the selected mode as compatibility data. The
current Builder and shared Build UI does not expose a mode selector, read
encounter assumptions, or execute either mode. Explicit `COMING SOON` panels
reserve the player-facing space for these calculations.
## Specialization ability attacks
@@ -795,6 +808,12 @@ holds the first position, and the firing-cycle stage holds the last.
`attribute_calculation_profiles` maps an Attribute to a weapon stage with its
weight, optional caps, curve, and weapon-category scope.
ISAC keeps combat revision editing, publication, calibration, assisted
suggestions, and the calculation AI assistant available so operators can
continue authoring the model. Builder and shared Build pages do not load the
active revision or consume revision, calibration, assistant, mechanic-runtime,
or combat-engine output at the current player-facing boundary.
The shared combat engine consumes weapon facts, accumulated Attributes,
calculation profiles, and mechanic outcomes. It produces four hit values, burst
DPS, reload-aware sustained DPS, encounter DPS, and stack telemetry. Custom mode
@@ -803,11 +822,11 @@ configured burst size, pauses between bursts, and encounter duration. It
resolves the active Attribute state at each landed shot before calculating that
shot's expected damage.
The builder scales a weapon definition's level-1 damage range to the equipped
item level, then the agent selects one damage value inside that valid range.
Combat receives `equipped_weapon.damage` as its base damage and consumes that
number once. The combat pipeline has no `level_scaled_damage` value and must not
apply item-level scaling a second time.
The deterministic equipment path scales a weapon definition's level-1 damage
range to the equipped item level, then the agent selects one damage value inside
that valid range. A combat invocation receives `equipped_weapon.damage` as its
base damage and consumes that number once. The combat pipeline has no
`level_scaled_damage` value and must not apply item-level scaling a second time.
The generated calculation listing names each typed pipeline stage and its bound
Attributes. The listing explains the active revision with statements such as
@@ -829,8 +848,8 @@ the builder supports a combined weapon-rotation model.
The engine returns `INSUFFICIENT_DATA` with missing requirement keys when a
calculation lacks required inputs or an Attribute binding. Callers must render
that state instead of a partial result. Saved and shared builds load the current
active revision for each request.
that state instead of a partial result. Current player routes do not call the
engine; their planned calculation surfaces display `COMING SOON`.
`calculation_calibration_cases` stores a versioned loadout snapshot, observed
hit values, timing values, optional encounter DPS, and the model prediction.