Skip to content

Fail closed when the Phase 1 solo-continuation bridge contract cannot be enabled #11

Description

@NeoLorenzo

Audit Priority: P2
Audit Type: FIX

Problem / Opportunity

Phase 1 depends on POLYVISION_SOLO_NO_OPPONENT_MODE=1 so a one-tribe SCORE-mode map continues across END_TURN actions through the wrapper's Turn-10 horizon. TribesGymEnv.__init__() asks the Java bridge to enable that behavior with PythonEnv.setSoloNoOpponentMode(...), but catches every exception from that call and silently continues.

If the Java/Py4J bridge is stale, incompatible, or otherwise fails while setting the mode, Python can return an apparently usable environment whose turn-termination semantics no longer match the Phase 1 contract.

Why This Matters

The solo-continuation flag is not an optional optimization. In PythonEnv.stepByIndex(), it changes whether END_TURN suppresses ordinary single-tribe SCORE-mode game-over and explicitly advances the tick, restores an incomplete result, initializes the next turn, and recomputes actions. Silently failing to configure that behavior can therefore invalidate training, evaluation, or human-benchmark execution at the game-transition layer.

The repository recently made TribesGymWrapper construction fail closed when the real environment interface cannot be established (#7 / commit 5641344575b6d486df388cba82e788cdb20c556d). The lower-level bridge should provide the same guarantee for this experiment-defining mode instead of retaining a compatibility fallback that can change semantics.

Evidence

Proposed Outcome

Treat requested solo/no-opponent configuration as part of the executable environment contract. When Python requests the mode, the bridge must either configure and verify the requested value or fail environment construction with the underlying cause preserved. Do not silently continue with unknown/default Java semantics.

Definition of Done

  • TribesGymEnv no longer silently ignores failure to call setSoloNoOpponentMode() when the mode is requested.
  • Environment construction verifies the Java-side value through getSoloNoOpponentMode() (or an equivalently authoritative contract check) and fails if it does not match the requested Python configuration.
  • A bridge/version mismatch or setter/getter failure raises a clear exception that preserves useful underlying diagnostic context.
  • A regression test covers at least one failed setter/getter or mismatched round-trip case.
  • A live contract test confirms that enabled solo mode permits the expected single-tribe END_TURN continuation semantics without changing the current successful Phase 1 behavior.
  • The regression is included in the maintained core CI gate.

Constraints / Non-Goals

This issue does not redesign solo gameplay, add opponents, change the Turn-10 curriculum, or introduce automatic bridge-version negotiation. It only makes the currently required Phase 1 mode explicit and fail-closed. If an intentionally supported legacy Java bridge without this API is ever needed, that should be a separate explicitly selected compatibility mode rather than an automatic silent fallback.

Validation

Run the cheap core CI with a mocked bridge that throws or reports the wrong solo-mode value and verify construction fails. Then run a live single-tribe environment path with solo mode enabled and verify an END_TURN reaches the next tick/turn rather than terminating immediately.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions