Update 2.123
6/16/2026
v2.123.0.0BETAMINOR
Wakka
Arena+ Multi Dark Aeon progress sidecar + reader/writer in FfxHooksDll
- (a) new sidecar
mods/Spira Reforge/arena/progress/spira-arena-progress.{json,schema.json}(dossier sec. 15 schema v1) withflags{}cleared/first_clear_utc/last_clear_utc/clear_count/evidence + optionaltier_lock_state{}(LOCKED/READY/CLEARED); keyed byprogress_flagfrom the catalog (arena.dark.<slug>); README documents usage rules and catalog<->sidecar mapping. (b) New moduleRuntimeTools/FfxHooksDll/hooks/ArenaProgressSidecar.{h,cpp}— best-effort JSON reader/writer (no deps),ArenaProgress_Initialize/IsRowCleared/RecordClearedgated byarena_plus_progress.flag(default off), searches$FFXHOOKS_ARENAPLUS_PROGRESS_PATH-><DllDir>/mods/Spira Reforge/arena/progress/...-> fallback<DllDir>/spira-arena-progress.json. Atomic persistence via.tmp + MoveFileEx. EnvFFXHOOKS_ARENAPLUS_FAKE_CLEAR=flag1,flag2lets devs seed flags manually for UI testing. (c)dllmain.cppcallsArenaProgress_InitializeinInstallHooksafter the catalog overlay. (d) Real victory detection is still NOT wired — kept as a documented TODO; Fase 6 of the plan acknowledges this split, and the public APIArenaProgress_RecordCleared(flag, note)is ready for a futurebattleEndhook consumer. PolyHook build PASS 10/10 cpp. In-game RT2 Needs Test (viaFFXHOOKS_ARENAPLUS_FAKE_CLEAR)
v2.122.0.1
v2.123.0.1BETAREVISION
Wakka
Arena+ Multi Dark Aeon: penta stretch recipe + dry-run PASS
- (recipe/docs, no shipped behavior change). Plan Fase 7 (stretch). New
RuntimeTools/ArenaMultiBossLab/recipes/dark_penta_elemental_five.json+ recipe docmods/Spira Reforge/arena/recipes/dark_penta_elemental_five.mdcoveringDark Valefor + Dark Ifrit + Dark Ixion + Dark Shiva + Dark Bahamutonnagi05_70(Dark Yojimbo alias, 5 of 6 vanilla monPos, slot 5 unused). PipelineArenaMultiBossLab --recipe dark_penta_elemental_five --dry-runPASS againstnagi05_70.bin.spiraforge.bak: chunk2 = 5 actors @ 0x18A4 (16 bytes), chunk3 = 6 monLive @ 0x1B04 (96 bytes, position-only), re-read confirms slots. Catalog rowdark-penta-elemental-fiveupdated: id renamed,token_modeblocked->alias(alias is technically legitimate),evidencenotes dry-run PASS,rt2_statusstaysblocked(no in-game proof) — only RT0 byte-safety proved. Does NOT promote penta to a feature: stays stretch until quartet RT2 PASS + documented in-game attempt via_RT2_CHECKLIST.md. 4-way promotion plan (PASS / blocked-by-camera / blocked-by-ai / blocked-by-crash) in the recipe MD
v2.123.0.0
v2.123.0.2BETAREVISION
Lulu
Spira Reforge: Capture Cascade Phase A lockdown — 8 decisions locked + 3 prep artifacts
- (design/doc/schema, no code). Halyson planning session 2026-06-16 closed all 8 open decisions from §7 of the Capture Cascade doc (
v2.122.0.1): D1 Magus Sisters → Mushroom Rock Road (not Gagazet — perverse nostalgia for Operation Mi'ihen + 3 tragic fayths, a mid-early area that flips to T7 endgame); D2 Bestiary F7 → dedicated tab + post-battle popup, with a slot for GPT-generated art per captured DA; D3 patrol non-fleeable; D4 drops = 1× themed shard + 1× rare consumable; D5 capture counts as kill++ (unlocks vanilla 1v1 AND SIN ladder); D6 no confirmation prompt; D7 safe-zone respected by both T7 mobs and the DA patrol; D8 buff announced only on first entry post-capture. Phase A delivers 3 artifacts: (a) sidecar schemamods/Spira Reforge/save-schemas/spira-reforge-flags.schema.jsonv1 (DA captures +sin_mode.region_overrides+conquistas_seen+capture_cascade.patrol_kills/first_entry_seen— de-conflicted with Jarvis-ARENA'sspira-arena-progress.jsonsidecar fromv2.123.0.0, which owns arena row clears); (b) region mapmods/Spira Reforge/arena/dark-aeon-region-map.json(8 DA → canonical area + patrol_subzones + safe_zones + narrative notes); (c) Phase B RE spike plandocs/reverse/FFX_SPIRA_REFORGE_CAPTURE_BIT_M_HEADER_RE_PLAN_2026-06-16.md(1–2h playbook to locate thecapturablebit inm###header via hex diff + optional IDA). Master doc updated §7 (lockdown) + §4 (final map) + §13 (artifact refs). VISION_AND_ROADMAP §11 got a "Phase A artifacts" block. 4-phase plan defined (A=lockdown done, B=RE spike in a separate chat, C=Cap-1 writer in v0.5, D=RT2 pilot)
v2.123.0.1
v2.123.1.0BETAPATCH
Lulu
Ronso Mana: Overdrive re-arm fix (bug #2) + 2nd-pass command-ring RE
- (fixes a runtime-hook behavior bug + RE/docs). Bug #2 ("Ronso Rage won't re-select going left after one use"):
RonsoManaHook.cpplowered the OD display gate fromgateMin=100(vanilla "full bar") to 40 (=kRonsoSkillCosts[0], the Overdrive Jump cost). With the gate at 100, after a single partial use (drain 40 → charge 60 < 100) every forcing functionreturned early and OD vanished until the bar refilled to 100 — contradicting the 0–255 partial pool itself. Per-row greyout (G3) still blocks unaffordable skills (cost > current charge), so lowering the gate is safe. Install banner fixedhudSafe=19→hudSafe=21(the log printed the wrong version, hampering diagnosis). 2nd-pass RE (after RT2hudSafe=20FAIL): full decompile of79BB70/79B500/7B6BD0/79AD40/7A07D0/797D60+ an offlinecommand.bindump proved: (a) the runtime command row = 0x14 header + file struct (anchorbyte[25]=CharacterUser=file+5), sobyte[22]=MenuFlgs etc; (b) cmd282 (Ronso Rage) IS the OD ring header (MenuFlgs=0x11→header,MainMenu=True,ODCat=19,MenuLeft) — the old "282→leaf cat4 +296" reading was wrong; (c) in79BB70loop-2, a header withMisc2 MenuLeft (0x10)→dword[28]&0x1000→ lands in BSS array +40, NOT +0 (visible headers) — which is why forcing 282 available never shows it in the middle ring; (d)resolve=-1is a red herring (the main ring shows even with -1); (e)797D60 case 3reads a per-actor blob (actor+0xF7C); (f)79B500writesactor[0x590]=save[+16]early — our forcing inRefreshMenu_Shim(Prepare before the trampoline) is overwritten/wiped by that store → explains why replicating the save-edit failed..i64renames:7B6BD0→FFX_Btl_UI_BuildOverdriveTargetList,79B500→FFX_Btl_RefreshActorMenuState(+ comments on79BB70/797D60/79B500). Doc:docs/reverse/FFX_RONSO_MANA_COMMAND_RING_PIPELINE_RE_2026-06-16.md§8. Next step (bug #1): a save-edited-vs-forced capture experiment to diff the exact delta. Fix #2 RT2 Needs Testing
v2.123.0.2
v2.123.1.1BETAREVISION
Lulu
Spira Reforge: Capture Cascade Phase B handoff prompt (RE spike for the `capturable` bit)
- (handoff doc, no code). New
docs/ai/PROMPT_JARVIS_CAPTURE_BIT_M_HEADER_RE_SPIKE_2026-06-16.md— complete prompt to spin up a dedicated chat for Capture Cascade Phase B. Lane identity: Jarvis-CAPTURE-RE. Mission: locate offset+bitcapturablein them###.binheader via hex diff (Sinscale ↔ Dark Valefor + 2 validation samples) + optional IDACanCapturecross-check. Deliverables: ≥4-row evidence table + RESULT doc + plan-doc update + master Cap Cascade doc update + PORT_STATUS + its own REVISION bump. Non-goals explicit (does NOT implement writer, does NOT touch runtime, does NOT capture in-game). Honest estimate 1.5–2h. Unblocks Cap-1 (Phase C, v0.5)
v2.123.1.0
v2.123.1.2BETAREVISION
Lulu
Spira Reforge: Capture Cascade dual naming convention (internal codename + player-facing brand)
- (design/doc, no code). Halyson locked 2026-06-16: the feature keeps two names with distinct roles. Internal (technical docs, changelogs, schema fields, IDs, prompts, lane signatures) stays Capture Cascade (Cap-1/2/3,
dark_aeons.captured.<id>,capture_cascade.patrol_kills,arena.dark.<id>). Player-facing (popups, mod README, mod page) = Yoke of Spira (EN) / Jugo de Spira (PT) — biblical/Yevon resonance (Matthew 11:30 "for my yoke is easy") echoes vanilla FFX's theocratic theme. F7 Conquests tab = The Yoke (EN) / O Jugo (PT). Default popup string: EN "Besaid is now under the yoke of Dark Valefor" / PT "Besaid está sob o jugo de Dark Valefor"; on-capture battletext EN "Dark Valefor has been tamed. Spira trembles." / PT "Dark Valefor foi domado. Spira sente o tremor." Capture Cascade doc gained §0 (naming convention table + Microsoft Threshold/Redstone rationale). VISION_AND_ROADMAP §11 gained the 3-context table with cross-link
v2.123.1.1
v2.123.2.0BETAPATCH
Lulu
Ronso Mana: root-cause FIX of the command ring — the ring buffer base was never dereferenced (bug #1)
- (fixes a runtime-hook behavior bug + RE). The finding: the command-ring buffer is runtime-allocated; its absolute pointer lives in a BSS cell (
*(u32*)0x2310CD8).7AEFC0/79BB70domov edi,[cell](DEREF) before indexing+20592(sort scratch) /+1144*slot(per-actor ring).RonsoManaHook.cppusedRVA_FFX_BATTLE_COMMAND_RING_BSS_BASE=0x1F0FCD8raw, without the deref, and off by 0x1000 — so ALL ring writes (template, per-slot header+0, OD row+296) acrosshudSafe 11..21landed in a static BSS region that was never the live displayed buffer. This explains why no BSS ring injection ever appeared, and whyCopyMenuTemplate_Shim(the7AEFC0detour) always early-returned (delta = slotPtr - ringBasewas never a multiple of 1144). Fix: newRVA_FFX_BATTLE_COMMAND_RING_BASE_PTR=0x1F10CD8(the real pointer cell, taken from the imm32 ofmov edi,[..]@0x7AEFC8) +BattleCommandRingUiBase()now dereferences it (*(u32*)(g_base+RVA), null-checked when not yet allocated). With this,PatchKimahriCommandRingUi(+0 header),PatchKimahriMainMenuOverdriveRow(+296 OD) andCopyMenuTemplate_Shim(+296 post-sort) write to the real ring for the first time. RE proven (IDA):7AD980= sort one array by priority (key=*(u8*)(GetCommandEntryById+92), scratch=ring+20592);7AEFC0calls it 8× (one per category) to sort the per-slot ring..i64renames:7AEFC0→FFX_Btl_UI_SortCommandRingSlot,7AD980→FFX_Btl_UI_SortCmdRingArrayByPrio+ comment on the pointer cell0x2310CD8. DIAG (hudSafe=22):DumpKimahriRingStatelogs a readback of the real+0/+296atG0-finalizeto confirm whether the encoded OD cmd (0x311A) lands. PolyHook build PASS (10/10), apply-mode deploy. RT2 Needs Testing (bug #1: OD in the middle ring). Doc:docs/reverse/FFX_RONSO_MANA_COMMAND_RING_PIPELINE_RE_2026-06-16.md§9
v2.123.1.2
v2.123.3.1BETAREVISION
Seymour
Spira Reforge: Capture Cascade Cap-1 — `capturable` bit in `m###.bin` LOCATED (Phase B RE spike, doc-only)
- (RE/doc, no behavior change; chained on top of
v2.123.3.0MINOR from a parallel lane — this REVISION is purely doc/RE and does not compete with that MINOR). Capture Cascade Phase B spike delivered doc-only: the byte that controlscapturable=true|falsein everym###.binwas located byte-precise and validated with 58 samples. Verdict: position =bytes[StatSheetPointer + 0x78](whereStatSheetPointer = uint32_le(bytes[0x0C])); semantics =0xFF(sbyte -1) means uncapturable,0x00..0x67(sbyte 0..103) means capturable (slot index in the vanilla Monster Arena's 104-slot table); paddingbytes[StatSheetPointer + 0x79]is always0x00. Evidence chain crossed (a) legacy editor v1.4FFXmon4.ini(label "Capture index" as 16-bit hex,00FF= uncap), (b) current C# structFfxLib/Monster/Monster_StatSheet.cslines 49-50 ([Data] public sbyte ArenaId+[Data] public byte ArenaIdPadding), (c) live UI bindingMonEditor_Control.axamlline 466 ("Capture index (Arena)"), (d) full structural layout (MonsterHeaderFile0x40-byte header + StatSheet section +Monster_StatSheetStatBlock where ArenaId sits at offset+0x64relative to the StatBlock that begins atsection + 0x14→ file-relative+0x78). Proof: 21/21 capturables matched expected slot (including byte-exact match withFFXmon4.iniform044=0x28/m045=0x29/m046=0x2A/m193=0x55/m194=0x56), 16/16 boss uncap =0xFF, 10/10 Dark Aeons (m334..m343) =0xFF, 3/3 Penance entries (m344..m346) =0xFF. Important operational correction: the old "DA live inm106..m113" assumption was WRONG — the real DAs arem334..m343(proved inFfxLib/Dictionaries/Monster_Dictionary.cslines 343-356), with Magus Sisters as 3 separate entries (m341/m342/m343). DOC-ONLY: nothing was written tom###.bin/DLL/runtime/save/hook in this session. Not executed: IDA confirmation of theCanCapture()gatekeeper (PLAN's optional Step 3); cross-validation against vanillaFFX Extracted\tree (recommended but not blocking — 58/58 modded already match the vanilla expectation via the FFXmon4.ini cross-reference). Artifacts:docs/reverse/FFX_SPIRA_REFORGE_CAPTURE_BIT_M_HEADER_RE_RESULT_2026-06-16.md(full RESULT doc with Phase C writer recipe),work/_capture_re_2026-06-16/parse_capture_offset.ps1(CLI parser),work/_capture_re_2026-06-16/dump_arena_id_evidence.ps1(bulk dump),work/_capture_re_2026-06-16/capture_re_evidence_summary.json(58 rows),work/_capture_re_2026-06-16/capture_re_evidence_hexdump.txt. The original PLAN doc gained a BLOQUEIO RESOLVIDO banner + corrected DA IDs.PORT_STATUS.mdgot a row "Capture Cascade Cap-1 —capturablebit located" asPrecisa Testar in-game (Phase C writer). Cap-1 writer (Phase C, next session) writes 1 byte per monster while preserving byte-identity of the 8 adjacent identity fields. [previous:v2.123.3.0(parallel lane; their changelog entry will land when they ship)]
v2.123.4.0BETAPATCH
Lulu
Nul Ward: teach/menu-surface RE VERDICT + FIX of the menu-bound hook (it was patching the wrong `cmp 320`)
- (fixes a behavior bug in
NulWardTeachHook+ RE proven on the real.i64; PATCH bump → revision resets; prior HEADv2.123.3.1was a parallel-lane REVISION). Full RE pass (idalib MCP on the realFFX_recon.i64) answering whether teaching Radiant(320)/Umbral(321) via the sphere grid + a growncommand.binworks end-to-end. PROVEN chain: (1)FFX_GrantCommandToCharacter@0x785D10routes id≥96 to the party-wide bankg_PartyWideCommandBank@0x11307FC— 16 words/256 bits = ids 96..351; Radiant=word14 bit0, Umbral=word14 bit1; (2)FFX_Btl_BuildActorCommandMenu@0x79BB70SEEDS the whole bank into actor+0x670 (copy loop ends atg_CmdAggregateAvailArrays@0x113081C→ bank = 16 words); (3)FFX_Btl_IsCommandAvailable@0x79AD40reads actor word818+id/16(id320→byte 0x68C bit0) — consistent; (4)FFX_SphereGrid_NodeActivateStateMachine@0x8CC300case21 calls grant(char, node.LearnedMove, 1) → a node withLearnedMove=0x3140/0x3141teaches it; (5) persistence viaFFX_IsCommandLearnedPersistent@0x7850E0reads the same bit. BUG FOUND & FIXED:BuildActorCommandMenuhas 3cmp r32,140h(two81 FE=esi on the aggregate loops, one81 FF=edi on the PLACEMENT loop that inserts the id into the White-magic submenu). Only the placement compare controls whether 320/321 reach the menu; the oldNulWardTeachHookpatched the first match (81 FE, a no-op for surfacing). FIX: it now patches allcmp r32,140h→0x142(PolyHook rebuild PASS). Documented RT2 risks: (a)FFX_Kernel_GetCommandEntryById@0x790AE0→FFX_Table_GetEntryByIdRange@0x7AB890is a range-table with a fallback to cmd 0 — the growncommand.binmust extend the range covering 320/321 (else Radiant resolves to cmd 0); (b) persistence depends on theply_savelimit/special map being wide enough to cover bit 224/225 (word 14). Design: id≥96 = party-wide (the whole party learns it), not per-char (96-bit cap). Renames+comments applied to the real.i64(FFX_Btl_IsCommandAvailable,FFX_Btl_InitPartyWideCommandBank,FFX_Btl_PrepareSaveCommandState,FFX_Btl_BuildAggregateChildList,g_PartyWideCommandBank,g_PerCharCmdMenuState, etc.). Doc:docs/reverse/FFX_NUL_WARD_TEACH_SURFACE_RE_VERDICT_2026-06-16.md
v2.123.3.1
v2.123.4.1BETAPATCH
Lulu
Ronso Mana hudSafe=24: PERSISTENT gauge-full PIN (`max:=charge`) — fixes "can't even go LEFT into Overdrive unless the bar is maxed"
- (fixes a runtime-hook behavior bug + RE). The finding (proven by log + decompile): FFX couples "Overdrive usable" to a full gauge (
charge==max) and re-checks it PER-FRAME in the HUD/menu renderer — outside our hooks. ThehudSafe=23transient spoof setmax:=chargearound each trampoline but restoredmax=255right after (EndKimahriMaxSpoof), so the frame the ring is drawn sawmax=255(gauge not full) → Overdrive hidden / LEFT blocked. RT2 log evidence (hudSafe=23):G0 menu charge=100 max=100(the spoof DID work during the build) yet OD still never appeared;IsOdReady ... vanilla=1 ->1(the 0x590 bits were set, even by vanilla) and it was still blocked. RE this pass (idalib MCP):79AF70 = (actor[0x590]>>2)&1,79AEE0 = (actor[0x590]>>3)&1— both forced and =1, NOT the gate;792AB0(FFX_Btl_BattleMenuInputDispatch) builds thekind=12OD ring when79AF70(so the OD ring exists);799AD0/799D60/7996E0/799830are target-mask resolvers, not the OD-full gate. Conclusion: the live gate is the per-framecharge==maxcompare in the renderer — out of reach of a transient spoof. Fix:ApplyKimahriRuntimePoolMaxnow persistently pinsmax:=chargewhilecharge>=gateMin(the gauge reads 100% full for every per-frame check while his command menu is up; the ATB/CTB is paused during command input, so no overdrive gain is lost); below the threshold it hands the real pool (255) back so the gauge refills toward 0–255. The transientBegin/Endspoof is retired (no-ops); the dispatch shim now calls the persistent pin. Known tradeoff (RT2): the bar reads full while OD is usable; OD gain may pause while charge sits in the usable band (revisit if RT2 shows a gain stall — scope the pin to menu-only). PolyHook build PASS (10/10), apply-mode deploy (SHAB092B4C6). RT2 Needs Testing (go LEFT + use Ronso Rage at partial charge). Doc:docs/reverse/FFX_RONSO_MANA_COMMAND_RING_PIPELINE_RE_2026-06-16.md§10
v2.123.4.0
v2.123.5.0BETAPATCH
Lulu
Nul Ward grid-teach: command.bin range PROVEN (no exe patch) + LearnedMove encoding FIX in the editor + offline verifier
- (fixes a SphereGridExplorer editor behavior bug + new offline proof/verifier + RE). DLL untouched (the Ronso Mana lane is using it) — C#/editor/IDA only. RT2 risk #1 ELIMINATED offline: RE proved
FFX_Kernel_LoadFileToTable@0x781E00(case 0"command") loadscommand.binverbatim into a global pointer (g_CommandKernelTable@0x112A92C, full-filememcpy) — no range synthesis.FFX_Table_GetEntryByIdRange@0x7AB890reads the range header straight from the file bytes, mapping exactly ontoEntryListFile:numRanges=int16@0(=Signature=1),lo=PreviousFileCount@8(=0),hi=(EntryCount-1)@10,stride=EntrySize@12(0x60),base=EntryTableFileOffset@16(0x14);record = file + 0x14 + id*0x60. Since the growncommand.binwritesEntryCount-1=321, ids 320/321 ∈ [0,321] → resolve to exactly the appended Radiant/Umbral rows. No exe/DLL patch. NewCommandKernelLookupVerifier(FfxLib/Ability) replays the engine's exact math against the grown bytes and is wired into the--nul-ward-staticgate (engine_lookup_resolvescheck: offline proof that GetCommandEntryById(320/321) does NOT hit the cmd0 fallback). Editor FIX (SphereGridExplorer): the LearnedMove dropdown stored the raw id (0x0140), but on-disk is the encoded id (0x3000|id) — proven empirically bySphereGridRt2Lab(Armor Break inpanel.bin=0x3012) and required by the grant's(cmd & 0xFFFFF000)==0x3000gate. The dropdown now emits0x3000|id(Radiant→0x3140, Umbral→0x3141) and resolves names masking& 0xFFF, so the user can place the wards on the sphere grid and they actually teach (before it stored 0x0140 and the grant rejected it)..i64renames:0x781E00→FFX_Kernel_LoadFileToTable,g_CommandKernelTable/g_KernelFileSizes/g_AAbilityKernelTable/g_ItemKernelTable+ proven comments on0x781E00/0x7AB890/0x790AE0(saved viaidalib_save). C# builds PASS (0 errors). Doc:docs/reverse/FFX_NUL_WARD_TEACH_SURFACE_RE_VERDICT_2026-06-16.md§F/§G
v2.123.4.1
v2.123.5.1BETAREVISION
Yuna
Aurora finalization balistica: Phase 0 kickoff (docs reconciliation + legacy comment fix + variant UNVERIFIED badge)
- (docs + RE/honesty annotation; no new feature; no behavioral bump). Plan persisted at
.cursor/plans/aurora_balistica.plan.md(10 phases, Halyson-confirmed scope A+B: 5 active RT2s + IDA W2S spike + variant-selector IDA spike). This REVISION ships Phase 0 only (docs reconciliation before probe instrumentation). Four edits: (1)PORT_STATUS.md"Aurora Chamber" row — Honestidade text corrected: wastransform battle->world is DESIGN/UNCALIBRATED (...) flip-Z is a hypothesis, now reflects the 2026-06-05 IDA-proof (X/Z = identity,Y residual RT2 pending, refsFFX_AURORA_BATTLE_TO_SCENE_TRANSFORM_IDA_PROVEN_2026-06-05.md+FFX_AURORA_MASTER_RT2_CHECKLIST_2026-06-15.mdA01/A04/A10). (2)PORT_STATUS.mdtop — new blockAtualizacao 2026-06-16 (Aurora finalizacao balistica)summarizing real Aurora state reconciled against A15 + confirmed RT2 order (azit03_00 -> klyt00_00 -> drag -> grow -> camera -> photo, then IDA spike). (3)RuntimeTools/FFXMapViewerWeb/aurora-overlay.js— JSDoc header (lines 9-10) corrected: wasRAW battle-local - design-only/UNCALIBRATED, nowIDA-proven IDENTITY in X/Z; Y residual per area/model height (actor+0x534) RT2 pending; flip-Z stays as comparison/debug only. (4)FFXProjectEditor/Modules/AuroraChamber/AuroraChamber_DataModel.cs—variantNote(shown inSceneDetailwhen_resolver.ResolveScenes(MapKey)returns more than 1 variant) now appendsruntime selector UNVERIFIEDnext to the_a/_b/_clist, so users know the Chamber renders whichever variant the catalog picks while the real selector (story-flag -> variant) hasn't been RE-proven — see A04FFX_AURORA_ARENA_VARIANT_SELECTION_RE_2026-06-15.md. Does not touch: probe, writers, offline gates, FfxHooksDll. Next (Phase 1): implementaurora-calib-v2inRuntimeTools/FfxDinput8Probe/ctl/Program.cswith CSV/JSON output (residualidentity_dx/dy/dz/rms,flipz_*,yaw180_*,winnerenum,height_0x534, route + battle id) — spec indocs/reverse/FFX_AURORA_CALIBRATION_PROBE_SPEC_2026-06-15.md. Phase 0 RT2: N/A (docs-only + UI string)
v2.123.5.0