# Aetherbound Guild - Gameplay, Battle, Economy And Save Complete gameplay rules, deterministic battle, progression, economy, pacing, failure, persistence and recovery. ## Owner Review / Owner 审核 重点确认招募、自动排阵、战斗、击倒与下关恢复、装备、持续成长、经济、难度、失败与存档规则。这里回答“每一步怎么玩、怎么算、输赢后发生什么”。 本文件是当前六份审核文档之一。历史拆分文件仅保留在 Git 历史中;文内规则、表格和 ID 仍是完整开发依据。 ## P0 Consolidation Role This document is the systems authority inside the consolidated project contract. It defines what each recurring decision changes, which state owns the result, how Coin/XP/Equipment/Company/Contract values persist, and how failure, recovery and Save receipts behave. It does not define page layout or art treatment; those belong to `03_PAGES_AND_UX.md` and `04_ART_ANIMATION_AUDIO.md`. ## 2026-08-17 Continuous-Growth Owner Override This override is the current authority everywhere this file conflicts with the older FG-4 implementation model below: - one Guild save owns one persistent Expedition Company across Contract runs; - New Game creates exactly four stable provisional offers and commits exactly two of them once as the initial persistent roster; - a zero-HP Recruit is knocked out for the current battle, remains owned and is battle-ready again for the next stage with the same identity and growth; - Contract clear or withdrawal closes only Contract-local progress, formation, encounter and temporary-effect state, then returns to the Guild; and - death-funded Replacement Credit, Company-collapse roster deletion, Recruit archiving and loss of levels/XP/equipment at Contract close are superseded. The exact next-stage HP amount is intentionally frozen for the later balance conversion. DEV-2 guarantees persistent ownership and next-stage availability; it must not invent a full-heal rule or permanent casualty. The older sections that still name `Fallen`, `Replacement Credit`, `run_creation_draft`, short-lived `current_run` Recruits, Company collapse or roster archiving are `FROZEN_LEGACY_FG4` evidence. Their deterministic battle, economy and Save-v11 details remain preserved until the named later player-order conversion, but those conflicting lifecycle effects are not current product authority. Battle-local `Fallen` event/code identifiers may temporarily remain as implementation names only; product-facing meaning is `Knocked Out` and never permanent roster removal. For DEV-2, the current persistence boundary is: ```text Guild_slot initial_company_draft or null expedition_company or null initial_company_draft draft_id, seed, status, source_revision offers[0..3], offer_set_hash selected_offer_ids[0..2], selection_revision expedition_company company_id, created_from_draft_id owned_recruits[2..], reserve_recruit_ids[] persistent inventory, Coin, levels, XP, Professions, Traits and history active_contract or null ``` An uncommitted draft and a committed initial Company are mutually exclusive. The same saved seed always produces the same four IDs in the same positions. Selection may contain zero, one or two distinct offer IDs; only exactly two can enter review. Commit atomically removes the draft, writes one Company containing only the selected two Recruit records and stores an idempotent receipt. A retry returns that receipt and never creates a second Company or rerolls the offers. ## Aetherbound Guild: Systems And Battle Authority > Authority: generated-Recruit state, Profession grammar, Market/run handoffs, > ordered Party-line geometry, deterministic auto-battle, equipment and Artifact > hooks, targeting, movement, knockout, recovery, and causal diagnosis. > > Revision: recruit-line-design-r2 / 2026-08-10 > > Product intent is defined in > [01_GAME_DESIGN.md](01_GAME_DESIGN.md). Prices, rewards, > progression rates, capacity selection, and pacing are defined in > [02_GAMEPLAY_AND_BALANCE.md](02_GAMEPLAY_AND_BALANCE.md). Durable commit and recovery > semantics are defined in > [02_GAMEPLAY_AND_BALANCE.md](02_GAMEPLAY_AND_BALANCE.md). ### 1. System Invariants 1. Each side occupies one ordered horizontal line. Position zero is front; a larger position is farther rearward. There is no second spatial axis. 2. Allied simultaneous footprint begins at four and reaches ten. Reserve and cumulative hires are separate and never redefine this limit. 3. Battle is automatic. The player may start, pause, change speed, inspect, or retreat, but cannot activate attacks/skills, reorder, equip, or promote while resolving. 4. A Recruit has one generated identity, one current fixed Profession, five rolled attributes from an equal level budget, exactly one Trait, equipment, level, and survival history. 5. Zero HP means Knocked Out. The Recruit leaves the resolving line immediately, never respawns in that battle, and is never replaced by Reserve during that battle. The Recruit remains in the persistent Expedition Company and is battle-ready again for the next stage with equipment and growth unchanged. 6. The same start state, ruleset, content revision, seed, and retreat timestamp produces the same state hashes and result. 7. Display frame rate and pause/1x/2x/4x do not change simulation time or draws. 8. Every targeting exception, failed action, movement conflict, retarget, immunity, proc suppression, and outcome has one inspectable reason. 9. All damage has a declared type, power source, defense, rounding boundary, critical rule, modifier groups, and floor/nullification behavior. 10. No standard battle exceeds 150 simulation seconds. ### 2. Authoritative State Model ```text profile settings, accessibility, language, input mappings Renown, unlock breadth, Region/Contract progress, Records, collection facts persistent Expedition Company, inventory, Coin and Recruit growth Contract expedition contract_run_id, contract_id, difficulty_id, ruleset_version, content_revision generation_seed, Market index, cleared Rounds, Line capacity route, refresh/lock counters, deployed formation, temporary Artifacts knockout events, boss state, Contract result Recruit recruit_id, generated_name_parts, rendered_name_snapshot, appearance_seed origin_profession_id, current_profession_id, promotion_state level, xp, five base attributes, Trait id equipped_item_id or null, effective stats, battles entered, victories, hire receipt encounter encounter_id, battle_offer_id, root_seed, phase, tick ordered allied/enemy actor sequences and footprints HP, resources, readiness, cooldowns, casts, statuses, barriers event queue, draw counters, retreat state, objective, outcome, event journal presentation only camera, interpolation, animation frame, particles, selected inspector, expanded tooltip, pointer, audio playback cursor ``` Presentation never authors state. Battle arithmetic uses signed 64-bit integer fixed point with 100 units per displayed point. Percentages use basis points (`10,000 = 100%`). A formula rounds only where this document says `floor`, `ceil`, or `round_half_up`. ### 3. Run And Market State Machine ```text Contract_created -> Market_open -> battle_offer_committed -> countdown -> resolving -> outcome_locked -> diagnosis -> reward_or_failure_applied -> next_Market | boss_Muster | Contract_return_to_Guild ``` The Market snapshot contains three Recruit offers, four equipment offers, and three battle offers. Offer generation, prices, locks, and refreshes are owned by the economy authority. This document owns these system rules: - leaving and reopening a Market preserves all offer IDs and generated values; - buying removes exactly that offer and never silently fills the empty slot; - locked unbought offers persist to the next Market as declared; - equipment, order, promotion, and dismissal are legal only while Market is open or during boss Muster; - battle commit stores an immutable deployed lineup, inventory ownership, effective-stat snapshot, enemy lineup, seed, risk, and result rules; - no Market edit after commit can affect that encounter; - result inspection never applies or skips a reward operation. ### 4. Generated Recruit Contract #### 4.1 Generation Recruit generation uses labeled deterministic streams so a name draw cannot change attributes or Trait: ```text recruit_name, recruit_appearance, recruit_profession, recruit_attributes, recruit_trait ``` For offer level `L` from 1 through 10: ```text attribute_budget(L) = 30 + 5*L attribute_floor(L) = 3 + L attribute_cap(L) = 12 + 3*L ``` `Might + Finesse + Insight + Vigor + Resolve` equals the exact budget. Every attribute stays within floor/cap. The generator first assigns the floor to all five, then distributes the remaining points one at a time by the labeled stream without exceeding cap. Because totals are equal at a level, no Recruit is strictly superior only because its random total is larger. Every Recruit row stores its inputs and output hash. Generated name components and modular visual parts create identity and readable variation but no hidden mechanical modifier. #### 4.2 Trait Each Recruit receives exactly one of 36 authored Traits. A Trait row has one visible benefit and one visible cost, both mechanical. It cannot be removed, stacked, upgraded, rerolled, or suppressed by changing language or appearance. A Trait is invalid if its cost never changes a decision in either of its two fixed fixtures, or if its benefit is only a larger unconditional value. Trait tags may participate in hidden-hybrid eligibility only when that condition is shown after discovery. #### 4.3 Survival History The persistent Recruit records battles entered, victories, retreats survived, allies ahead at commit, first knocked-out ally witnessed, promotion, knockout events and final dismissal if any. History may unlock a title or catalog fact but cannot grant a hidden stat. Contract close adds an immutable summary Record without making that Recruit unplayable or replacing its stable ID. ### 5. Profession Catalog And Promotion The fixed catalog contains 12 base, 24 regular advanced, and 6 hidden hybrid Professions. Content owns identities and instances; this document owns schema and topology. #### 5.1 Topology - Every base Profession has exactly two regular advanced descendants. - Every regular advanced Profession has exactly one parent base. - Every hidden hybrid declares exactly two compatible base-family IDs and an original battlefield responsibility distinct from both parents. - A Recruit has exactly one current Profession. Equipment never changes the stored Profession ID. - A Recruit's origin base is immutable even after promotion. #### 5.2 Promotion A base Recruit becomes eligible after reaching level 4 and surviving three completed battles. Promotion is one-way and can happen once. The Market review shows new action rules, lost rules, target/reach changes, resource loop, price or opportunity cost, and the two validation fixtures before confirm. The two regular descendants are always deterministic choices once eligible. A hidden hybrid appears as an additional choice only when its revealed catalog predicate is satisfied. Allowed predicate inputs are origin base, Trait tags, equipped behavior tags, current Artifact tags, adjacent deployed Profession families, and cleared Contract facts. A predicate cannot read generated name, appearance, playtime, wall clock, or social state. Promotion preserves that Recruit's individual level and XP, HP percentage outside battle, Trait, equipped item, survival history, and recruit ID. It replaces current Profession, action table, resource meter, and derived Profession bases atomically. It is not a free job switch or reversible respec. #### 5.3 Automatic Action Unlocks A Profession action kit unlocks by that Recruit's individual level. Levels are bounded to `1..10`; there is no Company level and another Recruit's XP cannot unlock these rules: | Recruit level | Available automatic rules | |---:|---| | 1 | basic action, resource rule, identity passive | | 2 | first technique and its priority row | | 3 | second technique and its priority row | | 4 | signature and its priority row; promotion becomes possible after the survival requirement | Promoting replaces the action kit with the promoted Profession's level-valid kit. A direct regular-advanced hire uses the same level schedule. Falling below an unlock level is impossible, and equipment cannot unlock a later action early. Every unlocked action is automatic; the player prepares through hire, equipment, deployment, and order rather than selecting it during battle. #### 5.4 Profession Row ```text profession_id, tier (base | regular_advanced | hidden_hybrid) parent_base_ids, unlock/promotion predicate battlefield responsibility, preferred depth, failure mode, counter tags base HP, base Tempo, base defenses, resource schema basic action, two techniques, signature, passives automatic priority table and target policies movement/reach/protection/projectile/healing rules two decision-opposed validation fixtures presentation and accessibility event requirements ``` An advanced or hidden Profession must transform target, timing, position, resource flow, protection, or risk ownership. A stronger scalar copy fails. ### 6. Party-Line Geometry #### 6.1 Ordered Footprint Each actor declares footprint 1 or 2. Standard Recruits use footprint 1. An actor with footprint 2 is one unit ID, one HP pool, and one action state occupying a contiguous block. The authoritative line is an ordered actor sequence with no interior empty space after normalization. For actor `A`: ```text depth(A) = sum(footprint(X) for every living actor X ahead of A) front_cell(A) = depth(A) rear_cell(A) = depth(A) + footprint(A) - 1 ``` Allied deployed footprint cannot exceed current Line capacity. Recruits left out of the sequence are Reserve. Order ties and simultaneous insertion use stable actor ID only after all player-visible rules are equal. #### 6.2 Cross-Line Distance And Same-Line Distance For opposing source `S` and target `T`: ```text cross_line_distance(S,T) = 1 + depth(S) + depth(T) ``` For allied actors: ```text same_line_distance(S,T) = max(0, max(front_cell(S), front_cell(T)) - min(rear_cell(S), rear_cell(T)) - 1) ``` Adjacent footprints therefore have same-line distance zero. Every action declares a maximum cross-line or same-line reach. No visual closeness overrides the integer distance. #### 6.3 Protection ```text protection_stacks(T) = min(2, depth(T)) ``` Each occupied footprint ahead contributes one stack up to two. Protection is not a generic defense stat; actions use one declared mode: | Mode | Rule | |---|---| | `frontbound` | Only targets with `depth=0` are candidates | | `screened` | Deeper targets may be candidates, but resolved damage is multiplied by `max(0.70, 1 - 0.15*protection_stacks)` | | `intercepted_projectile` | Projectile collides with the first eligible footprint in its current path | | `lobbed` | Ignores collision but uses screened damage | | `bypass_protection` | Ignores stacks; must be declared in preview and telegraph | Healing and boons do not gain a hidden bonus from protection. The inspect view shows stacks, contributing actors, target legality, and expected multiplier. ### 7. Encounter Lifecycle | Phase | Legal player actions | Commit behavior | |---|---|---| | Preview | Inspect enemy order, actions, risk, reward, timeout, retreat | Offer is stable; no spend | | Prepare | Equip, promote, dismiss, deploy, reorder | Changes remain reversible until battle confirm | | Countdown | Pause, speed, inspect | Three simulation seconds; lineup locked | | Resolve | Pause, speed, inspect, retreat | Automatic action events and retreat timestamp journaled | | Outcome locked | Inspect | Victory, defeat, timeout, or retreat cannot change | | Diagnose | Inspect causal timeline | No reward applied by viewing/skipping | | Settle | Choose fixed reward if eligible | One atomic result operation | | Finalized | Continue to Market/run result | Casualties, equipment return, Coin/Credit, and reward agree | ### 8. Deterministic Time, Events, And Draws #### 8.1 Fixed Tick And Priority One simulation tick is exactly 100 milliseconds. At each tick: 1. accept lifecycle control stamped for this tick, including retreat start; 2. expire statuses and barriers whose end tick equals this tick; 3. resolve periodic status events due this tick; 4. complete casts, channels, projectile arrivals, and summon expiries; 5. select actions for actors already ready and legal; 6. resolve voluntary and forced movement intents; 7. apply simultaneous damage, healing, barrier, and resource deltas by batch; 8. finalize action-outcome records, mark zero-HP actors Fallen, and run declared outcome/death triggers once; 9. compact lines, insert legal summons, and evaluate objective/retreat/phase; 10. advance readiness, cooldown, cast, status, timeout, and retreat clocks. Events in the same numeric batch read one pre-batch state and apply together. An actor alive at batch start completes its already-scheduled event even if the same batch makes it Fallen. A death trigger cannot restore the source above zero HP and cannot recursively produce another death trigger in the same tick. An outcome-triggered derived action is queued no earlier than priority 4 of the next tick; it cannot join or reopen the batch that produced its outcome. #### 8.2 Labeled Determinism The encounter root seed supplies independent labels: ```text target_tie, critical, status_apply, proc_choice, summon_variant, reward ``` For a draw: ```text roll_bp = hash64(root_seed, label, actor_id, action_sequence, target_id, draw_index) mod 10,000 ``` The event journal records label and draw index. Adding an equipment proc cannot shift target, critical, status, or reward results in another stream. There is no random damage variance or hidden miss chance. ### 9. Attributes And Derived Statistics | Attribute | Primary responsibility | |---|---| | Might | physical power and Guard contribution | | Finesse | Tempo, physical precision, and critical pressure | | Insight | arcane power and status Potency | | Vigor | maximum HP, Guard, and movement stability | | Resolve | healing power, Ward, and status Tenacity | At level `L`: ```text PhysicalPower = WeaponPower + 2.00*Might + 0.50*Finesse ArcanePower = FocusPower + 2.00*Insight + 0.50*Resolve HealingPower = FocusPower + 1.20*Insight + 1.20*Resolve MaxHP = ProfessionBaseHP + 8*L + 10*Vigor Guard = ArmorGuard + 1.20*Vigor + 0.60*Might Ward = ArmorWard + 1.20*Resolve + 0.60*Insight Potency = Insight + 0.50*Finesse + FlatPotency Tenacity = Resolve + 0.50*Vigor + FlatTenacity Tempo = clamp(ProfessionBaseTempo + 0.40*Finesse + FlatTempo, 20, 100) Initiative = clamp(ProfessionBaseInitiative + 0.25*Finesse + FlatInitiative, 0, 95) ``` Derived values round down to 1/100 after the full expression. Profession bases must stay within `BaseHP 140-420`, `BaseTempo 24-55`, and `BaseInitiative 0-45` unless a fixed exception fixture is approved. A MaxHP change outside battle preserves current HP percentage and does not heal. ### 10. Readiness And Automatic Action Selection At battle start, `Readiness = Initiative`. Each tick while an actor can act: ```text Readiness = min(150, Readiness + Tempo*0.1) ``` At `Readiness >= 100`, the actor scans its Profession priority rows from top to bottom. The first row with a legal action, true visible condition, and legal target starts. It subtracts 100 Readiness and retains overflow. If none is legal, readiness remains capped and the actor checks again next tick. Priority conditions may read only current HP bands, resource, status, casts, depth, protection, ally/enemy counts, summon space, cooldown, phase, and preview tags. They cannot read future draws. Every Profession has a legal fallback or an explicit `NO_REACHABLE_TARGET` idle result. | Timing field | Boundary | |---|---| | Wind-up | 0.1-1.5 s | | Major telegraph | at least 1.5 s; first boss use at least 2.5 s | | Channel/cast | 0.3-4.0 s | | Recovery | 0-2.0 s | | Cooldown | 0-30 s | The automatic table is part of Profession identity. Players compare it but do not script arbitrary condition programs. ### 11. Target Selection, Reach, And Retarget An action constructs candidates in this order: 1. required side and living/Fallen/summon state; 2. cross-line or same-line reach; 3. protection mode; 4. required status, cast, HP band, or tag; 5. exclusion, immunity, and maximum targets; 6. target policy. Core target policies are `frontmost`, `rearmost`, `lowest_hp_ratio`, `highest_power`, `active_cast`, `marked`, and `self`. Numeric ties use depth in the policy's natural direction, then `target_tie`. The default hostile policy is frontmost. Enemy-specific score tables must be shown in preview when they can select something other than the declared policy result. At action start the target unit ID is reserved. At completion, the action uses one declared invalid-target policy: - `retarget_same_policy`: rebuild candidates and choose again; - `fizzle`: apply no primary effect and use the stated cooldown refund; - `ground_resolve`: resolve at the stored depth and affect current occupants. A target moving to another depth remains the same target if still legal. Every retarget or fizzle logs the first rejecting filter. #### 11.1 Forecast Is Not Resolution A forecast is a diagnostic prediction made from the committed preview or the state at automatic action selection. It stores predicted target IDs, depth, timing, and the rules that could change them. It never reserves a target and never fires a battle trigger. At action start, target selection creates the authoritative reservation. If its target differs from forecast because an earlier action, movement, collapse, or status changed state, the journal records `FORECAST_DIVERGED` with the first changed input. That is not a hit, miss, dodge, resistance, or action outcome. The reserved action then resolves normally. Likewise, if a reserved target moves before completion but remains targetable and inside all declared reach/protection filters, the action follows the same unit ID. Its terminal component outcome can be `AO_APPLIED`; the detail reason is `TARGET_MOVED_STILL_LEGAL`. Movement alone never creates an avoidance roll. #### 11.2 Terminal Outcome IDs Every started action produces one or more terminal outcome records. Records are per effect component and actual recipient; routing/invalidity records can name the intended target, and action-level cancellation records have no recipient. An area or multi-component action can therefore produce mixed outcomes without collapsing them into an invented accuracy value. | Outcome ID | Exact precondition | Ordering point | Player-visible causal label | |---|---|---|---| | `AO_APPLIED` | Legal component changes HP, barrier, status, resource, order, or another declared authoritative field on its actual recipient | Finalized after priority-7 deltas | `Applied`; use `Followed target` detail for `TARGET_MOVED_STILL_LEGAL` | | `AO_NO_CHANGE` | Component reaches a legal recipient but caps/current state yield zero primary change | Finalized after priority-7 deltas | `No change` plus cap/current-state reason | | `AO_INVALID_REACH` | Reserved target is living/targetable but current reach or protection filter is illegal | Completion validation at priority 4 | `Out of reach` plus old/current depth and required reach | | `AO_INVALID_UNTARGETABLE` | Reserved target is living but a declared Untargetable rule excludes it | Completion validation at priority 4 | `Untargetable` plus rule ID and remaining duration | | `AO_INVALID_FALLEN` | Reserved target is absent from the living line because it became Fallen before completion | Completion validation at priority 4 | `Target already Fallen` plus death event ID | | `AO_INVALID_FILTER` | Reserved target fails another declared side/state/tag candidate filter after the three specific invalid checks | Completion validation at priority 4 | `Target no longer eligible` plus filter ID | | `AO_INTERCEPTED` | Current projectile/protection path deterministically redirects the intended target's component to an eligible interceptor | Routing after target validation at priority 4 | `Intercepted by {actor}` plus path/protection rule ID | | `AO_BLOCKED` | An explicit Block charge or named deterministic component blocker nullifies the component before its primary delta | Defense allocation at priority 4; charge/delta commits in priority 7 | `Blocked` plus blocker actor/rule ID | | `AO_IMMUNE` | A declared immunity tag fully rejects the component before any resistance draw | Component defense at priority 4 | `Immune` plus immunity tag/source ID | | `AO_RESISTED` | A resistible status component is not immune and its stored `status_apply` roll is at/above `ApplyChanceBp` | Component defense at priority 4 | `Resisted` plus roll, threshold, Potency, and Tenacity | | `AO_FIZZLED` | Invalid-target policy is `fizzle`, retarget finds no legal candidate, or ground resolution has no eligible occupant | After invalid-target policy at priority 4 | `Action fizzled` plus invalid outcome/filter and refund | | `AO_INTERRUPTED` | A started wind-up/channel is cancelled by a declared interrupt before completion | When interrupt commits at priority 4 | `Interrupted` plus interrupter/rule and refund | `AO_BLOCKED` is not generic zero damage: barrier absorption is `AO_APPLIED` because barrier state changes. `AO_IMMUNE` requires a named immunity. A legal heal into full HP is `AO_NO_CHANGE`, not resistance. `AO_RESISTED` is limited to the existing deterministic status-application check and never implies an accuracy/evasion stat or a general attack miss. An action summary is derived only for display: ```text APPLIED_ALL = every primary component record is AO_APPLIED APPLIED_PARTIAL = at least one primary component is AO_APPLIED and at least one is not APPLIED_NONE = no primary component is AO_APPLIED ``` Summary values are not trigger IDs. The terminal records remain authoritative. #### 11.3 Resolution And Routing Order At priority 4, each completing action uses this order: 1. If a committed interrupt already cancelled the action, emit one `AO_INTERRUPTED` action record and stop. 2. Revalidate each reserved target against current state in this first-failure order: Fallen/absent, Untargetable, other declared candidate filter, then reach/protection. Emit the corresponding `AO_INVALID_*` reservation record. 3. Apply the skill's declared invalid-target policy. A successful `retarget_same_policy` reserves a new target and continues without refund; `ground_resolve` snapshots eligible current occupants at the stored depth; otherwise emit `AO_FIZZLED` and stop that action. 4. Resolve current projectile/protection paths. Emit `AO_INTERCEPTED` for each redirected intended target, then create component records for the actual interceptor. Interception itself never counts as an applied component. 5. Expand components and area recipients in current depth then stable-ID order. A footprint-2 actor is expanded once unless the skill explicitly says once per footprint. 6. Allocate finite Block charges and deterministic blockers. Same-tick claims use completion tick, target depth, source stable ID, then action sequence; one charge cannot block two components. Emit `AO_BLOCKED` for each allocation. 7. Check declared immunity before consuming a resistance or critical draw. Emit `AO_IMMUNE` on rejection. 8. For remaining resistible status components, consume and record exactly one `status_apply` draw. Emit `AO_RESISTED` when the roll fails the threshold. 9. Queue remaining numeric/status/movement deltas for priority 7. After the simultaneous batch, emit `AO_APPLIED` when primary state changed or `AO_NO_CHANGE` when it did not. 10. At priority 8, derive the action summary, apply at most one declared refund, claim outcome triggers, log suppressed duplicates, and queue derived actions for the next tick. An invalid reservation record remains terminal evidence even when retarget or ground resolution continues. The redirected/new recipient receives its own terminal component record, so diagnosis can say both why the original target was not affected and what actually happened. #### 11.4 Journal, Refund, And Proc Contract Every outcome record stores: ```text root_action_id, action_instance_id, action_sequence, skill_id, source_id selection_tick, completion_tick, effect_component_id, component_tags forecast_target_ids, reserved_target_id, reserved_depth actual_recipient_id, current_depth, outcome_id, reason_id retarget_policy, resolution_disposition, redirected_action_or_component_id interceptor_id, blocker_id, immunity_tag as applicable roll_label, draw_index, roll_bp, threshold_bp as applicable raw_delta, effective_delta, barrier_delta, status_or_movement_delta resource_spent, cooldown_committed, refund_resource, refund_cooldown_ticks trigger_claim_keys, fired_trigger_ids, suppressed_trigger_ids parent_action_id, derived_depth ``` Resource cost, Readiness, and cooldown are committed when the action starts. Default refund/proc behavior is: | Outcome/disposition | Default refund | Primary effect procs | |---|---|---| | Invalid record followed by successful retarget/ground resolution | none | evaluate only the new actual recipient's component outcomes | | `AO_FIZZLED` | skill's declared `fizzle_resource_refund_bp` and `fizzle_cooldown_refund_bp` | no on-hit/on-damage/on-heal/on-status proc | | `AO_INTERRUPTED` | skill's declared interrupt refund fields | `on_interrupt` and matching `on_outcome` only | | `AO_INTERCEPTED` | none | intended target can observe `AO_INTERCEPTED`; primary procs evaluate on actual recipient only | | `AO_BLOCKED`, `AO_IMMUNE`, `AO_RESISTED` | none unless exact ID appears in `refund_on_outcome_ids` | matching defensive hook and `on_outcome` only; no primary effect proc | | `AO_NO_CHANGE` | none | `on_outcome` only; no effective-delta proc | | `AO_APPLIED` | none | only hooks whose required effective delta/status/movement actually occurred | An outcome refund is evaluated once per root action after every component record is final. The skill declares `refund_match = all_primary | any_primary`; default is `all_primary`. Refund totals clamp to the originally committed cost/cooldown and never multiply by targets, components, or repeated outcome records. Outcome triggers use: ```text trigger_id, observed_role (source | intended_target | actual_recipient) outcome_ids[], component_tags[], once_scope (action | recipient | component) allow_derived (default false), resulting_action_or_hook ``` Default `once_scope` is `action`. Before firing, create: ```text trigger_claim_key = hash(root_action_id, trigger_id, scope_recipient_or_component) ``` The first claim fires in outcome-record order; later identical claims log `DUPLICATE_TRIGGER_CLAIM` and do nothing. Derived actions keep the same `root_action_id`, increment `derived_depth`, and cannot trigger a row with `allow_derived=false`. No derived chain can exceed depth 4 or the hook's declared per-action cap. ### 12. Projectile And Area Resolution A projectile declares speed in footprints per second, collision mode, pierce count, and damage retention. At launch: ```text arrival_ticks = max(1, ceil(cross_line_distance / projectile_speed / 0.1)) ``` At arrival, an intercepted projectile traverses the **current** opposing order from front to its reserved target and collides with the first eligible actor. After each pierced actor, remaining damage is multiplied by the declared retention in `0.50-0.90`. A reserved target that moved behind a new protector can therefore be intercepted. Lobbed and bypassing projectiles follow their declared protection mode instead. Areas are contiguous footprint intervals, not visual circles. An area row declares start policy, length, falloff, and whether a footprint-2 actor is hit once or once per footprint; default is once per actor. ### 13. Healing, Support, And Protection Access Support actions use same-line distance. Default heal selection is lowest HP ratio among legal allies; exact ratio ties choose the frontmost, then `target_tie`. A heal cannot pass its declared same-line reach because the animation appears to span the line. Barrier applies after healing in the same batch and is capped at 40% of target MaxHP across all generic barriers. Excess is logged as waste. `Block` is an explicit charge that nullifies one eligible hit after interception and before barrier. Area, true, or `unblockable` events must declare ineligibility. Protection stacks do not redirect heals. A support Profession may explicitly target `nearest_ally_ahead`, `nearest_ally_behind`, or a contiguous interval; the predicted support path updates when order changes. ### 14. Movement, Push, Pull, And Summons #### 14.1 Reordering Actions Battle movement is an automatic action, never free dragging: - `advance`: swap the actor block with the adjacent actor block ahead; - `withdraw`: swap with the adjacent actor block behind; - `push N`: move the target toward rear through up to `N` adjacent block swaps; - `pull N`: move the target toward front through up to `N` swaps; - `insert`: add a legal summon before/after its source; - `return`: remove a temporary summon or restore an explicitly stored order. Footprint-2 actors move as indivisible blocks. Simultaneous conflicting intents resolve larger declared movement priority first, then higher source Potency, then stable source ID. Losing intents fail with `DESTINATION_RESERVED`. Forced movement stops before an `Immovable` actor. Each unresolved forced step at a line boundary or blocker deals: ```text collision_damage = max(1, floor(0.08 * source_PhysicalPower)) ``` once per action, not once per blocked step. `Rooted` blocks voluntary movement; `Immovable` blocks forced movement. Rejections name `ROOTED`, `IMMOVABLE`, `NO_ADJACENT_ACTOR`, `DESTINATION_RESERVED`, or `CAST_LOCKED`. #### 14.2 Summon Footprint Each side has temporary summon allowance of two footprint beyond its committed deployment. A summon declares footprint 1 or 2 and insertion side relative to its source. It is legal only when: ```text current_living_footprint + summon_footprint <= committed_deployment_footprint + 2 ``` A failed insertion spends no summon resource and returns `NO_SUMMON_SPACE`. Summons never enter Reserve, hold equipment, create Replacement Credit, count as cumulative hires, or persist after battle. #### 14.3 Death Collapse After every death batch, Fallen actors are removed and both lines compact while preserving the relative order of survivors. New depths become authoritative before summon insertion and objective checks at priority 9. A scheduled action that reserved a Fallen target follows its retarget policy; it does not target the actor that happened to collapse into the old depth unless it uses `ground_resolve`. Reserve Recruits never fill a collapsed position during battle. At the next Market the player explicitly chooses any replacement and new order. ### 15. Damage, Critical, Healing, And Floors #### 15.1 Damage Skills declare `Base`, `Coefficient`, `PowerSource`, type, pierce, protection mode, and whether critical is legal. ```text RawDamage = max(0, Base + Coefficient * selected_power) EffectiveDefense = clamp(relevant_defense - pierce, -75, 500) if EffectiveDefense >= 0: DefenseMultiplier = 100 / (100 + EffectiveDefense) else: DefenseMultiplier = 2 - 100 / (100 - EffectiveDefense) CritChanceBp = clamp(skill_base_crit_bp + 20*(source_Finesse - target_Resolve) + explicit_crit_bp, 0, 5000) crit = can_crit and critical_roll_bp < CritChanceBp CritMultiplier = clamp(declared_crit_multiplier, 1.25, 2.00) if crit else 1.00 OutgoingGroup = clamp(1 + sum(outgoing_modifiers), 0.25, 3.00) IncomingGroup = clamp(1 + sum(incoming_modifiers), 0.25, 3.00) EncounterGroup = clamp(1 + sum(encounter_modifiers), 0.25, 3.00) GroupProduct = clamp(OutgoingGroup * IncomingGroup * EncounterGroup, 0.10, 4.00) Mitigated = RawDamage * DefenseMultiplier * CritMultiplier * GroupProduct Screened = Mitigated * max(0.70, 1 - 0.15*protection_stacks) DamageFloor = ceil(0.04 * RawDamage) FinalDamage = 0 if explicit_nullification else max(1, DamageFloor, floor(Screened)) HPDamage = max(0, FinalDamage - barrier_absorbed) ``` Use `Screened=Mitigated` for non-screened modes. Guard defends physical, Ward defends arcane, and true damage uses zero defense, cannot critical, ignores screening, and is capped at 25% target MaxHP per non-boss event. Barrier absorbs after the floor; an explicit nullification can produce zero. No other ordinary reduction bypasses the four-percent floor. Fixed boundary: `RawDamage=125`, defense `500`, GroupProduct `0.10`, no critical, and no screening yields `2.083...` before the floor. `DamageFloor=5`, so the resolved damage is `5` before barrier. Explicit nullification yields zero. #### 15.2 Healing ```text RawHeal = max(0, Base + Coefficient * HealingPower) FinalHeal = floor(RawHeal * OutgoingHealGroup * ReceivedHealGroup) EffectiveHeal = min(FinalHeal, MaxHP - current_HP) ``` Healing does not critical unless the skill declares a visible healing-critical rule. Overheal has no effect unless one named hook converts it; conversion is capped at 50% of overheal and still respects the barrier cap. ### 16. Status Effects And Resolution Order Each status declares: ```text status_id, category, source_id, target_id base_chance_bp, potency_source, resist_stat duration_ticks, interval_ticks, max_stacks stack_rule (add | refresh | replace | independent) dispel/immunity tags, on_apply, on_tick, on_expire presentation and causal-report events ``` For a resistible status: ```text ApplyChanceBp = clamp(BaseChanceBp + 25*(Potency - Tenacity), 500, 9500) applies = status_apply_roll_bp < ApplyChanceBp ``` Guaranteed effects bypass the roll but not declared immunity. If simultaneous effects apply the same status, resolve `replace`, then `add`, then `refresh`, then independent instances by source ID. Expiry occurs before periodic ticks, so a status with `end_tick == current_tick` does not tick again. Hard control effective duration is: ```text duration = clamp(BaseDuration * 100/(100 + Tenacity), 0.2, 3.0) ``` After hard control ends, the actor gains four seconds of Control Guard, reducing new hard-control duration by 75%. No actor may be unable to act for more than 50% of any rolling ten-second window. Boss caps and immunities are previewed. ### 17. Equipment, Artifacts, And Hooks Each Recruit has exactly one universal active equipment slot. An item may be presented as armament, guard, garb, charm, or kit, but those forms describe eligibility, attachment and visual language rather than simultaneous body slots. A Recruit therefore owns zero or one `equipped_item_id`. Equipping a candidate is one atomic replacement: the candidate leaves run inventory, the previous item returns to inventory if present, and the Recruit's single slot points to the candidate. An Artifact is a shared run rule and never occupies this slot. An item may react to an allied Recruit's item event, but no effect may require its wearer to hold a second item. All 320 equipment rows must alter a decision and declare one named hook. Scalar budget may support the hook but cannot be the row's only identity. One item ID cannot be owned by two Recruits. Company-unique effects declare a unique group; later copies retain local behavior but show the shared portion dormant. Artifacts are shared run rules. A run holds at most three active Artifacts. A fourth acquisition requires replacing one or declining the new row after an exact before/after preview. All 60 must change formation, targeting, market, risk, resource, promotion, summon, or reward valuation and must name a conflict. Legal battle hooks are: ```text before_target, after_target, before_cast, on_cast_complete, on_interrupt, before_damage, after_damage, on_critical, before_heal, after_heal, on_barrier_break, on_status_apply, on_status_expire, on_advance, on_withdraw, on_push, on_pull, on_protection_change, on_resource_gain, on_signature, on_summon, on_fallen, after_collapse ``` Each hook has a trigger limit, minimum 0.5-second cooldown unless a fixed loop proof allows otherwise, and recursion declaration. Derived events cannot retrigger their source by default. ### 18. Death, Dismissal, And Replacement #### 18.1 Battle Death At zero HP, a non-summon Recruit becomes Fallen: - it cannot act, target, protect, receive healing, or be promoted; - its death trigger resolves once at priority 8; - it is removed for line collapse; - no timer, item, Profession, Artifact, difficulty rule, or Reserve state can respawn, resurrect, or substitute for it during the encounter; - its recruit ID and optional equipped item ID enter the pending outcome casualty set; - it remains visible in diagnosis with the preceding five seconds of causes. At outcome application, each casualty and all returned equipment commit with Replacement Credit as one transaction. Victory, defeat, timeout, and retreat do not change the permanence of already Fallen Recruits. #### 18.2 Dismissal Dismissal is a Market-only operation. It is illegal for a deployed Recruit in a committed battle, a Fallen Recruit awaiting outcome, or a Recruit referenced by a pending promotion. It also uses the product authority's canonical count: ```text live_recruit_count = count(unique Recruit IDs owned by the current run whose state is living, across deployed party and Reserve) dismissal_legal = Market_open and target_is_living and live_recruit_count >= 2 ``` The preview and commit independently evaluate `dismissal_legal`. Review shows equipment return, rebate, lost level/history, and resulting deployable footprint. A legal confirm removes the Recruit once and asserts the post-state has `live_recruit_count >= 1`. If the count is one, or a once-valid preview becomes stale after another serialized operation leaves one living Recruit, reject `FINAL_LIVE_RECRUIT`. The rejection removes no Recruit or equipment, grants no Coin or Replacement Credit, changes no counters, and creates no protected recovery offer. Repeated confirm returns the same rejection. An interrupted pending dismissal must revalidate the active count before it can apply and is rejected without mutation when that count is one. Dismissal never creates Replacement Credit or a Meta reward. Explicit run abandonment is a distinct Market/result transaction, and casualty-driven replacement/Company collapse remains exclusive to casualty settlement. #### 18.3 Replacement Replacement is an ordinary hire using Coin and eligible Replacement Credit. After a casualty, the next Market protects one base-Profession recovery offer from refresh until bought or explicitly declined. Reserve never fills the line automatically. A run closes only when the player cannot legally deploy one living Recruit after all available recovery purchases or explicitly abandons. A blocked final dismissal never creates or refreshes this offer and never invokes the casualty recovery predicate. ### 19. Battle Control, Retreat, Timeout, And Outcome Pause, 1x, 2x, and 4x affect presentation only. Inspection while paused can open actor state, target reasoning, current action, queued major event, line depths, protection, status order, and causal log. Retreat becomes legal at tick 50 (5.0 seconds). Confirm begins a 20-tick global withdrawal. Automatic actions continue and Recruits can fall during it. At the end of the 20th tick, living allied non-summon actors escape and outcome becomes retreat. Repeating retreat confirm returns the same command receipt. At 120 seconds, Overtime begins: ```text for each completed 10-second Overtime band: all damage dealt multiplier += 0.25 all healing and new barrier multiplier -= 0.20 damage bonus caps at +0.75; healing/barrier penalty caps at -0.60 ``` At tick 1500, if the objective is not satisfied, the result is timeout defeat. Living Recruits survive; Fallen Recruits remain lost. Timeout grants no battle reward and applies the failure transaction in the save authority. Victory is evaluated after simultaneous damage, death, collapse, and summon events. If both victory and all-allied-Fallen predicates become true in the same batch, the declared objective decides: elimination objectives are a mutual defeat; survival/objective-complete battles are victory with zero living deployed Recruits and can close the run if no Reserve remains. ### 20. Enemy And Battle-Offer Contract Every ordinary/elite enemy and boss row declares: ```text enemy_id, ordinary | elite | boss, Region/Contract placement footprint, preferred depth, movement rules basic/technique/signature actions and automatic priority target/protection/reach/projectile/heal/summon rules first-major-action window and telegraph phase predicates, immunities, counter tags, two rational responses interaction with at least two older mechanics first-failure contribution and fixed fixtures ``` Before commitment, a battle offer shows exact enemy order and footprint, target policies, protection bypass, earliest major windows, movement, summon allowance, resistances, objective, timeout, retreat consequence, Coin reward, and reward family. A hidden visual identity may remain concealed for discovery; a mechanic needed for a fair choice may not. The complete envelope is 100 ordinary/elite identities plus 16 bosses across 8 Regions. Presentation variants do not count toward those totals. ### 21. Causal Diagnosis The result report presents, in order: 1. committed allied and enemy order; 2. predicted and actual first targets; 3. first divergence from predicted action/target/timing; 4. first protection change, projectile interception, or reach failure; 5. first decisive major action and available pre-battle counter categories; 6. every Fallen Recruit with the preceding five simulation seconds; 7. collapse, displacement, summon-space, retarget, and proc-suppression events; 8. effective damage, prevention, healing, control, and resource totals; 9. reward/failure/casualty operation IDs in technical details. The report can compare one alternate order or equipment removal against the same seed in a no-reward rehearsal. It may explain categories but cannot auto-equip a supposed universal answer. ### 22. Content Schemas #### 22.1 Skill Row ```text skill_id, owner_profession_id, tags, timing candidate filters, target policy, protection mode, retarget policy invalid-target outcome mapping, fizzle/interrupt refund fields reach, projectile/area/movement/summon fields Base, Coefficient, PowerSource, type, pierce, critical rule resource cost/gain, cooldown, status rows, proc hooks refund_on_outcome_ids, refund_match outcome triggers (trigger_id, observed_role, AO_* outcome_ids, component_tags, once_scope, allow_derived, resulting action/hook) automatic priority condition, illegal reasons, causal labels animation/VFX/SFX/caption/reduced-motion requirements fixed input and expected event output ``` #### 22.2 Equipment Row ```text equipment_id, form, acquisition band, list-price inputs eligible Profession/action tags changed decision and named behavior hook stat support budget, trigger, cooldown, recursion order/target/timing/resource/risk tradeoff two interaction fixtures and one loss/comparison fixture presentation/accessibility/localization needs ``` #### 22.3 Artifact Row ```text artifact_id, unlock/offer placement, shared hook run rule changed, conflict group, replacement comparison Market/battle/risk inputs and outputs two builds whose valuation changes in opposite directions fixed seed fixture and causal event ``` #### 22.4 Battle Offer Row ```text battle_offer_id, Region, Contract, Round, risk tier enemy lineup/order/levels, seed labels, objective preview fields, Coin reward, reward family, retreat/failure receipt expected duration, profile assertion, causal-report requirements ``` ### 23. Static Validation Gates - all Profession topology counts and parent links reconcile to 42; - all 36 Traits have one benefit, one cost, and two decision fixtures; - all 320 equipment and 60 Artifact rows name a behavior change; - all 100 ordinary/elite and 16 boss rows create a distinct counter question; - no deployed footprint exceeds current Line capacity; - target preview equals the first simulated target for fixed fixtures; - identical state/seed/retreat inputs yield identical hashes at every tick; - all actions stay inside reach, critical, defense, barrier, control, proc, and timeout bounds; - every projectile and movement conflict produces the declared collision/order; - every death returns the exact owned equipment once and never introduces a Reserve automatically; - invalid actions spend no resource and return one enumerated reason; - every started action/component has a declared terminal `AO_*` record and every outcome trigger references only IDs in Section 11.2; - duplicate trigger claims are journaled and cannot fire twice; - all standard fixtures resolve or timeout at/before tick 1500. ### 24. Required Fixed Test Vectors | Vector | Setup | Expected result | |---|---|---| | Frontbound | Three enemies; target policy frontmost | Only depth-zero enemy is a candidate | | Screened rear | Target has two footprint ahead | Legal screened hit uses `0.70` multiplier | | Cross-line reach | source depth 1, target depth 2, reach 4 | distance `1+1+2=4`, legal; reach 3 is illegal | | Heal tie | Two allies at equal HP ratio in reach | Frontmost wins, then deterministic tie draw | | Projectile intercept | Reserved rear target gains a new front summon before arrival | Current front summon is hit unless bypass/lobbed | | Push footprint | Push a footprint-2 target one step | Whole block swaps; it never splits | | Blocked push | Forced move has two remaining steps at boundary | One collision event, not two | | Summon full | committed footprint 10 plus temporary footprint 2 | another footprint-1 summon fails `NO_SUMMON_SPACE` | | Simultaneous lethal | Two actors complete lethal actions in one batch | Both events apply, both actors become Fallen | | Death collapse | Front actor falls before a reserved cast completes | Survivors compact; cast follows its declared retarget rule | | Reserve behavior | Deployed actor falls while living Reserve exists | Reserve does not enter until next Market preparation | | Damage floor | Raw 125, defense 500, group product 0.10 | damage 5 before barrier; explicit nullification 0 | | Critical boundary | roll 2499 with chance 2500 bp | critical; roll 2500 is not | | Status expiry | periodic tick equals end tick | expiry occurs; no final periodic tick | | Retreat | confirm at tick 50, no terminal predicate | outcome retreat after tick 70 batch; later duplicate has no effect | | Speed parity | identical battle at 1x and 4x | all authoritative hashes equal | | Timeout | objective incomplete at tick 1200/1500 | Overtime applies, then timeout defeat at tick 1500 | | Casualty equipment | Fallen Recruit owns one item | Recruit removed and that item ID returned exactly once; null slot returns nothing | | Final dismissal | one living Recruit across deployed plus Reserve | preview/commit reject `FINAL_LIVE_RECRUIT`; no state or recovery-offer change | | Moved target remains legal | Reserved target changes depth but remains targetable and in reach | same ID receives `AO_APPLIED`; detail `TARGET_MOVED_STILL_LEGAL`; no refund | | Moved target leaves reach | Reserved target moves from distance 2 to 3 against reach 2; policy `fizzle` | `AO_INVALID_REACH` then `AO_FIZZLED`; declared fizzle refund once | | Target becomes Untargetable | Living reserved target gains declared Untargetable before completion | `AO_INVALID_UNTARGETABLE`; row retarget/fizzle policy applies; no resistance draw | | Target falls first | Reserved target becomes Fallen in an earlier tick | `AO_INVALID_FALLEN` names death event; collapsed-depth actor is not substituted | | Interception | New front protector intercepts projectile aimed at legal rear target | intended target `AO_INTERCEPTED`; protector gets its own component outcome | | Explicit Block | Actual recipient owns one eligible Block charge | `AO_BLOCKED`; one charge consumed; no primary proc or default refund | | Immunity | Status target has matching immunity tag | `AO_IMMUNE`; no `status_apply` draw and no status proc | | Resistance | No immunity; stored roll 7000, threshold 6500 | `AO_RESISTED` with roll/threshold; no general attack miss | | Mixed area | Three recipients: one changed, one immune, one already capped | `AO_APPLIED`, `AO_IMMUNE`, `AO_NO_CHANGE`; summary `APPLIED_PARTIAL` | | Duplicate trigger suppression | Mixed area yields three matching records for one once-per-action trigger | first claim fires; later claims log `DUPLICATE_TRIGGER_CLAIM`; one derived action next tick | ### 25. Acceptance Checklist - [ ] One ordered line owns protection, reach, projectiles, healing, movement, summon footprint, death collapse, and replacement behavior. - [ ] Battle formulas define tick order, random labels, damage floor, critical, status order, timeout, and fixed vectors. - [ ] Deterministic outcomes distinguish forecast divergence, target invalidation, interception, Block, immunity, resistance, application, and duplicate trigger suppression without accuracy/evasion. - [ ] Generated Recruit and fixed Profession schemas are complete without requiring authored individual narrative content. - [ ] Fully automatic combat exposes only the approved diagnostic controls and retreat. - [ ] Content counts and no-filler tests match the product authority. - [ ] Save/failure owns durable death and operation recovery; economy owns all purchase, reward, capacity, and pacing numbers. ## Aetherbound Guild: Economy And Balance Authority > Authority: Market offers, prices, locks, refreshes, Coin and Replacement > Credit, rewards, progression rates, Line-capacity selection, difficulty > parameters, first-clear pacing, solvency, recovery, and anti-dominance tests. > > Revision: anti-dominance-fixture-r1 / 2026-08-11 > > [01_GAME_DESIGN.md](01_GAME_DESIGN.md) owns the player promise > and content envelope. [02_GAMEPLAY_AND_BALANCE.md](02_GAMEPLAY_AND_BALANCE.md) owns > battle and content schemas. [02_GAMEPLAY_AND_BALANCE.md](02_GAMEPLAY_AND_BALANCE.md) > owns exactly-once application, run failure, interruption, and recovery. ### 1. Economy Invariants 1. All gameplay value is earned in play. There is no paid currency, paid reroll, ad reward, energy, streak, offline income, or real-time wait. 2. Coin and Replacement Credit exist only in the current run. Renown and progression facts persist, but cannot buy raw combat stats, starting Coin, or starting Line capacity. 3. Every Market contains one steady battle offer. A random offer or refresh is never required to obtain a baseline counter for a mandatory boss. 4. Death is costly through lost level, Profession, Trait, history, and order, but returned equipment and Credit make ordinary replacement recoverable. 5. Dismissal, selling, refresh, lock, reward, and purchase formulas cannot create Coin-positive loops. 6. All 320 equipment and 60 Artifact rows change a decision. Economy tiers and prices may not turn a scalar variant into a gameplay identity. 7. Reward, Market, Recruit-generation, and combat random streams are separated. Reload, speed, input repeat, and unrelated draws do not change offers. 8. The Standard first clear is solvent on deterministic steady offers without Meta power, random high-tier equipment, or repeated failed-run farming. ### 2. Resource Ledger | ID | Player name | Persistence/cap | Sources | Sinks or closure | |---|---|---|---|---| | `coin` | Coin | Current run; nonnegative; no hard cap | Run start, battle rewards, reward cards, equipment sales, dismissal rebate | Recruit/equipment purchase, refresh, lock; cleared when run closes | | `replacement_credit` | Replacement Credit | Current run; cap 54 | Fallen non-summon Recruits | Optional reduction on a later Recruit hire; cleared when run closes | | `xp` | Experience | Current Recruit; level cap 10 | Completed battles entered by that Recruit | Level thresholds; disappears with Recruit/run close | | `renown` | Renown | Guild; cap 9,999 | first Contract clears, first discoveries, mastery goals, limited repeat objective | Catalog breadth, previews, challenge laws, hidden-hybrid discovery clues | | `clear_fact` | Region/Contract clear | Guild fact, not spendable | first valid boss result | Region order, ending, postgame access | | `discovery_fact` | Catalog discovery | Guild fact, not spendable | first valid inspection/acquisition/encounter | Collection, deterministic future pool access, completion | There is no material or crafting currency in the base contract. Equipment is bought, rewarded, equipped, returned after death, sold, or closed with the run. Adding a persistent resource requires an Owner-approved contract revision. ### 3. Run Opening And Capacity Economy A run begins with: - two of four provisional generated Recruits selected at zero Coin price; - `52 Coin`; - zero Replacement Credit; - Line capacity four; - exactly one starting item on each provisional Recruit and no extra equipped slots; - no active Artifact. The first Market contains at least two base-Profession Recruit offers at level 1. The two together cost 28 Coin, leaving 24 for an equipment, lock, refresh, or reserve decision. For `C` cleared ordinary Rounds in `0..12`: ```text line_capacity(C) = min(10, 4 + floor(C/2)) ``` Capacity therefore becomes `4,5,6,7,8,9,10` at clear counts `0,2,4,6,8,10,12`. It is granted automatically after result settlement, is not sold, and resets next run. Purchases and cumulative hires do not change it. ### 4. Market Board And Offer Generation Every ordinary Market contains: | Row | Slots | Generation constraint | |---|---:|---| | Recruit | 3 | At least one base Profession; after a casualty, one protected recovery offer | | Equipment | 4 | At least three different behavior tags and two legal current users unless Company is empty | | Battle | 3 | Exactly one steady offer and two distinct higher-risk or different-counter offers | Boss Muster uses the same Recruit/equipment counts but one fixed boss offer. It cannot refresh or replace the boss. Each Market is generated from: ```text hash(run_seed, contract_id, Market_index, row_id, slot_index, refresh_index) ``` Labeled substreams are `recruit`, `equipment`, `battle`, and `reward`. An offer stores its complete generated fields and hash before presentation. Reopening, changing language, inspecting another screen, or closing the application does not redraw it. #### 4.1 Offer Level And Pool For ordinary Round `R` in `1..12`: ```text offer_level(R) = min(10, 1 + floor((R-1)/3)) ``` Boss Muster uses the Round-12 offer level. Base Professions remain in every pool. Regular advanced direct hires may appear from Round 7 after their catalog unlock. Hidden hybrids are promotion outcomes and cannot be bought directly. Equipment uses Region band `B` in `0..7` and item tier `T` in `0..3`. At least one tier-0/1 legal item remains possible in every ordinary Market. A boss counter has one deterministic Region objective or fixed Muster offer; it is never refresh-gated. #### 4.2 Lock The player may lock at most three unbought Recruit/equipment offers. Each newly locked offer costs `2 Coin` once and persists through the next Market or until bought/declined. Unlocking does not refund Coin. Battle offers can be locked only within the current Market so the player can refresh other rows; they never carry beyond a committed battle. The protected recovery offer needs no paid lock, survives refresh, and expires only when bought, explicitly declined, or the run closes. #### 4.3 Refresh Refreshing replaces every unlocked, unbought offer except a fixed boss and a protected recovery offer. Let `N` be prior refreshes in the current Market and `L` the number of paid locked offers: ```text refresh_cost(N,L) = min(24, 6 + 3*N + 2*L) ``` `N` starts at zero each Market and increments atomically with the new board. The first no-lock refresh costs 6, the second 9, and the seventh and later cost 24. Insufficient Coin rejects the operation without changing offers or `N`. ### 5. Prices, Sales, And Dismissal #### 5.1 Recruit Price For offer level `L` and Profession tier `P` (`0` base, `1` regular advanced): ```text hire_list_price(L,P) = 10 + 4*L + 10*P ``` Trait and rolled distribution do not add a hidden price because level totals are equal-budget and every Trait has a cost. A Recruit's generated offer stores the list price. Replacement Credit is optional at confirm. If `use_credit` is true: ```text credit_used = min(replacement_credit_balance, hire_list_price) coin_cost = hire_list_price - credit_used ``` If false, `credit_used=0`. Coin cost, Credit spend, Recruit creation, and offer removal apply atomically. Credit cannot buy equipment, refreshes, locks, or Meta progression. #### 5.2 Equipment Price And Sale For Region band `B` in `0..7` and item tier `T` in `0..3`: ```text equipment_list_price(B,T) = 12 + 3*B + 6*T sale_value = floor(0.30 * coin_price_paid) ``` An equipment reward stores `coin_price_paid=0` and therefore sells for zero; its value is the behavior it enables. Purchased copies never sell above 30%. Locked, equipped, or battle-committed items must be released before sale. #### 5.3 Dismissal Rebate The product authority's canonical count and precondition apply before rebate calculation: ```text live_recruit_count = count(unique Recruit IDs owned by the current run whose state is living, across deployed party and Reserve) dismissal_legal = Market_open and target_is_living and live_recruit_count >= 2 ``` Only for a legal dismissal: ```text if survived_battles >= 2: dismissal_rebate = min(10, floor(0.25 * coin_price_paid)) else: dismissal_rebate = 0 ``` `coin_price_paid` excludes Credit. Equipment returns before the Recruit is removed, all in one operation. Dismissal creates no Credit, Renown, XP transfer, offer reroll, or reward. A same-level replacement always costs more Coin than the rebate unless Credit came from an unrelated death. When `live_recruit_count == 1`, preview and commit reject `FINAL_LIVE_RECRUIT` before the rebate formula. The blocked action grants zero Coin, zero Credit, no protected recovery offer, and no economic or roster mutation. `Abandon Run` remains a separately confirmed run-close operation and does not pay a dismissal rebate. Counterexample trace: ```text state: Market open; one living Recruit; Coin=3; Credit=0; no protected recovery offer; Recruit paid 32 Coin and survived 3 battles attempt: preview dismissal, then submit the same confirm after interruption result: FINAL_LIVE_RECRUIT at preview and commit after: one living Recruit; Coin=3; Credit=0; no protected offer; dismissed_total unchanged; calculated dismissal rebate is not applied next legal terminal choice: continue Market play or confirm Abandon Run ``` The hypothetical eight-Coin rebate cannot make the final dismissal legal. Casualty settlement may later create Credit or a protected offer if the Recruit falls; it is not simulated by dismissal. ### 6. Battle Income And Reward Drafts Battle risk `Q` is `0` steady, `1` pressured, or `2` elite. For Region band `B` in `0..7` and ordinary Round `R`: ```text battle_coin(B,R,Q) = floor((18 + 2*R + 2*B + 7*Q) * difficulty_reward_multiplier) reward_budget(B,R,Q) = 12 + 2*R + 3*B + 6*Q ``` Coin pays once on victory before the reward choice. Defeat, timeout, and retreat pay no battle Coin. Economic consequences after those outcomes are owned only by the save/failure authority. The victory reward draft is stable: | Risk | Cards | Required composition | |---|---:|---| | Steady | 2 choose 1 | one legal equipment/tag card; one `floor(0.50*reward_budget)` Coin card | | Pressured | 3 choose 1 | two distinct legal equipment/tag cards; one Coin or Recruit-discount card | | Elite | 3 choose 1 | one Artifact-eligible card, one equipment/tag card, one Coin/recovery card | An Artifact card offers three fixed Artifact IDs and the player chooses one. If three Artifacts are already active, comparison/replacement is part of the same operation. Declining a reward is legal and grants nothing. A reward card cannot be rerolled by leaving the result. The boss awards no spendable Coin because the run closes. A first boss clear grants the persistent values in Section 9 and one fixed discovery choice. ### 7. Death Credit And Recovery Solvency When a hired or provisional Recruit becomes Fallen, use its original list price and actual Coin paid: ```text credit_grant = min(original_list_price, 10 + floor(coin_price_paid/2)) new_credit_balance = min(54, old_credit_balance + credit_grant) ``` Credit, permanent Recruit removal, and equipment return apply in one casualty operation. A provisional Recruit has `coin_price_paid=0` and an implicit level-1 base list price of 14, so it grants 10 Credit. Summons grant none. After one or more casualties, the next Market reserves one base-Profession recovery offer with all of these properties: - its level is `max(1, offer_level-1)`; - its Profession supplies at least one missing primary responsibility among protection, damage, reach, or sustain when such a catalog row is unlocked; - it is not replaced by refresh and needs no lock fee; - its list price uses the normal formula and Credit can reduce it to zero; - buying or explicitly declining it clears protection, not remaining Credit. The guarantee makes a replacement visible, not automatically optimal. A lost advanced or promoted Recruit returns as a cheaper base Recruit unless the player chooses to spend more on another offer. #### 7.1 Three-Death Fixture At Round 7, three base Recruits originally bought for 18 Coin each fall. The current base list price is 22, the player has 12 Coin, and Credit cap is 54: ```text grant per Recruit = min(22, 10 + floor(18/2)) = 19 balance after three grants = min(54, 57) = 54 replacement Coin costs = 0, 0, 12 ending Coin = 0; ending Credit = 0 ``` Three legal replacements are therefore purchasable in the next Market. The player has lost their levels, Traits, promotion progress, history, and all liquid flexibility, so the loss is recoverable but not profitable. ### 8. XP, Levels, And Promotion Pace For Recruit level `L` from 1 through 9: ```text xp_to_next(L) = 20 + 10*L battle_xp(R,Q) = 10 + 2*R + 4*Q ``` Living deployed Recruits receive 100% on victory, 50% on defeat/timeout when at least one deployed Recruit survives, and 50% on completed retreat. Reserve and Fallen Recruits receive zero. Difficulty and display speed do not multiply XP. XP is applied after casualty determination. A Recruit can gain multiple levels from one award, checking the formula at each new level, but cannot exceed 10. At cap, excess is discarded and shown. Promotion eligibility at level 4 plus three survived battles is owned by the systems authority. There is no permanent Recruit level, inheritance, XP item, or Meta stat. New hires catch up through offer level and price rather than receiving another Recruit's progress. #### 8.1 Enemy Rank And Within-Run Scaling Regions add mechanics, not a permanent vertical stat ladder. Within a run, enemy stat pressure follows the current offer level and risk: ```text encounter_rank(R,Q,boss) = min(6, offer_level(R) + Q + (1 if boss else 0)) rank_multiplier = 1 + 0.08*(encounter_rank - 1) ``` Apply `rank_multiplier` once to an enemy row's base MaxHP, power, Guard, Ward, Potency, and Tenacity, rounding half up. Tempo, Initiative, reach, target rules, cooldowns, footprint, and status durations do not scale. Difficulty then applies its declared HP and damage/healing multipliers once. Identity base budgets are content-authored within the systems ranges and must pass fixed same-rank comparisons. A later Region cannot substitute a larger base budget for a new mechanic, and no mandatory battle assumes a prior run's Recruit or equipment. ### 9. Renown And Meta Progression For Region number `G` in `1..8` and Contract rank `K` in `{1,2}`: ```text first_clear_renown(G,K) = 8 + 2*G + 4*K repeat_objective_renown = min(2, unclaimed_repeat_goals_for_contract) ``` First discovery of a Profession, Trait, equipment behavior family, Artifact, ordinary/elite enemy, or boss grants one Renown once. A row's presentation variants grant none. Repeat objectives are finite checklist entries; replaying an unchanged clear after they are claimed grants zero Renown. Renown purchases only breadth: | Unlock | Cost range | Allowed effect | |---|---:|---| | Catalog pool packet | 4-8 | Add sidegrade equipment/Trait/Artifact rows to future eligible pools | | Advanced Profession clue/trial | 8-12 | Reveal requirements and enable a deterministic trial | | Hidden-hybrid clue/trial | 14-18 | Reveal one predicate and enable its mastery trial | | Threat archive upgrade | 6-10 | Expose additional exact preview fields for encountered families | | Oath law | 12-20 | Add a postgame optional run modifier and its completion Record | Forbidden effects include percentage power, HP, defense, Coin gain, cheaper shops, free refreshes, starting equipment, starting Recruits, extra reward cards, larger starting Line capacity, or casualty reversal. All mandatory Standard counters are in the default or deterministic Contract pool. A player never needs a Renown purchase to finish the first clear. #### 9.1 Guild Charter Transaction `PRO-002` presents the existing Renown authority as the **Guild Charter**. It is not a new economy, currency, progression tree, or permanent-stat layer. The board contains exactly eight horizontal Region seals in campaign order. A seal opens only its authored packet cards and prerequisite tracks; no radial layout or copied node graph is permitted. Each claim uses one stable `charter_claim_id` and the existing cost range above: ```text preview = (charter_claim_id, region_id, prerequisite_ids[], renown_cost, effect_family, future_run_effect, balance_revision) commit = verify preview + debit Renown + append one claim receipt atomically retry = return the original receipt; never debit or grant twice ``` The preview must show current Renown, remaining Renown, every prerequisite, whether each prerequisite is satisfied, the exact future-run breadth change, and the statement `No permanent combat power`. A failed prerequisite, stale balance revision, insufficient balance, duplicate claim, or interrupted write cannot partially reveal a packet or consume Renown. Respec and refund are not part of the contracted board; claims are permanent breadth unlocks. The first-clear choice after the sixteenth boss creates no new currency and grants no choice-specific combat value. Both branches settle the same earned Renown and first-clear Records exactly once, archive the surviving Company, and close Coin/Credit with the run. **Complete the First Chronicle** changes only the next destination to Final Ledger/Title. **Open the Oath Season** additionally sets postgame eligibility and enters rule review; its first playable state is a new generated run after that review. Ordinary New Run remains available and uses the same persistent breadth already owned. ### 10. Equipment And Artifact Distribution The 320 equipment entries are divided into eight Region bands of 40. Every band contains all five item forms (armament, guard, garb, charm, and kit), all primary responsibilities, and at least three opposed order/reach/protection plans. Every Recruit has one universal active slot, so form controls eligibility and presentation rather than granting simultaneous slots. Tier describes price and availability, not strict power. A lower tier must lead one fixed comparison in which it is the rational choice. Each item has a numeric support budget separate from its required behavior: ```text item_stat_budget(T) = 30 + 8*T ``` The behavior hook reserves 12-24 budget points. At most 50% of the total budget may be generic HP, power, Guard, or Ward. Remaining numeric support uses: | Stat | Cost | |---|---:| | +1 Might, Finesse, Insight, Vigor, or Resolve | 2 | | +1 WeaponPower, FocusPower, ArmorGuard, or ArmorWard | 1 | | +6 MaxHP | 1 | | +1 Potency or Tenacity | 1 | | +0.20 Tempo or Initiative | 1 | The one equipped item's numeric support is added before derived-stat rounding. Region band does not increase this budget; later bands introduce new interactions rather than automatic vertical power. All 320 entries pass the systems behavior fixture. No scalar-only allowance or minimum subset exists. The 60 Artifacts are distributed across first-clear, elite, boss, mastery, and postgame pools. Every run sees at least one deterministic Artifact choice by the end of Round 6 and at least one additional choice by boss Muster. No Artifact is required for a mandatory boss. Duplicate active Artifact IDs are illegal. Bad-luck protection uses behavior tags: ```text if two consecutive eligible equipment drafts omit the selected behavior tag: the third eligible draft contains that tag ``` The counter resets when offered, not accepted. The selected tag may be changed at any Market for zero Coin before a draft is generated. It cannot name an undiscovered exact item. ### 11. Capacity Selection Simulation The `10-12` target range was evaluated with an explicit analytical workload model. It is a design simulation, not human readability evidence. For profile `P` and candidate capacity `C`: ```text prep_seconds(P,C) = ceil(base_P + inspect_P*C + reorder_P*C*(C-1)/2) battle_p95_seconds(C) = ceil(52 + 5.4*C) causal_events_per_second(C) = 1.2 + 0.24*C ``` The pair term models order comparisons, not every permutation. The gate is `prep <= 150 s` for every profile, battle p95 `<=120 s`, causal events `<=4.0/s`, and the three-death fixture recoverable in at most one Market. | Profile | `base` | `inspect` | `reorder` | C=10 prep | C=11 prep | C=12 prep | |---|---:|---:|---:|---:|---:|---:| | Normal | 20 | 4.0 | 0.8 | 96 s | 108 s | 121 s | | Active | 25 | 5.0 | 1.4 | 138 s | 157 s | 178 s | | Efficient | 15 | 3.0 | 0.5 | 68 s | 76 s | 84 s | | Adversarial | 20 | 4.5 | 1.3 | 124 s | 141 s | 160 s | | Returning | 30 | 5.5 | 1.3 | 144 s | 162 s | 182 s | | Candidate | Profiles passing prep | Battle p95 | Causal events/s | Three-death recovery | Result | |---:|---:|---:|---:|---:|---| | 10 | 5/5 | 106 s | 3.60 | 1 Market | Pass | | 11 | 3/5 | 112 s | 3.84 | 1 Market | Fail profile gate | | 12 | 2/5 | 117 s | 4.08 | 1 Market | Fail profile and event gates | Ten is the largest candidate passing every declared gate. Human testing still owns whether ten simultaneous allies plus enemies remain visually legible. ### 12. Contract And First-Clear Pacing Each Region contains two Contracts. Every Contract is twelve ordinary Rounds, boss Muster, and one boss. The Normal authored means are: | Region | Contract 1 | Contract 2 | Region total | Content pressure | |---:|---:|---:|---:|---| | 1 | 50 min | 54 min | 104 min | recruit valuation, front/rear, reach | | 2 | 54 min | 58 min | 112 min | protection bypass and healing access | | 3 | 56 min | 60 min | 116 min | projectiles and interception | | 4 | 58 min | 62 min | 120 min | movement, push, and pull | | 5 | 60 min | 64 min | 124 min | summons and footprint pressure | | 6 | 62 min | 66 min | 128 min | status ordering and control | | 7 | 64 min | 68 min | 132 min | promotion and Artifact conflicts | | 8 | 66 min | 70 min | 136 min | full-system synthesis | Successful Contract time sums to `972 minutes`. This time is active Market, battle, result, and boss play; it excludes loading and forced waiting. #### 12.1 Five Full-Clear Profiles | Profile | Successful Contract minutes | Failed/abandoned-run minutes | Guild/onboarding/recap minutes | Total | First-clear hours | |---|---:|---:|---:|---:|---:| | Efficient | 768 | 120 | 90 | 978 | 16.30 h | | Normal | 972 | 120 | 78 | 1,170 | 19.50 h | | Active | 1,152 | 150 | 90 | 1,392 | 23.20 h | | Adversarial | 928 | 300 | 92 | 1,320 | 22.00 h | | Returning | 1,024 | 120 | 161 | 1,305 | 21.75 h | Every profile is inside 15-25 hours. The efficient profile cannot skip required bosses or decisions; it saves time through faster comparison and presentation speed. Adversarial includes more elite offers and recoverable losses. Returning includes recap/segmentation overhead, not forced repetition. Mastery targets 60+ cumulative hours. At least 70% of post-ending time must use a previously unclear Profession, Trait, equipment behavior, Artifact conflict, enemy/boss fixture, or Oath law. An unchanged clear may contribute at most 20% of any mastery milestone. ### 13. Exact Twenty-Minute Pacing Traces All timestamps are simulation-independent wall time spent actively playing a representative 1,200-second session. `M` lists Market openings. `B` lists battle start-end intervals. `D` lists meaningful decisions; confirmation, inspection, speed changes, and reward animation do not count. | Profile | `M` Market opens (s) | `B` battle intervals (s) | `D` decision timestamps (s) | Maximum decision gap | |---|---|---|---|---:| | Normal | `[0,300,600,900]` | `[(180,270),(480,570),(780,870),(1080,1170)]` | `[25,90,175,280,325,390,475,580,625,690,775,880,925,990,1075,1180]` | 105 s | | Active | `[0,330,660,990]` | `[(210,300),(540,630),(870,960),(1140,1200)]` | `[20,75,135,205,310,350,410,475,535,640,680,740,805,865,970,1015,1070,1135]` | 105 s | | Efficient | `[0,260,520,780,1040]` | `[(130,230),(390,490),(650,750),(910,1010),(1170,1200)]` | `[35,125,240,295,385,500,555,645,760,815,905,1020,1075,1165]` | 115 s | | Adversarial | `[0,290,610,940]` | `[(150,260),(440,580),(760,910),(1100,1200)]` | `[30,80,145,270,320,375,435,590,640,700,755,920,970,1030,1095]` | 165 s | | Returning | `[0,270,590,930]` | `[(140,240),(420,550),(760,890),(1090,1180)]` | `[25,85,135,250,300,355,415,560,620,680,755,900,950,1015,1085,1190]` | 145 s | The gap includes time zero to the first decision and the last decision to 1,200. Every battle that completes before the trace boundary is followed by its next decision within 15 seconds. Decision kinds across each trace must include Recruit/equipment valuation, order or deployment, battle-risk commitment, reward/recovery, and next-Market budget. Adversarial's 165-second gap is a long elite battle and remains below the product veto because the battle itself is capped at 150 simulation seconds and the result decision appears immediately afterward. ### 14. Standard Solvency Trace A lowest-reward run takes only steady offers. In Region band `B`, ordinary battle income is: ```text sum(battle_coin(B,R,0), R=1..12) = sum(18 + 2*R + 2*B) = 372 + 24*B Coin ``` With starting Coin, total pre-boss resources are `424 + 24*B Coin`. The baseline plan spends: | Required purchase | Cost | |---|---:| | Eight base hires needed to grow from two provisional Recruits to capacity ten | 156 | | Two tier-0/1/2/3 items in Region band `B` | `168 + 24*B` | | Two refreshes in one no-lock Market | 15 | | Three locks | 6 | | Total | `345 + 24*B` | The Region-band income and equipment-price terms cancel exactly, so the run reaches boss Muster with `79 Coin` before optional sales, risky-offer bonuses, reward Coin cards, or Credit. The deterministic boss-counter objective costs no more than one omitted baseline equipment purchase. Standard solvency passes when every Region seed can follow an equivalent plan with at least 40 Coin or one complete three-casualty recovery set entering boss Muster. ### 15. Anti-Dominance And Balance Gates #### 15.1 Required Strategy Tests | Candidate policy | Why it might dominate | Rejection fixture | |---|---|---| | Always refresh twice | More chances at desired synergies | Costs at least 15 Coin per Market before locks; 12-Market use costs 180, exceeds the 79-Coin baseline reserve and must lose one fixed low-variance seed | | Never refresh | Preserves all Coin | Must lose value in at least two of five seeds where one refresh exposes a counter tag worth more than 6 Coin | | Buy every Recruit | Reserve breadth and death insurance | Reserve earns no XP/Coin; dismissal returns at most 25% paid Coin; fixed plan must lose equipment/refresh flexibility and fail one boss comparison | | Dismiss after every battle | Attempt to cycle Traits/offers | No Credit, zero rebate before two survivals, maximum 10 later; cycle is strictly Coin-negative and loses history/level | | Never dismiss | Avoid sunk-cost loss | Must lose one fixture where releasing an obsolete low-level Reserve funds a reachable counter without weakening deployed footprint | | Never replace | Preserve Coin after death | Must lose one post-casualty fixture because lower footprint changes reach/protection and leaves Coin unused | | Always take steady | Minimize death | Must trail pressured/elite in at least one build-breadth objective and one Artifact timing fixture | | Always take elite | Maximize rewards | Expected casualties and missed steady recovery must reduce clear rate or terminal Coin in at least two profiles | No policy needs to be bad everywhere. A policy is dominant if it weakly beats all alternatives in every fixed state and strictly beats one; any such result blocks the design. #### 15.2 Executable Fixed-Seed Comparator The Gate 6 build-policy proof is [ANTI_DOMINANCE_FIXED_SEEDS.json](product/fixtures/ANTI_DOMINANCE_FIXED_SEEDS.json), recalculated by `python3 tools/simulate_anti_dominance.py`. It is a prebattle feasibility comparator, not a second combat model: the fixture declares the locked route's ordered enemy inputs, required counter tags, minimum deployed footprint, and casualty counts. The script replays the Market transactions, tests that the resulting deployed build covers those route requirements, and then applies the Section 6 battle-Coin formula only on a clear. It introduces no accuracy, evasion, random draw, hidden generator state, or formula override. Every seed declares all of the following rather than asking a generator for them at test time: | Fixture field | Required declared input or recalculation | |---|---| | State | Round, cleared Rounds, Region band, difficulty, Coin, Credit before casualties, prior refresh count, paid locks, and expected capacity/offer-level/refresh-cost values | | Company | Every living Recruit ID, deployed/Reserve assignment, counter tags, Coin paid, and survived-battle count | | Recovery | Every casualty's original list price, Coin paid, expected Credit grant, post-casualty Credit, and the protected offer ID or explicit null | | Boards | All three Recruit, four equipment, and three battle offers on both the opening and first-refresh board, including exact price inputs and stored prices | | Route | The paid-locked route preserved through refresh, ordered enemy inputs, risk, required tags, deployed footprint, outcome casualties, and stored battle Coin | | Oracle | Exact action trace and outcome metrics for every policy plus the expected winner | Each fixture's opening Coin is the post-lock balance; the declared paid lock is already sunk. Its count still enters the first-refresh formula, and the locked route is byte-identical on the refresh board so every policy faces the same combat contract. The script rejects a missing row or field, a sixth or duplicate seed, a changed locked route or protected offer, a noncanonical price/reward/Credit value, an illegal deployment, or an expected-result mismatch. A casualty state must have exactly one protected Recruit on both boards. The protected offer remains unchanged through refresh. Dismissal checks the canonical living count before target selection; with one living Recruit it records `FINAL_LIVE_RECRUIT`, pays no rebate, and may still perform a separate legal equipment purchase. Casualty Credit and protected recovery are inputs to later hire transactions, never a dismissal side effect. The four fixed policy families are intentionally narrow and deterministic: | Policy | Exact algorithm | |---|---| | `refresh_first` | Pay exactly the declared first refresh when affordable, then buy at most one affordable refreshed equipment offer that maximizes missing route-tag coverage; ties use lower price then offer ID | | `hire_first` | Buy at most one affordable opening-board Recruit, preferring the protected offer, then missing route-tag coverage, lower Coin cost after optional Credit, lower list price, and offer ID; deploy it only when capacity has a vacancy | | `dismiss_first` | If legal, dismiss one Reserve with least route relevance, then highest rebate and offer ID tie-breaks; otherwise record the rejection; buy at most one affordable opening-board equipment counter | | `no_replace` | Never refresh, hire, or dismiss; buy at most one affordable opening-board equipment counter using the same coverage/price/ID ordering | The comparison is lexicographic and all higher values are better: `route_cleared`, ending Coin, ending Credit, ending living Recruit count, then counter-tag coverage. The JSON also records deployed/required footprint, battle Coin, Market Coin spent, dismissal rebate, Credit used, Line capacity, and exact actions. This ordering does not convert Credit into Coin and does not claim that the fixture policies are exhaustive play. It makes one declared prebattle choice comparable without hiding a utility weight. For two policies `A` and `B`, `A` weakly dominates `B` only when `A`'s complete comparison tuple is at least `B`'s on all five seeds and strictly greater on at least one. The run fails if either policy has no win, has no loss, or any ordered policy pair meets that definition. `--self-test` first accepts the canonical matrix, then creates an in-memory matrix in which `refresh_first` beats every peer on every seed and proves that the dominance check rejects it. | Stable seed | Fixed state counterfactual | Expected winner | |---|---|---| | `AD-FS-001-REFRESH-COUNTER` | First refresh exposes the locked pressured route's only affordable wardbreak counter | `refresh_first` | | `AD-FS-002-PROTECTED-HIRE` | One casualty leaves both a protection and fourth-deployed-Recruit gap | `hire_first` | | `AD-FS-003-DISMISSAL-REBATE` | A legal four-Coin obsolete-Reserve rebate makes the current reach counter affordable | `dismiss_first` | | `AD-FS-004-PRESERVE-COIN` | The current line already clears; extra transactions lose Coin or living roster value | `no_replace` | | `AD-FS-005-CREDIT-CROSSOVER` | Final-Recruit dismissal is illegal and a zero-Coin protected hire beats two equipment paths | `hire_first` | Canonical verification is: ```sh python3 tools/simulate_anti_dominance.py --self-test python3 tools/simulate_anti_dominance.py python3 tools/simulate_anti_dominance.py | shasum -a 256 ``` Two default runs must be byte-identical. The summary prints every policy's clear, ending Coin, ending Credit, ending living count, and counter coverage for every seed, the win counts, a canonical result SHA-256, and `ABG_ANTI_DOMINANCE_OK no_weak_dominance=1`. #### 15.3 Complete Gates 1. **Solvency:** all eight Region bands have a steady Standard plan reaching boss Muster with 40 Coin or the full declared recovery set. 2. **Recovery:** the Section 7.1 three-death state fields three legal base replacements in one Market and does not increase total Coin-equivalent value. 3. **Capacity:** candidate ten is the only candidate passing all profile, battle-duration, event-rate, and recovery gates. 4. **Profession diversity:** each base branch pair and hidden hybrid has opposed fixtures; no identity leads both without a different Company/order cost. 5. **Equipment/Artifact diversity:** every row changes two observable events; no price/tier creates strict catalog-wide superiority. 6. **Market diversity:** across five fixed run seeds and five profiles, at least three different first purchases, battle risks, and final orders are optimal. 7. **Failure pressure:** one death is consequential; three are recoverable; a full-company loss can close a run without making next-run Meta power required. 8. **Decision density:** exact traces reproduce their maximum gaps, and no battle/result handoff exceeds 15 real seconds after resolution at 1x. 9. **Campaign:** all profiles finish within 15-25 hours and mastery has new decision content through 60+ hours. ### 16. Difficulty Contracts Difficulty is chosen before run creation and stored for the entire run: | Difficulty | Enemy HP | Enemy damage/healing | Reward multiplier | Audience | |---|---:|---:|---:|---| | Wayfinder | 0.90x | 0.90x | 1.00x | learning and accessibility-forward play | | Standard | 1.00x | 1.00x | 1.00x | authored first-clear baseline | | Oathbound | 1.10x | 1.12x | 1.15x | prepared high-risk play | Multipliers apply once after enemy derived stats and once to battle Coin where declared. They do not change offer access, Recruit attribute budgets, XP, Renown, target rules, telegraph length, Replacement Credit, Line capacity, or save behavior. Fallen Recruits remain permanent on every difficulty. Postgame Oath laws are opt-in rule changes, not hidden difficulty multipliers. Each declares Market/formation/enemy/reward changes and its Record. Laws may not alter transaction integrity or reintroduce permanent Meta stats. ### 17. Fixed Economy Test Vectors | Vector | Inputs | Expected result | |---|---|---| | Capacity | cleared Rounds 0,2,4,6,8,10,12 | `4,5,6,7,8,9,10` | | Base hire | L=3, P=0 | 22 Coin list price | | Advanced hire | L=3, P=1 | 32 Coin list price | | Credit hire | list 22, Credit 19, use=true | 3 Coin, Credit becomes zero | | Item price | B=4, T=2 | `12+12+12=36` Coin | | Item sale | 36 Coin paid | 10 Coin | | Refresh | N=0/L=0; N=1/L=0; N=7/L=0 | 6, 9, 24 Coin | | Steady income | B=0, R=5, Standard | 28 Coin | | Region steady income | B=7, R=5, Standard | 42 Coin | | Elite income | B=0, R=5, Oathbound | `floor((18+10+14)*1.15)=48` Coin | | Level XP | L=4 | 60 XP to level 5 | | Battle XP | R=5, Q=2 | 28 XP to living deployed winner | | Death Credit | original list 22, paid 18 | 19 Credit | | Dismissal | paid 32, survived 3 | 8 Coin; no Credit | | Final dismissal | one living Recruit, paid 32, survived 3, Coin 3 | reject `FINAL_LIVE_RECRUIT`; Coin remains 3, no rebate/offer/roster change | | Solvency | any B; start plus 12 steady wins minus baseline | 79 Coin | | Decision gaps | five Section 13 traces | 105, 105, 115, 165, 145 seconds | | Capacity candidate | C=10 | 5/5 prep, 106 s p95, 3.60 events/s, one-Market recovery | ### 18. Acceptance Checklist - [ ] Market board, offer levels, prices, refresh, lock, purchase, sale, and reward formulas are complete. - [ ] Coin, Credit, XP, Renown, and progression facts have explicit persistence, sources, sinks, caps, and non-power boundaries. - [ ] Guild Charter preview/claim/retry uses existing Renown, the declared cost ranges, exactly-once receipts, and no permanent raw power. - [ ] Death recovery is affordable without making dismissal/death profitable. - [ ] The dismissal rebate is unreachable when the target is the final living Recruit; abandonment and casualty recovery remain separate. - [ ] Capacity ten follows a declared five-profile analytical selection. - [ ] Five exact Market/battle/decision traces and campaign budgets meet 15-25 first-clear and 60+ mastery targets. - [ ] Solvency and anti-dominance gates cover refresh, hire, dismiss, replace, and risk policies. - [ ] All fixed content counts and no-filler requirements match the other authorities. - [ ] Both final-campaign choices settle identical earned economy receipts, archive the Company, and differ only in destination/postgame eligibility. ## Aetherbound Guild: Save And Failure Contract > Authority: versioned persistence, pending/applied operations, exactly-once > commit, retry, duplicate protection, deterministic battle resume, Recruit > death, dismissal, run failure, backup, corruption, migration, rollback, cloud > conflict, clock behavior, bounded offline work, delete, and recovery UX. > > Revision: recruit-line-design-r3 / 2026-08-11 > > [01_GAME_DESIGN.md](01_GAME_DESIGN.md) owns the player promise. > [02_GAMEPLAY_AND_BALANCE.md](02_GAMEPLAY_AND_BALANCE.md) owns battle state and casualty > predicates. [02_GAMEPLAY_AND_BALANCE.md](02_GAMEPLAY_AND_BALANCE.md) owns normal > prices, rewards, pacing, and difficulty multipliers. This document is final > authority for operation and gameplay-failure application. ### 1. Persistence Invariants 1. A confirmed operation applies exactly once or not at all. Cost, result, receipt, and final status are one committed state. 2. A durable `pending` row contains immutable intent and zero gameplay deltas. It can be safely finalized or rejected; it can never contain a spent cost. 3. Suspend, crash, power loss, retry, duplicate input, device change, or cloud transport cannot redraw a Market/reward, duplicate an item/Renown grant, reverse a valid casualty, or change a deterministic battle. 4. The newest valid local commit remains fully playable offline. Platform and cloud copies never become gameplay authority silently. 5. A Fallen Recruit never respawns in the same battle and never returns to the same run through Reserve substitution, reload, backup choice, rehearsal, migration, reward, promotion, difficulty, or clock manipulation. 6. Death removes the Recruit but returns exactly the Recruit's optional `equipped_item_id` to run inventory. Neither half of that result can commit alone; an empty slot returns nothing. 7. Offline gameplay advances by zero simulation ticks and grants zero Coin, XP, Renown, offers, healing, or progress. 8. Migration is copy-first, deterministic, sequential, and reversible until a later verified boundary. It never rerolls generated Recruit fields. 9. Corruption recovery identifies the exact verified boundary. If later irreversible run operations cannot be reconstructed, the run is sealed rather than resumed from a state that could reverse death or duplicate value. 10. Save, conflict, recovery, overwrite, abandon, dismissal, and delete flows support touch, mouse, keyboard, controller, localization, and accessibility. 11. A Run seed is reserved in a durable `run_creation_draft` before any opening Recruit is generated. At most one draft or `current_run` exists, and a draft can only become the `current_run` that carries that same seed. ### 2. Save Topology And Envelope The product supports three independent Guild slots. Each slot holds one active commit, four rotating verified backups, one run-start checkpoint, one latest Market checkpoint, one optional pre-migration copy, and redundant closure receipt ledgers. ```text profile_save profile_schema_version settings_revision, language, accessibility, input mappings Guild_slot_index[] platform_service_outbox (non-authoritative, bounded) Guild_slot Guild_id, lineage_id, slot_id save_schema_version, ruleset_version, content_revision commit_id, parent_commit_id, commit_sequence generation_root_seed, next_run_ordinal Region/Contract progress, Renown, unlocks, Records, discoveries run_creation_draft or null current_run or null operation_journal, compact_applied_ids closure_receipt_head, run_creation_receipt_head payload_sha256, envelope_crc32 run_creation_draft draft_id, run_id, Contract, difficulty, status seed_ordinal, run_seed, source_commit_id ruleset_version, content_revision, opening_role_weight_snapshot opening_offers[0..3] or empty, opening_offer_set_hash or null selected_offer_ids[2] or empty, selection_revision draft_hash, run_creation_receipt_head current_run run_id, Contract, difficulty, run_seed, status Market/cleared-Round/boss state Coin, Replacement Credit, capacity, offers, locks, refresh counters living Recruits, Reserve, inventory, Artifacts encounter or null, pending outcome/reward or null hired/fallen/dismissed totals ``` IDs and seeds are 128-bit values rendered as lowercase hexadecimal. Commit sequence is a local monotonic unsigned integer. CRC32 catches incomplete media writes; SHA-256 covers canonical payload bytes. Checksums are integrity tools, not online signatures or anti-cheat requirements. `run_creation_draft` and `current_run` are mutually exclusive. A draft with status `seed_reserved` has an empty offer array and selection. `offers_ready` has exactly four complete offers and no accepted pair; `selection_ready` has the same four offers and exactly two distinct selected IDs. No state may serialize a partial offer array, one selected ID, or a draft whose seed ordinal is not less than `next_run_ordinal`. Wall-clock fields may be stored for display and diagnostics only. They cannot select conflict winners or calculate gameplay. ### 3. Versioning And Compatibility | Field | Changes when | Compatibility rule | |---|---|---| | `profile_schema_version` | settings/slot index layout changes | profile-only ordered migration | | `save_schema_version` | Guild/run/operation serialization changes | sequential copy migration required | | `ruleset_version` | combat, target, price, failure, or progression formula changes | committed battle finishes under stored version | | `content_revision` | stable catalog row or localization data changes | stable-ID mapping or explicit legacy handling | The current schema and previous three shipped schemas must have tested adjacent migrations. Older schemas may have a longer supported chain; absence of a chain blocks that slot with export/recovery options and never authorizes reset. A run-creation draft, battle, reward draft, Market board, or outcome already committed stays on its stored ruleset/content snapshot. A new ruleset becomes active only before seed reservation or a new Market is generated, after all prior result operations are finalized. It cannot rematerialize an existing opening four. No shipped gameplay save exists during this design-only stage. These rules bind all later prototype and production schemas and do not imply a current runtime migration obligation. ### 4. Operation Identity And Status Every state-changing action has: ```text operation_id = hash(Guild_id, lineage_id, commit_sequence_at_intent, operation_kind, source_stable_id, local_nonce) intent_hash = sha256(canonical_operation_inputs) status: pending | applied | rejected ``` The journal row stores: ```text operation_id, operation_kind, intent_hash, status pre_commit_id, result_commit_id cost_delta, result_delta, rejection_reason run_id, Market_index, encounter_id, simulation_tick as applicable receipt_hash, previous_closure_receipt_hash as applicable ``` Rules for duplicate IDs: - same `operation_id` and same `intent_hash`: return stored pending status, applied receipt, or rejection without creating a new operation; - same ID and different hash: reject `OPERATION_ID_CONFLICT`, applying nothing; - new ID: validate and enter the transaction procedure below. Applied IDs remain in the full journal through run close. They then compact into an immutable membership set retained for the Guild lineage. Receipt-bearing casualty, reward, boss-clear, Renown, run-close, migration, and delete operations remain in the redundant closure ledger until the Guild slot is deleted. The detailed journal is bounded to 4,096 rows. At a Market with no pending operation, reaching 3,584 rows compacts the oldest finalized non-closure rows into sorted exact-ID segments containing operation ID, intent hash, final status, and receipt hash. The newest 512 detailed rows and every closure receipt remain expanded. Lookup checks exact segments before accepting a new ID; probabilistic membership is forbidden because a false match could reject a valid purchase or hide a duplicate. ### 5. Pending-To-Applied Transaction Procedure Every durable transaction uses these steps: 1. Look up ID/hash before current-state validation and return any existing row. 2. Validate the active commit, legal phase, referenced IDs, target, and intent. 3. Build a candidate child commit containing a `pending` row with the complete immutable intent and **zero** `cost_delta`/`result_delta`. 4. Validate, write, flush, atomically point to, and read back that pending child. 5. From the pending intent and unchanged parent facts, compute the complete cost and result. No new random draw is allowed; generated outputs were fixed in intent or derive from stored labeled seeds. 6. Build one child that replaces `pending` with `applied`, includes all cost and result deltas, receipt, and closure link when required. 7. Validate schema, nonnegative resources, unique ownership, Recruit/equipment consistency, Market lineage, battle hashes, and operation transition. 8. Serialize to a new file, write integrity values, flush file and directory, atomically replace the active pointer, then read back. 9. Rotate backups only after the applied child reads back and validates. A precondition failure after step 3 produces a `rejected` child with zero deltas and one reason. It cannot return to pending. Presentation, sound, achievement, cloud upload, and screen transition occur only after step 9. #### 5.1 Crash And Retry Boundaries | Crash point | Reachable active state | Recovery/retry | |---|---|---| | Before pending pointer switch | Parent only | retry creates same intent; no cost exists | | After pending switch | Pending intent, zero deltas | deterministic finalize or reject once | | During applied pointer switch | Pending or complete applied child | validate selected pointer; finalize or return receipt | | After applied switch, before backup rotation | Complete applied child | return stored receipt; never reapply | | During backup/closure replication | Applied active plus older replicas | repair replicas from active receipt; no gameplay replay | Recovery may finalize a pending buy, casualty, reward, or run-close operation only from its fixed intent. It never asks the player to redraw or reconfirm a result whose confirm was already durably recorded. A pending destructive action that lacks a valid target after recovery becomes rejected with no deltas. ### 6. Transaction Boundaries | Action | Pending intent contains | Applied child contains | |---|---|---| | Begin run creation | Contract, difficulty, expected `next_run_ordinal`, derived draft/run IDs and seed, version/role-weight snapshot | one `seed_reserved` draft and ordinal increment; no offers or `current_run` | | Materialize opening offers | draft ID/hash, run seed hash, versions, expected empty offer set | all four indexed offer records/IDs/output hashes and one offer-set hash | | Set opening selection | draft ID/hash, offer-set hash, expected selection revision, exactly two distinct offer IDs | same four offers, canonical selected pair, revision increment, receipt | | Commit run creation | draft ID/hash, offer-set hash, selection revision, exact pair and output hashes | draft removed; same run ID/seed and selected Recruit records in one new `current_run`; opening Coin/capacity and run-start receipt | | Buy Recruit | offer ID, recruit output hash, Credit choice, expected price | Coin/Credit cost, offer removal, Recruit ownership | | Buy/sell equipment | offer/item ID and expected receipt | Coin delta and exactly one ownership change | | Lock/refresh | Market hash, selected locks, expected cost | Coin cost, counters, complete fixed offer board | | Equip/reorder | Recruit, candidate item, expected prior item or null, and/or order IDs | one-slot replacement receipt, complete legal inventory and Party-line state | | Promote | Recruit, old/new Profession, eligibility proof | one Profession replacement and derived-state refresh | | Dismiss | Recruit, optional equipped item ID, rebate preview, expected `live_recruit_count` | Recruit removal, optional item return, Coin rebate, post-count at least one | | Commit battle | battle offer, lineup, stats, seed, risk | immutable encounter start snapshot | | Start retreat | encounter, accepted tick | one retreat timestamp; no duplicate start | | Lock outcome | objective and final state hashes | immutable victory/defeat/timeout/retreat result | | Apply casualties | exact Recruit/optional-item/Credit set | all Recruit removals, all present item returns, all Credit grants | | Claim reward | fixed draft/card/disposition | one reward and draft removal | | Close run | terminal cause and persistent grants | Coin/Credit clear, run result, Records/Renown once | | Change difficulty/law | Guild-only selected rule set | next-run configuration only | An operation cannot use a presentation animation as a commit boundary. A double-tap, key repeat, controller repeat, OS lifecycle retry, or cloud retry returns the same status/receipt. ### 7. Run Creation, Market, And Round Save Points #### 7.1 Seed-First Run Creation `Begin run creation` derives values without an ambient RNG or wall clock: ```text seed_ordinal = next_run_ordinal run_seed = low128(sha256(generation_root_seed || lineage_id || "run-seed" || u64(seed_ordinal))) draft_id = low128(sha256(run_seed || "run-creation-draft")) run_id = low128(sha256(run_seed || "run-id")) ``` Its pending intent fixes the chosen Contract/difficulty and generation snapshot but generates no Recruit. Its applied child creates the `seed_reserved` draft, increments `next_run_ordinal` once, mirrors a seed-reservation receipt into both closure ledgers, and is flushed, pointed to, and read back before the opening generator may run. A retry from the unchanged parent derives the same ordinal and seed. Once a draft exists, a new begin request returns `RUN_CREATION_DRAFT_ACTIVE` and that draft; it cannot consume another ordinal. If `current_run` exists, begin returns `RUN_ALREADY_ACTIVE` and applies nothing. `Materialize opening offers` uses only the read-back draft and the content authority's fixed mappings for indices `0..3`. One applied child stores all four complete Recruit records, offer IDs, output hashes, and their canonical offer-set hash. A missing index, duplicate ID, output-hash mismatch, changed generation snapshot, or any fifth offer rejects with zero deltas and leaves the same reserved seed. The materialization receipt is mirrored redundantly and is sufficient to regenerate and verify the same four records. The UI may hold a zero- or one-card highlight transiently, but the durable `Set opening selection` operation accepts only a canonical unordered pair of two distinct IDs from the saved four. A different legal pair replaces the prior pair and increments `selection_revision`; repeating the same operation ID/hash returns its original receipt. A new operation requesting the already accepted pair returns `SELECTION_UNCHANGED` and that receipt without a commit. The player may revise the pair until Run commit without regenerating an offer. Back or Cancel exits the view only; it does not discard the draft, change its Contract/difficulty, consume an ordinal, or expose a refresh action. Save and Quit, suspension, process restart, locale/timezone change, and wall-clock rollback reopen the same four offers and latest durable pair. No player-facing action allocates a replacement draft while one exists. `Commit run creation` revalidates the draft ID/hash, offer-set hash, exact selection revision, pair, and both selected output hashes. Its applied child is one atomic state: it removes the draft, creates `current_run` with the same `run_id` and `run_seed`, transfers the two unchanged Recruit records, establishes 52 Coin and Line capacity four, and writes the run-start checkpoint and receipt. There is no intermediate state with both objects or neither object. A request for a stale draft/revision returns `STALE_RUN_CREATION_DRAFT` plus the current draft summary and applies nothing. A retry naming an already promoted draft and matching its commit receipt returns `RUN_CREATION_ALREADY_APPLIED` plus the original receipt; a conflicting pair/hash is rejected. Neither path generates offers or creates a second Run. The Run-creation commit receipt is indexed by both `operation_id` and `draft_id`. Therefore a duplicate confirm with the original ID and a recovery retry that acquired a new operation ID both resolve to the one applied receipt when their draft/pair/hash intent matches. A reused `draft_id` with different intent returns `RUN_CREATION_COMMIT_CONFLICT` and cannot reach the generic new-ID path. ##### Run-Creation Crash And Retry Matrix | Durable boundary | Reachable state after recovery | Exact retry result | |---|---|---| | Before begin-pending pointer | parent, no draft, unchanged ordinal | derive the same ordinal/seed and retry | | After begin-pending pointer | fixed seed intent, zero deltas | finalize the same `seed_reserved` draft once | | After seed-reservation pointer/read-back | `seed_reserved`, no offers | materialize indices `0..3` from that seed | | Before/during materialization pointer | seed-only or one complete four-offer child | validate pointer; regenerate same four or return receipt | | After materialization pointer | `offers_ready`, complete saved four | reopen exact four; no generator call on normal load | | Before/during selection pointer | prior pair or one complete revised pair | validate pointer; finalize pair or return its receipt | | After selection pointer | `selection_ready` with exact pair/revision | reopen same pair; later revision remains legal | | Before/during Run-commit pointer | complete draft or complete `current_run` | finalize from pending intent or return original commit receipt | | After Run-commit pointer, before replica rotation | `current_run`, no draft | repair replicas; never recreate draft or transfer twice | Every row uses the generic pending-to-applied procedure in Section 5. A corrupt candidate is never partially merged with its parent. #### 7.2 Market, Round, And Run Save Points Safe commits occur after: - run-seed reservation, complete opening-offer materialization, each accepted two-Recruit selection revision, and atomic Run creation; - Market generation, lock, refresh, buy, sell, equip, reorder, promote, and dismissal; - battle offer commit and countdown start; - accepted retreat start; - encounter outcome lock; - casualty application; - reward claim or failure application; - capacity increase, boss Muster, boss result, and run close. `Save and Quit` completes the current tick/transaction and points to the same active commit. It does not create a selectable branch or reroll point. Loading a Market returns the exact offers, locks, refresh counter, Coin, Credit, Company, Reserve, inventory, and order. Failed attempts increment `Market_index` but not `cleared_rounds`. The next Market still prepares the same required Round number with a new precommitted board from the run seed. A boss failure reopens boss Muster with the same fixed boss and newly derived Recruit/equipment offers. This progression cannot be reset by closing or restoring a player-selectable save. ### 8. Battle Interruption And Deterministic Resume An encounter snapshot stores: ```text encounter_id, ruleset_version, content_revision, root_seed simulation_tick and per-label draw counters ordered actor IDs/footprints, fixed-point HP/stats/resources/readiness casts, projectiles, movement intents, summons, statuses, barriers, cooldowns objective/phase/Overtime/retreat state automatic event journal and accepted lifecycle commands snapshot_hash, previous_snapshot_hash ``` The game writes a resumable snapshot every ten ticks, at every accepted retreat command, after every Fallen/collapse batch, and at outcome lock. On normal suspend it completes the current priority batch before acknowledging suspend. If killed earlier, recovery: 1. loads the newest valid encounter snapshot; 2. replays deterministic automatic events and accepted lifecycle commands from the previous valid hash to the last journaled tick; 3. verifies all labeled draw counters and state hashes; 4. resumes at the first unprocessed priority of the next tick. No wall time is substituted. A week-long suspend resumes the same tick. Camera, animation, particles, and audio may restart; authoritative events may not. If all encounter snapshots are corrupt but the committed battle start and event journal validate, replay from countdown using the same seed and retreat tick. If replay hash diverges, seal the run as `recovery_incomplete` under Section 12; never offer a fresh seed or pre-battle edit after observed casualties. ### 9. Recruit Death, Equipment Return, And Dismissal #### 9.1 Casualty Settlement Fallen state exists in battle snapshots as soon as the death batch resolves. Run ownership changes only in the casualty settlement after outcome lock. The pending intent lists, for every casualty: ```text recruit_id, final Profession/level/XP/Trait/history hash equipped_item_id or null original list price, Coin paid, computed Credit grant death tick and causal event ID ``` Applied settlement must satisfy: ```text all casualty Recruit IDs absent from living Company and Reserve every non-null casualty equipped_item_id present exactly once in run inventory Replacement Credit equals the capped sum fallen total increases by exact casualty count no non-casualty Recruit or item changes ownership ``` If any condition fails, the candidate is rejected and the outcome remains locked pending recovery. The game cannot enter the next Market with a partial casualty result. Casualties apply on victory, defeat, timeout, and retreat. A same-batch mutual defeat does not preserve either Fallen Recruit. Rehearsal simulations create no operation and cannot affect ownership. #### 9.2 Dismissal Dismissal is an explicit destructive operation from a Market. The pending review shows generated name, Profession, Trait, level, survival history, returned equipment, Coin rebate, resulting deployable footprint, and no Credit grant. Default focus is cancel. Both preview and commit use the product authority's canonical count: ```text live_recruit_count = count(unique Recruit IDs owned by the current run whose state is living, across deployed party and Reserve) dismissal_legal = Market_open and target_is_living and live_recruit_count >= 2 ``` Dismissal is rejected for a Recruit referenced by a committed battle, pending promotion, pending casualty settlement, or another dismissal. It is also rejected as `FINAL_LIVE_RECRUIT` when the canonical count is one. Preview rejection creates no operation ID, pending row, or save mutation. A crafted or stale confirm is revalidated before a pending gameplay operation can apply. Its `FINAL_LIVE_RECRUIT` response has zero cost/result deltas: no Recruit or equipment moves, no Coin rebate, no Credit, no protected recovery offer, no dismissed-total change, and no commit-sequence advance. The implementation may retain only the rejected intent response keyed by operation ID and intent hash so duplicate confirms return the same response; this is not an applied/pending gameplay receipt and cannot later become legal after the Company changes. A pending dismissal recovered after interruption stores its parent commit and expected count. Before transition to applied, it must prove the active parent is unchanged, pre-count is at least two, and post-count is exactly pre-count minus one and at least one. Otherwise it becomes the same zero-mutation rejected intent response. A successfully applied dismissal returns its original receipt on duplicate confirm and cannot remove another Recruit or pay a second rebate. Explicit `Abandon Run` is a separate run-close operation; it does not reuse a dismissal ID or pay a rebate. Casualty settlement is also separate and remains the only path by which a final Recruit's death can create Credit, a protected offer, recovery viability evaluation, or Company collapse. #### 9.3 No Resurrection Boundary Applied casualty receipts are closure receipts. An older backup that predates a casualty can become active only after the receipt chain deterministically replays through that casualty or after the affected run is sealed. A recovery UI must never present "continue run" from an older state containing a Recruit whose later valid casualty receipt is known. ### 10. Duplicate Purchase, Reward, And Persistent Grant Protection UI debounce is optional convenience; operation IDs are authority. For purchase: ```text if operation applied: return stored Recruit/item and receipt if pending: finalize same fixed offer and price if offer absent under a new operation ID: reject OFFER_ALREADY_CONSUMED ``` For reward: ```text verify card ID belongs to stored draft pending contains exact selected card and replacement choice if required applied removes draft and adds one item/Artifact/Coin result ``` For Renown, clear, and discovery facts, the stable grant ID is derived from Guild ID plus objective/content ID. A repeated boss outcome or platform retry finds the existing applied ID and grants nothing again. Optional platform achievements derive from applied Records. The outbox holds at most 100 idempotent events. When full, older events are regenerated from Records rather than blocking play or changing gameplay resources. ### 11. Backup, Corruption, And Closure Receipts #### 11.1 Backup Set Each Guild slot stores: - `active`: newest validated commit; - `backup_1..4`: distinct prior verified transaction boundaries; - `run_creation`: latest verified seed/offers/selection draft boundary until atomic Run commit; - `run_start`: current run creation commit until run close; - `Market_checkpoint`: latest Market-open commit; - `pre_migration`: source bytes before the latest migration; - `closure_A` and `closure_B`: alternating append-only closure receipt ledgers; - `quarantine`: corrupt bytes and diagnostics, never auto-deleted. Backups rotate only after active read-back. Storage pressure removes diagnostic logs before any active, closure, run-creation, run-start, Market, or pre-migration copy. Seed reservation, offer materialization, selection revision, and Run commit receipts are mirrored into both closure ledgers under `run_creation_receipt_head`. Older selection receipts may compact only after an exact-ID segment and the latest complete pair/revision snapshot are retained. #### 11.2 Validation Order 1. envelope parse and size bounds; 2. CRC32 and SHA-256; 3. schema and required fields; 4. Guild/lineage/parent/sequence links; 5. operation status transitions and receipt chain; 6. nonnegative Coin/Credit/Renown and cap checks; 7. Recruit uniqueness, generated output hashes, and Profession topology; 8. equipment ownership uniqueness and equip references; 9. run-creation seed ordinal, draft/current-run exclusivity, indexed opening offer hashes, and selection revision; 10. Market seed ancestry, offers, locks, and counters; 11. encounter snapshot, event journal, draw counters, and outcome; 12. persistent clear/discovery IDs and run-close consistency. A settings error falls back to defaults without touching gameplay. Optional cloud/platform failure never labels a local save corrupt. #### 11.3 Recovery Algorithm 1. Validate active, then backups newest to oldest. 2. Validate both closure ledgers and choose the longest common valid chain. 3. Select the newest valid gameplay commit whose ancestry matches the slot. 4. Before Run commit, reconstruct a draft only from a valid seed-reservation receipt plus a complete matching receipt chain. Regenerate the four offers and verify their saved hashes, then restore the latest complete pair/revision. 5. After a Run-commit receipt exists, never reconstruct its former draft. Recover the matching `current_run`, or seal it if the full transferred state cannot be verified. 6. Replay later closure receipts only when parent/result hashes form a complete chain and each result validates. 7. If the chain reconstructs the newer state, write a recovered child and continue normally. 8. If a missing/corrupt gap crosses a Run commit, casualty, reward, boss clear, Renown grant, or run close, restore persistent Guild state only through the verified boundary and seal the current run as `recovery_incomplete`. 9. If no active, backup, draft checkpoint, or redundant receipt proves the reserved seed, mark the slot `creation_recovery_blocked`; do not advance the ordinal, allocate another seed, or offer a playable branch. Export and the existing explicit Guild-slot delete/reset recovery remain available. 10. Preserve all rejected bytes in quarantine and write a diagnostic manifest. Sealing clears run-only Coin/Credit and prevents reward or casualty farming. Recovered persistent facts are never guessed beyond the last verified receipt. The UI states the boundary and any unverifiable operations; it never claims full preservation without matching hashes. ### 12. Failure State Model And Consequences Failure is classified before one operation calculates consequences: | Kind | Predicate | Casualties | Coin fee | Run transition | |---|---|---|---:|---| | Victory with losses | objective succeeds with one or more Fallen Recruits | Apply all | 0 | pay reward, next Market/boss/clear | | Encounter defeat | all deployed non-summons Fallen or objective failure before timeout | Apply all | difficulty table | no reward; recovery Market if viable | | Timeout defeat | objective incomplete at tick 1500 | Apply prior Fallen only | difficulty table | no reward; recovery Market if viable | | Voluntary retreat | withdrawal completes | Apply all Fallen before completion | difficulty table | no reward; recovery Market if viable | | Run abandonment | player confirms from Market/result | No new casualties | clear all run Coin/Credit | close run, no unearned boss grant | | Company collapse | no living Recruit and no affordable protected recovery hire | already applied | 0 additional | close run | | Process interruption | suspend/crash/power loss | none beyond deterministic replay | 0 | resume/reconstruct; not gameplay failure | | Save corruption | active data fails validation | none invented | 0 | recover or seal; not gameplay failure | Difficulty fees are the sole numeric failure-fee authority: | Difficulty | Encounter defeat | Timeout | Retreat | |---|---:|---:|---:| | Wayfinder | 0 Coin | `min(2,current Coin)` | `min(4,current Coin)` | | Standard | `min(2,current Coin)` | `min(4,current Coin)` | `min(6,current Coin)` | | Oathbound | `min(4,current Coin)` | `min(6,current Coin)` | `min(8,current Coin)` | Fee, casualty settlement, failure totals, consumed battle offer, and next-Market seed advance are one result transaction. Fees never make Coin negative and do not alter Credit. Retreat is therefore a controlled loss rather than a free way to cycle battle/Market offers. #### 12.1 Recovery Viability And Run Close After failure settlement: ```text can_continue = living_recruit_count > 0 or coin + replacement_credit >= protected_offer_list_price ``` If true, open a recovery Market using the same required cleared-Round number. If false, show Company collapse and close the run after confirmation/automatic receipt. Explicitly declining the only affordable protected offer recomputes the predicate and previews run close before confirm. This predicate runs only after casualty/failure settlement or protected-offer decline. Dismissal cannot reduce the canonical live count below one and cannot invoke this recovery/closure path. A player who wants to end a run while one or more Recruits live must use the separate `Abandon Run` transaction. Boss defeat follows the same rule. Cleared-Round count remains 12; boss Muster reopens if viable. No failure restores a consumed reward, dead Recruit, prior Market, or refresh counter. #### 12.2 Run Close Run close stores terminal cause, Company history, all casualties/dismissals, boss/clear facts, discoveries, and eligible Renown. It then clears run-only Coin, Credit, Recruits, inventory, Artifacts, Market, and encounter state. Survivors become nonplayable history Records. One operation applies closure and persistent grants; retry returns the same run result. ### 13. Migration Contract Migration runs only at startup or a Market with no pending operation. It never runs during countdown, battle, outcome, casualty settlement, reward selection, or run close. 1. Validate and copy source bytes to `pre_migration`. 2. Build an adjacent-version plan; skipping a required step is illegal. 3. Resolve stable content IDs and list legacy/missing rows. 4. Apply each pure deterministic migration to a copy. 5. Preserve generated name parts, rendered-name snapshot, appearance seed, attributes, Trait, Profession, level, and survival history for living Recruits; do not draw replacements. 6. Recompute derived stats from preserved source fields under the boundary rule. 7. Validate operation, ownership, Market, battle, and closure chains. 8. Write/read a new lineage child, then switch active pointer. 9. Preserve pre-migration bytes until two later valid Market commits and run close or 30 launches, whichever is later. A removed equipment/Artifact ID becomes a sealed legacy record with its stable ID and original ownership. At the next safe Market, the player chooses one of two deterministic same-band behavior replacements or leaves it sealed. A removed Profession keeps its stored ruleset for the current committed battle; afterward a deterministic parent-compatible replacement review is required. If migration fails, discard the candidate and leave the source active under its last supported ruleset where possible. Mark only that slot `migration_blocked` and offer details/export. Never reset, auto-sell, reroll, or auto-equip. ### 14. Local, Cloud, Multi-Device, And Rollback Cloud transports complete validated commits plus closure ledgers. It does not merge Coin, Recruits, equipment, offers, casualties, rewards, or operation rows. | Commit topology | Resolution | |---|---| | Identical commit | no action | | Local ancestor of cloud | offer verified cloud descendant; retain local backup | | Cloud ancestor of local | keep local; queue upload | | Different Guild/lineage | import only into an empty slot after validation | | Same lineage, divergent descendants | never merge; choose one active branch, archive the other read-only | Conflict comparison shows commit boundary, Region/Contract, Market/encounter, cleared Rounds, living/fallen counts, Renown, and closure receipt head. Wall clock is context only. Default is cancel/inspect. The unchosen divergent branch cannot be duplicated into a second playable slot, because that would duplicate generated offers and allow alternate casualty or reward outcomes. It remains exportable/read-only until explicitly deleted. A developer/support rollback follows the same recovery algorithm as corruption. It may activate an older commit only after replaying later valid closure receipts or sealing the affected run. No debug, platform, or user-facing path may resume an older branch that reverses a known applied casualty or reopens a known claimed reward. ### 15. Clock Rollback And Bounded Offline Behavior All gameplay time uses simulation ticks or monotonic in-session duration. Wall clock is display/diagnostic data. ```text wall_delta = current_wall_clock - last_seen_wall_clock if wall_delta < -300 seconds or wall_delta > 180 days: record CLOCK_ANOMALY change no gameplay state ``` While closed, the game advances exactly zero ticks and generates no Market, offer, Coin, Credit, XP, Renown, healing, promotion, unlock, enemy outcome, or reward. Return opens the saved state plus a compact recap. Background work is bounded: - at most one local save flush at a time; - at most three complete cloud payloads queued per Guild slot; - at most 100 idempotent platform events; - at most 30 seconds of best-effort upload after an explicit foreground save, cancellable without affecting the local commit; - no retry loop blocks exit, local play, or a new local commit. Changing clock, timezone, locale, sleep duration, or network availability cannot change generated names, offers, difficulty, results, or Records. ### 16. Confirmation, Overwrite, Delete, And Reset These actions require an effect review and a separate confirm: dismissal with history, promotion, Artifact replacement, protected recovery-offer decline that would close a run, run abandonment, difficulty/Oath-law change, cloud branch choice, migration fallback, Guild-slot overwrite, and Guild-slot delete. Delete moves the complete Guild slot and closure ledgers to recoverable local trash for seven successful launches or until explicit empty-trash confirmation. A profile-wide reset additionally requires selecting a displayed localized phrase in a second dialog; typing is not required. Default focus is cancel, and destructive actions cannot share a single repeated input with the opener. Every accepted confirm receives an operation ID. Repeating it returns the first receipt and cannot dismiss, grant, overwrite, close, or delete twice. ### 17. Accessibility, Localization, And Input Requirements - `Saving`, `Saved`, `Pending`, `Recovered`, `Sealed`, `Conflict`, and `Blocked` use text plus distinct icons, never color/spinner alone. - Closing during `Pending` is legal; recovery finalizes/rejects from intent. - Recovery and conflict dialogs support 130% UI scale, screen-reader order, complete touch path, keyboard/controller focus, and reduced motion. - Casualty review lists generated name, Profession, equipment returned, Credit, death tick, and first cause; it does not rely on animation or sound. - Technical IDs/hashes are hidden by default but available in details and an exportable diagnostic manifest. - Localized messages use semantic IDs and typed values, never string fragments. - Controller disconnect or focus loss pauses presentation and commits nothing until a new explicit confirm is accepted. - Haptic/audio feedback may acknowledge a save or casualty but cannot be the only state indication. ### 18. Required Recovery And Failure Matrix | Test | Fault/input | Expected invariant | |---|---|---| | Seed reservation crash | crash after begin-pending or applied pointer | same ordinal/seed; zero offers before applied draft read-back; one draft after retry | | Offer materialization crash | crash around four-offer pointer | seed-only draft or complete indices `0..3`; retry yields identical IDs/output hashes | | Selection revision crash | revise accepted pair and crash around pointer | prior complete pair or new complete pair with one revision/receipt; never one selected ID | | Run creation duplicate | repeat original ID or use a new ID naming the applied draft/pair | same original receipt, same seed/two Recruit records, no draft and no second Run | | Run creation stale draft | submit old draft hash or selection revision | `STALE_RUN_CREATION_DRAFT`, current summary returned, zero mutation | | Run creation cancel/restart | Cancel, Save and Quit, or process restart before commit | same draft, four offer IDs/hashes and latest durable pair; no new ordinal/seed | | Run draft clock rollback | wall clock moves back 24 hours before Run commit | diagnostic only; same draft/offers/pair and zero gameplay delta | | Run draft active corruption | invalid active checksum, intact draft checkpoint/backup | recover newest valid draft boundary and exact four/pair; no replacement seed | | Run draft replica corruption | active/backups invalid, redundant creation receipts intact | rebuild same seed/four/pair, or same committed Run if commit receipt exists | | Run draft total corruption | no valid primary, backup, checkpoint, or creation receipt | `creation_recovery_blocked`; quarantine/export, no new draft or free reroll | | Pending purchase | crash after pending pointer | zero cost until deterministic applied child; one Recruit after retry | | Applied purchase | duplicate same operation ID | one cost, one Recruit, same receipt | | Refresh crash | crash after Coin validation | old complete board or new complete board and cost; never mixed | | Legal dismiss duplicate | start with two live Recruits; repeat confirm | one Recruit removal, zero-or-one item return, one rebate; final live Recruit remains | | Final dismiss preview | one live Recruit, low Coin, no protected offer | `FINAL_LIVE_RECRUIT`; no operation ID or mutation; `Abandon Run` remains separate | | Stale final dismiss | preview at two, another serialized dismissal leaves one, submit old confirm | zero-delta `FINAL_LIVE_RECRUIT`; no rebate, protected offer, or count change | | Interrupted final dismiss | recover pending intent against active count one | reject without apply/receipt beyond rejected intent response; one Recruit remains | | Battle suspend | suspend during projectile at tick 417 | identical next event/draw counters/final hash | | Death snapshot | crash one tick after front Recruit falls | replay contains same death and collapse | | Outcome crash | crash before casualty settlement | locked result reopens; settlement applies exact set once | | Casualty partial candidate | omit the non-null equipped item in candidate | validation rejects; no Recruit removal/Credit commits | | Reward duplicate | double-tap selected card | one item/Artifact/Coin result and draft removal | | Boss grant duplicate | replay same boss-clear result | one clear fact and Renown grant | | Three deaths | fixed economy fixture | Recruits removed, all equipment returned, 54 Credit capped | | Standard retreat | 10 Coin at/after tick 70 | 6 Coin fee, all earlier casualties apply, no reward | | Wayfinder timeout | 1 Coin at tick 1500 | 1 Coin fee, living Recruits survive, no reward | | Company collapse | zero living, 9 Coin+Credit, protected price 14 | run closes; no free Recruit invented | | Recoverable company | zero living, 14 Coin+Credit, protected price 14 | recovery Market opens; purchase still requires confirm | | Clock rollback | wall clock moves back 24 hours | diagnostic only; zero gameplay delta | | Thirty-day offline | close mid-run and return | zero tick/resource/offer progress; exact recap | | Active corruption | invalid active checksum, intact receipts/backups | reconstruct newest valid chain or seal run at stated boundary | | Casualty receipt beyond backup | selected backup contains later-Fallen Recruit | replay casualty or seal run; never resume with Recruit | | All battle snapshots corrupt | valid start/journal remains | replay same seed/retreat tick or seal on hash divergence | | Migration failure | stable-ID mapping invalid | source stays active; candidate discarded; export offered | | Cloud divergence | same lineage, different descendants | one chosen active, other read-only; no merge/duplicate slot | | Run-close retry | crash after persistent grants before screen transition | same result, Coin/Credit remain cleared, no duplicate Renown | ### 19. Acceptance Checklist - [ ] Schema, ruleset, content, lineage, commit, and operation versions are separate and migration is copy-first. - [ ] Pending/applied/rejected operations preserve zero-delta pending and atomic cost/result receipts. - [ ] Run creation durably reserves one seed before offer generation, stores an all-or-nothing indexed four, receipts revisable exact-pair selection, and promotes that same seed and pair into `current_run` exactly once. - [ ] Market, battle, casualty, reward, and run-close retries are idempotent. - [ ] Battle suspend/crash reproduces deterministic state or seals the run on an unverifiable divergence. - [ ] Death, equipment return, Credit, dismissal, replacement, defeat, timeout, retreat, and Company collapse are explicit and testable. - [ ] Preview, stale confirm, duplicate confirm, and interruption cannot dismiss the final living Recruit or route dismissal through casualty recovery. - [ ] Backups, closure receipts, corruption, migration, rollback, and cloud conflicts cannot knowingly reverse casualties or duplicate rewards. - [ ] Clock rollback and bounded offline behavior produce zero gameplay progress. - [ ] Confirmation, delete, accessibility, localization, and input rules cover every destructive and recovery state.