Update mechanic authoring persistence

This commit is contained in:
jb
2026-08-20 23:07:14 -04:00
parent 29d26bd036
commit 8c021c134f
15 changed files with 838 additions and 75 deletions
+34 -11
View File
@@ -2390,9 +2390,11 @@ display `ADVANCED`, and stay visible in the generated script. State rows expose
label, agent or target scope, initial value, bounds, best-case value, and
optional expiry. A state change that writes a target pool uses a `STATE OWNER`
segmented control with `EVENT TARGET` and `EVENT ACTOR`; the selected owner
remains visible in the generated script. Outcome rows expose kind, target scope,
Attribute or resource when applicable, value basis, state scaling, phase, and
every source-specific value column. The Value Model control supports static
remains visible in the generated script. The `DERIVED VALUE` operation writes
the branch reducer's numeric result into the selected pool and displays that
link as a text readout instead of a numeric input. Outcome rows expose kind,
target scope, Attribute or resource when applicable, value basis, state scaling,
phase, and every source-specific value column. The Value Model control supports
values, live Attribute totals, percentage-normalized Attribute values, event
fields, reducer output, source-defined scenario controls, and OS Protocol
upgrade scaling where the source permits it. Selecting either Attribute model
@@ -2404,6 +2406,15 @@ 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.
Selecting `DERIVE A SCALAR VALUE` exposes a `DERIVED VALUE SOURCE`
`SegmentedChoice`. `STATIC` shows the numeric value input. `EVENT FIELD` shows
the numeric fields registered for the branch event, including the proximity
snapshot's allied-Agent count; it never asks the author to type a field path.
Keep an existing expression that falls outside these manual patterns visible as
disabled `ADVANCED` data. The source and field controls retain `SegmentedChoice`
radio semantics, visible legends, arrow-key operation, focus-visible treatment,
and text labels.
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
@@ -2421,13 +2432,15 @@ 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 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
Builder Controls define source-specific scenario assumptions for 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 calculation timeline builder can consume values supplied for
these controls, including `allies-within-30m-with-agent-granted-buff`. Current
Builder and shared Build pages do not render the controls or let players change
those values. They use 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,
@@ -2478,7 +2491,10 @@ The panel presents five explicit states:
polite live region, and disables repeat actions.
- `CLARIFICATION REQUIRED` lists each focused question with its reason and
bounded answer control. The author may answer, revise the source text, or
return to manual authoring.
return to manual authoring. For an unresolved numbered numeric placeholder,
show a required clarification for every source value column whose number is
missing. Do not prefill, infer, or suggest a percentage. Keep
`APPLY TO EDITOR` unavailable until the author answers each required variant.
- `CAPABILITY GAP` names the unsupported behavior and displays the developer
handoff, supported approximation, and optional workaround in separate labeled
blocks. Do not present a capability gap as validation failure.
@@ -2502,6 +2518,13 @@ applying the draft would replace configured branches, pools, controls, or
outcomes. The standard ISAC save lifecycle begins only after the author reviews
and saves the resulting form.
An applied AI draft stores each clarified number in the corresponding
human-facing outcome-variant value. A scaling expression may retain the
draft-only `variant_value` reference so later saves preserve the link to that
displayed value. The runtime adapter resolves the reference separately for each
variant. Show the value and generated formula in the ordinary review controls;
do not require an author to inspect or edit raw JSON.
Use text labels with status colors. Orange marks Generate, Answer, and Apply
actions. Blue identifies modeled information, yellow marks assumptions or
unsupported coverage, and red marks request or validation failures. Never use
+18
View File
@@ -79,6 +79,24 @@ meters:
duration.
- The wearer does not count as an ally.
## Close and Personal
Close and Personal uses a proximity-snapshot qualifying set:
- Include each distinct allied Agent whose distance from the source Agent is
less than or equal to 30 meters and who has at least one buff granted by that
source Agent.
- Count an ally once when several of the source Agent's buffs qualify.
- Do not include an ally whose qualifying buffs come only from other sources.
Record the resolved non-negative integer count in
`proximity_snapshot.values.alliesWithin30MetersWithAgentGrantedBuff`. The
calculation builder supplies it from the
`allies-within-30m-with-agent-granted-buff` scenario input. The confirmed rule
defines this qualifying set but does not provide Close and Personal's base
percentage. Keep that percentage unresolved until source evidence or an author's
clarification supplies it.
## Emergency Retreat
Emergency Retreat activates whenever at least one enemy is within 20 meters and
+43 -13
View File
@@ -638,12 +638,24 @@ normalized events are `shot_fired`, `weapon_hit`, `skill_deployed`,
`weapon_swapped`, and `tick`. Event details such as target, distance, critical
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. `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
bounded contract. For those events, the mechanic editor derives event-field
conditions and manual derived-scalar controls from that metadata.
`proximity_snapshot.values.alliesWithin30MetersWithAgentGrantedBuff` is an
optional non-negative integer. It contains the resolved count of distinct allied
Agents at a distance less than or equal to 30 meters who have at least one buff
granted by the source Agent. Several qualifying buffs on one ally count once.
`proximity_snapshot` remains non-strict, so saved mechanic data and producers
that omit the field remain compatible.
`src/lib/builder/loadout-combat.ts` bridges the calculation scenario input
`allies-within-30m-with-agent-granted-buff` into that field on each generated
`proximity_snapshot`. For example, a derived-scalar reducer can select the
registered numeric field without requiring a hand-entered path. Other registered
metadata includes `weapon_hit.values.headshot`, a 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.
@@ -707,11 +719,20 @@ The program graph uses three child tables:
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.
Draft outcome expressions may use `{"ref":{"source":"variant_value"}}`. This
reference belongs to the conditional draft grammar and does not enter the
runtime expression grammar. Each persisted outcome-variant row keeps its
human-facing numeric `value`, while `value_expression_json` preserves the
reference and its semantic link. The adapters in
`src/lib/calculations/mechanic-editor.ts` and
`src/lib/calculations/mechanic-persistence.ts` resolve the reference from the
current row's `value` when they construct a runtime program.
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.
@@ -800,6 +821,13 @@ descriptions, and calculation metadata. The client cannot replace the system
instructions, choose arbitrary models, attach files, add tools, or add external
URLs.
When source wording contains an unresolved numbered numeric placeholder, the
assistant must return `clarification_required` and ask for the value of every
required source variant. It must not infer a percentage or other numeric value.
After clarification, the draft places each answer in the corresponding
outcome-variant `value`; any scaling expression uses the draft-only
`variant_value` reference instead of repeating that number.
The deterministic draft parser owns the canonical outcome-capability manifest.
The AI context serializes that manifest instead of maintaining a second outcome
grammar. The parser rejects outcome fields absent from the manifest. Contract
@@ -896,8 +924,10 @@ events remain the evidence for revision saves and activation.
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.
for continued mechanic authoring, and the calculation timeline builder can
consume scenario values supplied by calculation orchestration. Current Builder
and shared Build pages do not expose those controls or invoke the simulation.
Their calculation panels display `COMING SOON` instead.
Loadout schema version 6 stores one focus, selected tree ranks, nine Skill
Chips, independent T1/T2 choices for each equipped gear and weapon Talent, a