Repository navigation
Description
Highest-leverage parity blocker after merged #574, #575, and #577. The failed/closed #572 and #576 experiments established that compatibility projections must be removed only after all resolver consumers migrate.
Current main: 5e514e6308e0de11b1322fbbb9e5f6625949502d
Pinned Python oracle: Teffa14/AutoPTU@16d228efa63aabecb67fa788959a359aac7f8f03
Current repository evidence
BattleRuntime.applyAuthoritativeMoveInternal still carries three independent legacy decisions:
spendOrdinaryMoveResourcesrunPreDamageReactionsdeclaredChoiceAlreadyValidated
The first boolean currently controls both action-budget mutation and moveFrequencyUsage().recordUse(move). That prevents the resolver from representing action-spend ownership and move-frequency ownership as independent contract dimensions.
#577 is now merged. CommittedReactionRuntimeExecutionPlan.spendOrdinaryMoveResources() derives its transitional projection from executionContext().ownsActionSpend() rather than the deprecated combined context projection. This removes one real consumer before the central migration and preserves frequency ownership as an independent dimension.
Live ingress mapping at current main
- ordinary public/dependency-aware paths: legacy tuple
true, true, false->MoveRuntimeExecutionContext.ordinary() - pre-resolution target replacement:
true, true, true->MoveRuntimeExecutionContext.preResolutionResolved() - area target execution:
false, true, false->MoveRuntimeExecutionContext.areaResolved() - delayed hit execution:
false, false, false->MoveRuntimeExecutionContext.delayed() - committed reaction remains deferred until this migration is green ->
MoveRuntimeExecutionContext.committedReaction()
Required bounded migration
- Replace the three resolver booleans with one
MoveRuntimeExecutionContextin the same production change. - Every ingress constructs its named identity explicitly:
ORDINARY,PRE_RESOLUTION_RESOLVED,AREA_RESOLVED,DELAYED, laterCOMMITTED_REACTION. - Call
executionContext.requireValidDeclaration(...)exactly once before RNG consumption. - Gate PRE hooks only with
executionContext.runPreDamageReactions(). - Pass only
executionContext.ownsActionSpend()to the action-budget mutation point. - Record move frequency only when
executionContext.ownsMoveFrequency()is true. - Remove the deprecated combined context projection only after every Java consumer is migrated in the same PR. Do not repeat Remove combined move resource ownership projection #572/Remove combined execution-context resource projection #576 cleanup-first ordering.
- Preserve RNG draw order, accuracy/evasion, move-special ordering, type multiplier handling, post-damage hooks, HP/injury history, forced movement, semantic event ordering and final state.
Acceptance gates
- Java Core Parity
- Python Action Economy
- Kairos Action Economy
- Runtime Ordinary Damage Ingress
- Battle RNG Ownership
- Pre Resolution Target
- Multi-Target Move Execution
- Delayed Hit Execution + Delayed Hit Resource
- Move Special Registry + Move Special Effect Roll
- Status Move Execution + StatusController Phase Order
- Forced Movement Instruction
- Intercept Orchestration
- Initiative Rebuild
- Round Temporary Effect Expiry
- Field Round Progression
- relevant Trainer Feature / Held Item / history / temporary-HP gates
Do not wire COMMITTED_REACTION until this migration is green. The next slice after this issue is the first end-to-end AoO trace against the pinned Python oracle.
Activity
Teffa14 commentedon Sep 23, 2026
Fresh main audit at e131719 confirms the resolver is still the highest-leverage action-economy blocker. BattleRuntime.applyAuthoritativeMoveInternal still accepts three independent booleans: spendOrdinaryMoveResources, runPreDamageReactions, declaredChoiceAlreadyValidated. The first boolean still controls BOTH applyResolvedMoveOutcomeInternal(... spendAction) and actor.moveFrequencyUsage().recordUse(move), so the resolver cannot yet represent split action/frequency ownership. Current typed MoveRuntimeExecutionContext already exposes the required independent decisions: requireValidDeclaration(...), ownsActionSpend(), ownsMoveFrequency(), runPreDamageReactions().
Pinned Python oracle re-inspected: Teffa14/AutoPTU@16d228e. Its frequency.py keeps frequency as a separate rules authority with battle/round scopes, reinforcing that frequency accounting must not be inferred from action-spend ownership.
Atomic migration map for this issue:
No partial BattleRuntime edit was pushed in this audit because the resolver change must be atomic; leaving mixed boolean/context ownership would create an invalid intermediate authority boundary.
Teffa14 commentedon Sep 24, 2026
Fresh main audit after #577 merge (
5e514e6308e0de11b1322fbbb9e5f6625949502d) confirms the next atomic resolver migration. LiveBattleRuntimestill passes three booleans intoapplyAuthoritativeMoveInternal: combined ordinary-resource ownership, PRE-reaction execution, and declaration-already-validated. The combined resource flag still owns both action-budget spending andMoveFrequencyUsage.recordUse, whileMoveRuntimeExecutionContextalready exposes independentownsActionSpend(),ownsMoveFrequency(),runPreDamageReactions(), and declaration validation. Pinned Python oracle inspected:Teffa14/AutoPTU@16d228efa63aabecb67fa788959a359aac7f8f03.Bounded implementation contract for #573 remains atomic: migrate both internal overloads and every ingress together; validate the context before state/RNG; route action spend only through
ownsActionSpend(), frequency accounting only throughownsMoveFrequency(), PRE hooks only throughrunPreDamageReactions(). Preserve target preparation, RNG order, move-special ordering, damage/HP/history, forced movement, ordered events, and final state. Keep the deprecated combined projection until all consumers in this migration are gone; remove it only as a follow-up after green parity.Current ingress mapping from live main: ordinary = ordinary context; pre-resolution target path = declaration already validated context; area target = area-resolved context; delayed hit = delayed context; committed reaction remains disconnected until this seam is green. Acceptance gates: Java Core + pinned Python oracle, Python/Kairos action economy, ordinary damage ingress, RNG ownership, pre-resolution target, multi-target, delayed-hit execution/resource, forced movement, intercept, move-special registry/order/effect-roll, status move/phase order, initiative rebuild, temporary-effect expiry, field progression, Trainer Feature, held-item, history and temp-HP gates.
Teffa14 commentedon Sep 24, 2026
Fresh audit on main@5faa49993822037728731068c066296061b99eb9 after closing red #579. Re-inspected every internal docs file and all three docs/contracts files, then read BattleRuntime across the full authoritative move seam. Oracle remains Teffa14/AutoPTU@16d228e.
Current evidence pins the highest-leverage blocker to action economy / authoritative move dispatch. BattleRuntime still has three internal overloads carrying spendOrdinaryMoveResources, runPreDamageReactions, and declaredChoiceAlreadyValidated. The terminal overload uses spendOrdinaryMoveResources twice for distinct state mutations: applyResolvedMoveOutcomeInternal(..., spendAction) and actor.moveFrequencyUsage().recordUse(move). It also selects declaration validation from the legacy tuple before the first RNG draw. Ordinary, PRE_RESOLUTION_RESOLVED, AREA_RESOLVED, and DELAYED ingress paths still construct those tuples independently.
The next safe implementation must therefore be one atomic BattleRuntime migration, not another compatibility-removal precursor:
Do not remove MoveRuntimeExecutionContext.spendOrdinaryMoveResources() in this same first implementation attempt. #579 proved that removing the compatibility projection before the resolver migration causes broad Java/Python gate failures. Remove it only after the migrated resolver and all call sites are green.
Required regression matrix after the atomic edit: Java Core/Python oracle; Python + Kairos action economy; RNG ownership; ordinary damage ingress; pre-resolution target; multi-target; delayed-hit execution/resource; move-special registry/order/effect-roll; status move execution/phase order; forced movement; intercept; initiative rebuild; temporary-effect expiry; field round progression; related Trainer Feature, held-item, temporary-HP, combat-stage, and history gates. No merge until relevant CI is green.
Teffa14 commentedon Sep 24, 2026
Fresh audit on main@c6e1bcd11b45ab2f609c6781f4fbe7a0c512ce65 and pinned Python oracle Teffa14/AutoPTU@16d228e. All 86 workflows on the current main head are completed with zero failures. Re-read every current docs file and all three runtime contracts before inspecting the live resolver.
Exact production seam confirmed in BattleRuntime.java: ordinary dependency-aware ingress still passes (true,true,false); pre-resolution-resolved passes (true,true,true); area-resolved passes (false,true,false); delayed passes (false,false,false). The three applyAuthoritativeMoveInternal overloads still transport spendOrdinaryMoveResources/runPreDamageReactions/declaredChoiceAlreadyValidated. The terminal overload still branches declaration validation from that tuple before RNG, passes spendOrdinaryMoveResources to applyResolvedMoveOutcomeInternal for action spending, and reuses the same boolean for moveFrequencyUsage().recordUse(move).
MoveRuntimeExecutionContext/Policy/DeclarationValidator already provide the replacement contract: requireValidDeclaration(...), ownsActionSpend(), ownsMoveFrequency(), runPreDamageReactions(), plus explicit ORDINARY/PRE_RESOLUTION_RESOLVED/AREA_RESOLVED/DELAYED/COMMITTED_REACTION identities. No additional registry family is needed before the migration.
Prepared branch codex/573-runtime-context-production-guard from the exact green main head. Do not remove spendOrdinaryMoveResources() first (the closed #579 proved that order breaks broad parity). Next safe production commit must migrate all internal overloads and all four existing ingress identities together, preserve RNG/hook/event ordering, then run the full relevant parity matrix before wiring COMMITTED_REACTION.