From cd3981f09541d4a87d8402ce534d16dce7737768 Mon Sep 17 00:00:00 2001 From: "Flemming N. Larsen" Date: Mon, 19 Oct 2026 20:56:00 +0200 Subject: [PATCH 1/7] Propose stop overwrite routing change --- .clue/id-ledger.yaml | 1 + .../open-questions.md | 3 ++ .../CH-020-stop-overwrite-route/proposal.md | 29 +++++++++++++++++++ changes/CH-020-stop-overwrite-route/tasks.md | 10 +++++++ 4 files changed, 43 insertions(+) create mode 100644 changes/CH-020-stop-overwrite-route/open-questions.md create mode 100644 changes/CH-020-stop-overwrite-route/proposal.md create mode 100644 changes/CH-020-stop-overwrite-route/tasks.md diff --git a/.clue/id-ledger.yaml b/.clue/id-ledger.yaml index 2f91534..2b93ca3 100644 --- a/.clue/id-ledger.yaml +++ b/.clue/id-ledger.yaml @@ -1612,6 +1612,7 @@ events: - {id: AN-705, kind: numeric, state: reserved, prefix: AN, component: "705"} - {id: AN-704, kind: numeric, state: live, prefix: AN, component: "704"} - {id: AN-705, kind: numeric, state: live, prefix: AN, component: "705"} + - {id: CH-020, kind: numeric, state: reserved, prefix: CH, component: "20"} high-water: - {id: ADR-002, kind: numeric, state: reserved, prefix: ADR, component: "2"} - {id: AN-014, kind: numeric, state: reserved, prefix: AN, component: "14"} diff --git a/changes/CH-020-stop-overwrite-route/open-questions.md b/changes/CH-020-stop-overwrite-route/open-questions.md new file mode 100644 index 0000000..7e04d04 --- /dev/null +++ b/changes/CH-020-stop-overwrite-route/open-questions.md @@ -0,0 +1,3 @@ +# Open questions + +No blocking open questions have been identified. The remaining semantic risk is whether Tank Royale's overwrite-stop state matches Classic after an earlier stop; the official robot retest will check that risk. diff --git a/changes/CH-020-stop-overwrite-route/proposal.md b/changes/CH-020-stop-overwrite-route/proposal.md new file mode 100644 index 0000000..a146692 --- /dev/null +++ b/changes/CH-020-stop-overwrite-route/proposal.md @@ -0,0 +1,29 @@ +--- +id: CH-020 +type: change +status: open +links: [P-001, CAP-008, CRIT-008] +title: Route classic stop overwrite through Tank Royale +--- + +# CH-020 — Route classic stop overwrite through Tank Royale + +## What and why + +M-006 found that the legacy `jaybot.bots.Oddball` calls `Robot.stop(true)`, and `BotPeer.stop(boolean)` currently rejects that call even though Tank Royale's `IBot` exposes `setStop(boolean)`. This prevents the robot from producing a Tank Royale result and leaves a bridge-owned discrepancy in the parity registry. + +Route the Classic overwrite flag to `IBot.setStop(overwrite)`. Revise CAP-008's stop-routing acceptance criterion and its evidence so the bridge preserves the boolean argument rather than rejecting it. + +## Commitment challenge + +The key assumption is that Tank Royale `setStop(true)` preserves Classic's overwrite semantics for an already-stopped robot. The Bot API implementation saves the pending movement and turn rates again when overwrite is true, which appears to match Classic's documented behavior. + +The alternative is to keep `stop(true)` unsupported and record this as a known bridge limitation. That conflicts with M-006's exit criterion, which requires bridge-owned discrepancies to be repaired and retested. + +The cheapest useful check is a peer-routing regression test for both boolean values, followed by the official-parameter retest of `jaybot.bots.Oddball`. Revise or stop the change if Tank Royale's resulting stop/resume behavior differs from Classic in the focused retest. + +An implementation could pass the routing test and still fail the user if the saved command state differs after an earlier stop. The official robot retest is included to detect that failure beyond the unit criterion. + +## Scope + +This change updates the existing stop-routing criterion in CAP-008, the peer implementation and focused unit evidence, the capability design, the parity registry after retest, and `CHANGELOG.md`. It does not change the frozen `robocode.*` signatures or the M-006 plan promise. diff --git a/changes/CH-020-stop-overwrite-route/tasks.md b/changes/CH-020-stop-overwrite-route/tasks.md new file mode 100644 index 0000000..243afa6 --- /dev/null +++ b/changes/CH-020-stop-overwrite-route/tasks.md @@ -0,0 +1,10 @@ +# Tasks + +- [ ] Revise CAP-008 stop-routing acceptance evidence, retiring the criterion that requires rejecting overwrite and adding a criterion for preserving the `stop(boolean)` argument. +- [ ] Route `BotPeer.stop(boolean)` through the Tank Royale stop setter while preserving the existing non-overwrite behavior. +- [ ] Add focused positive and negative unit evidence for overwrite-stop routing and prove no neighboring peer call is used. +- [ ] Update the CAP-008 design and `CHANGELOG.md` to describe the restored Classic behavior. +- [ ] Run the relevant bridge unit checks and build the bridge and wrapper jars. +- [ ] Retest `jaybot.bots.Oddball` with official Melee parameters, record repair-linked evidence in the parity registry, and diagnose any remaining difference. +- [ ] Run the required Cliewen validation and review loop on the committed candidate. +- [ ] Digest the accepted capability and registry changes, then remove this change workspace. From 5ecb4a1801144bcc7e76c227c0274d19ce34241c Mon Sep 17 00:00:00 2001 From: "Flemming N. Larsen" Date: Mon, 19 Oct 2026 20:58:28 +0200 Subject: [PATCH 2/7] Clarify stop overwrite change proposal --- .clue/id-ledger.yaml | 1 + changes/CH-020-stop-overwrite-route/proposal.md | 6 +++--- changes/CH-020-stop-overwrite-route/tasks.md | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.clue/id-ledger.yaml b/.clue/id-ledger.yaml index 2b93ca3..4c04cf1 100644 --- a/.clue/id-ledger.yaml +++ b/.clue/id-ledger.yaml @@ -1613,6 +1613,7 @@ events: - {id: AN-704, kind: numeric, state: live, prefix: AN, component: "704"} - {id: AN-705, kind: numeric, state: live, prefix: AN, component: "705"} - {id: CH-020, kind: numeric, state: reserved, prefix: CH, component: "20"} + - {id: ROUTE-013, kind: numeric, state: reserved, prefix: ROUTE, component: "13"} high-water: - {id: ADR-002, kind: numeric, state: reserved, prefix: ADR, component: "2"} - {id: AN-014, kind: numeric, state: reserved, prefix: AN, component: "14"} diff --git a/changes/CH-020-stop-overwrite-route/proposal.md b/changes/CH-020-stop-overwrite-route/proposal.md index a146692..07a856f 100644 --- a/changes/CH-020-stop-overwrite-route/proposal.md +++ b/changes/CH-020-stop-overwrite-route/proposal.md @@ -12,11 +12,11 @@ title: Route classic stop overwrite through Tank Royale M-006 found that the legacy `jaybot.bots.Oddball` calls `Robot.stop(true)`, and `BotPeer.stop(boolean)` currently rejects that call even though Tank Royale's `IBot` exposes `setStop(boolean)`. This prevents the robot from producing a Tank Royale result and leaves a bridge-owned discrepancy in the parity registry. -Route the Classic overwrite flag to `IBot.setStop(overwrite)`. Revise CAP-008's stop-routing acceptance criterion and its evidence so the bridge preserves the boolean argument rather than rejecting it. +Route the Classic overwrite flag to `IBot.stop(overwrite)`. Retire `ROUTE-005` and replace it with `ROUTE-013`, which preserves stop overwrite while retaining the existing stop, resume, and independence-flag coverage. ## Commitment challenge -The key assumption is that Tank Royale `setStop(true)` preserves Classic's overwrite semantics for an already-stopped robot. The Bot API implementation saves the pending movement and turn rates again when overwrite is true, which appears to match Classic's documented behavior. +The key assumption is that Tank Royale `IBot.stop(boolean)` preserves Classic's overwrite semantics for an already-stopped robot. Its interface documents that `true` overrides a previous saved movement and that `false` behaves like `setStop()`, matching the Classic contract. The alternative is to keep `stop(true)` unsupported and record this as a known bridge limitation. That conflicts with M-006's exit criterion, which requires bridge-owned discrepancies to be repaired and retested. @@ -26,4 +26,4 @@ An implementation could pass the routing test and still fail the user if the sav ## Scope -This change updates the existing stop-routing criterion in CAP-008, the peer implementation and focused unit evidence, the capability design, the parity registry after retest, and `CHANGELOG.md`. It does not change the frozen `robocode.*` signatures or the M-006 plan promise. +This change updates the CAP-008 stop-routing criterion, the peer implementation and focused unit evidence, the capability design, the parity registry after retest, and `CHANGELOG.md`. It does not change the frozen `robocode.*` signatures or the M-006 plan promise. diff --git a/changes/CH-020-stop-overwrite-route/tasks.md b/changes/CH-020-stop-overwrite-route/tasks.md index 243afa6..16a70b3 100644 --- a/changes/CH-020-stop-overwrite-route/tasks.md +++ b/changes/CH-020-stop-overwrite-route/tasks.md @@ -1,7 +1,7 @@ # Tasks -- [ ] Revise CAP-008 stop-routing acceptance evidence, retiring the criterion that requires rejecting overwrite and adding a criterion for preserving the `stop(boolean)` argument. -- [ ] Route `BotPeer.stop(boolean)` through the Tank Royale stop setter while preserving the existing non-overwrite behavior. +- [ ] Retire `ROUTE-005` and add `ROUTE-013` to CAP-008 for stop overwrite, preserving existing stop, resume, and independence-flag coverage. +- [ ] Route `BotPeer.stop(boolean)` through `IBot.stop(overwrite)` while preserving the boolean argument. - [ ] Add focused positive and negative unit evidence for overwrite-stop routing and prove no neighboring peer call is used. - [ ] Update the CAP-008 design and `CHANGELOG.md` to describe the restored Classic behavior. - [ ] Run the relevant bridge unit checks and build the bridge and wrapper jars. From 55de3fc5a191daadb83e455663ca4473bf6656c4 Mon Sep 17 00:00:00 2001 From: "Flemming N. Larsen" Date: Mon, 19 Oct 2026 20:59:44 +0200 Subject: [PATCH 3/7] Route stop overwrite through matching Bot API method --- CHANGELOG.md | 1 + changes/CH-020-stop-overwrite-route/tasks.md | 10 ++-- .../CAP-008-call-routing-fidelity/criteria.md | 10 +++- .../CAP-008-call-routing-fidelity/design.md | 2 + .../robocode/tankroyale/bridge/BotPeer.java | 8 +-- .../bridge/StandardPeerRoutingTest.java | 50 +++++++++++-------- 6 files changed, 47 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40bc7c0..5794936 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- Route legacy `Robot.stop(boolean)` overwrite calls to the matching Tank Royale API, preserving saved movement when the robot calls `stop(true)`. - Truncate legacy robot and team author metadata to the Bot API's 50-character limit so long author names do not prevent wrapped bots from starting. - Trim legacy robot and team author metadata in generated bot JSON so it matches the Bot API's canonical author identity and does not block bot startup. - Copy a robot's bundled data file when `getDataFile()` resolves it, and create an empty file when no bundled resource exists, matching Classic's file initialization behavior. diff --git a/changes/CH-020-stop-overwrite-route/tasks.md b/changes/CH-020-stop-overwrite-route/tasks.md index 16a70b3..16f4be2 100644 --- a/changes/CH-020-stop-overwrite-route/tasks.md +++ b/changes/CH-020-stop-overwrite-route/tasks.md @@ -1,10 +1,10 @@ # Tasks -- [ ] Retire `ROUTE-005` and add `ROUTE-013` to CAP-008 for stop overwrite, preserving existing stop, resume, and independence-flag coverage. -- [ ] Route `BotPeer.stop(boolean)` through `IBot.stop(overwrite)` while preserving the boolean argument. -- [ ] Add focused positive and negative unit evidence for overwrite-stop routing and prove no neighboring peer call is used. -- [ ] Update the CAP-008 design and `CHANGELOG.md` to describe the restored Classic behavior. -- [ ] Run the relevant bridge unit checks and build the bridge and wrapper jars. +- [x] Retire `ROUTE-005` and add `ROUTE-013` to CAP-008 for stop overwrite, preserving existing stop, resume, and independence-flag coverage. +- [x] Route `BotPeer.stop(boolean)` through `IBot.stop(overwrite)` while preserving the boolean argument. +- [x] Add focused positive and negative unit evidence for overwrite-stop routing and prove no neighboring peer call is used. +- [x] Update the CAP-008 design and `CHANGELOG.md` to describe the restored Classic behavior. +- [x] Run `./gradlew :robocode-api:test` and build the bridge and wrapper jars. - [ ] Retest `jaybot.bots.Oddball` with official Melee parameters, record repair-linked evidence in the parity registry, and diagnose any remaining difference. - [ ] Run the required Cliewen validation and review loop on the committed candidate. - [ ] Digest the accepted capability and registry changes, then remove this change workspace. diff --git a/docs/capabilities/CAP-008-call-routing-fidelity/criteria.md b/docs/capabilities/CAP-008-call-routing-fidelity/criteria.md index 1c4ae8f..297c990 100644 --- a/docs/capabilities/CAP-008-call-routing-fidelity/criteria.md +++ b/docs/capabilities/CAP-008-call-routing-fidelity/criteria.md @@ -48,7 +48,7 @@ Feature: Bot API call-routing fidelity Then each value comes from the corresponding Bot API value, converted into Robocode's frame And no getter returns a neighbouring component's value - @ROUTE-005 + @ROUTE-005 @retired Scenario: Stopping, resuming, and the independence flags route individually Test-type: Unit Given a robot that stops, resumes, or sets one independence flag @@ -56,6 +56,14 @@ Feature: Bot API call-routing fidelity Then it reaches that call alone, carrying its argument rather than an assumed value And an unsupported variant is refused rather than silently downgraded + @ROUTE-013 + Scenario: Stopping, resuming, overwrite, and independence flags route individually + Test-type: Unit + Given a robot that stops with an overwrite flag, resumes, or sets one independence flag + When the call is routed + Then it reaches the matching Bot API call alone, carrying its argument rather than an assumed value + And stop(overwrite) reaches IBot.stop(overwrite) with the boolean preserved + @ROUTE-006 Scenario: A queued command is queued, not executed Test-type: Unit diff --git a/docs/capabilities/CAP-008-call-routing-fidelity/design.md b/docs/capabilities/CAP-008-call-routing-fidelity/design.md index 07fef2c..4f4ef79 100644 --- a/docs/capabilities/CAP-008-call-routing-fidelity/design.md +++ b/docs/capabilities/CAP-008-call-routing-fidelity/design.md @@ -32,6 +32,8 @@ Not "the call succeeded". Each names the Bot API method reached and the argument That negative half is doing most of the work. A method that routes to the wrong neighbour still compiles, still runs, and still produces a battle; only an assertion that the neighbour was untouched distinguishes it. +`Robot.stop(boolean)` preserves its overwrite flag by calling the matching `IBot.stop(boolean)` overload. The routing tests check the `true` flag reaches that overload and that no neighbouring stop or resume call is made. + ## Completeness, and why it is enforced rather than reviewed `PeerSurfaceCoverageTest` walks the peer interfaces reflectively from `ITeamRobotPeer` and `IJuniorRobotPeer`, and fails naming any method no routing test calls. diff --git a/robocode-api/src/main/java/dev/robocode/tankroyale/bridge/BotPeer.java b/robocode-api/src/main/java/dev/robocode/tankroyale/bridge/BotPeer.java index 3f74b36..413e41d 100644 --- a/robocode-api/src/main/java/dev/robocode/tankroyale/bridge/BotPeer.java +++ b/robocode-api/src/main/java/dev/robocode/tankroyale/bridge/BotPeer.java @@ -806,13 +806,7 @@ public void rescan() { @Override public void stop(boolean overwrite) { log("stop()"); - if (overwrite) { - // flemming-n-larsen: I don't expect any bots to use this functionality, and hence it is not supported (yet) - // in Robocode Tank Royale. - throw new UnsupportedOperationException( - "stop(overwrite=true) is unsupported. Contact Robocode Tank Royale author for support"); - } - bot.stop(); + bot.stop(overwrite); } @Override diff --git a/robocode-api/src/test/java/dev/robocode/tankroyale/bridge/StandardPeerRoutingTest.java b/robocode-api/src/test/java/dev/robocode/tankroyale/bridge/StandardPeerRoutingTest.java index dad1aeb..264d3ce 100644 --- a/robocode-api/src/test/java/dev/robocode/tankroyale/bridge/StandardPeerRoutingTest.java +++ b/robocode-api/src/test/java/dev/robocode/tankroyale/bridge/StandardPeerRoutingTest.java @@ -7,11 +7,10 @@ import static java.lang.Math.toRadians; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; /** - * Acceptance evidence for ROUTE-005 — the {@code IStandardRobotPeer} surface: stopping, + * Acceptance evidence for ROUTE-013 — the {@code IStandardRobotPeer} surface: stopping, * resuming, turning the radar, and the three independence flags. * * The flags are the interesting part. Each decouples one component from another's rotation, @@ -33,10 +32,11 @@ void setUp() { } @Test - @DisplayName("ROUTE-005 positive: stopping and resuming route to their Bot API calls") - void testROUTE005_UnitPositive_RoutesStopAndResume() { + @DisplayName("ROUTE-013 positive: stopping and resuming route to their Bot API calls") + void testROUTE013_UnitPositive_RoutesStopAndResume() { peer.stop(false); assertTrue(bot.called("stop"), bot.names()); + assertEquals(Boolean.FALSE, bot.onlyCall("stop").args[0]); bot.clear(); peer.resume(); @@ -44,26 +44,34 @@ void testROUTE005_UnitPositive_RoutesStopAndResume() { } @Test - @DisplayName("ROUTE-005 negative: stop with overwrite is refused rather than silently downgraded") - void testROUTE005_UnitNegative_RefusesStopWithOverwriteRatherThanIgnoringIt() { - // Tank Royale has no equivalent. Refusing is the honest answer: quietly treating it as - // an ordinary stop would discard the robot's saved movement state, and the robot would - // resume into a different action than the one it stopped. - assertThrows(UnsupportedOperationException.class, () -> peer.stop(true)); - assertFalse(bot.called("stop"), "the unsupported call must not reach the bot: " + bot.names()); + @DisplayName("ROUTE-013 positive: stop overwrite reaches the Bot API with its argument") + void testROUTE013_UnitPositive_RoutesStopOverwriteArgument() { + peer.stop(true); + + assertEquals(Boolean.TRUE, bot.onlyCall("stop").args[0]); + } + + @Test + @DisplayName("ROUTE-013 negative: stop overwrite does not call a neighboring Bot API method") + void testROUTE013_UnitNegative_DoesNotCallAnotherStopAction() { + peer.stop(true); + + assertEquals(1, bot.calls().size(), bot.names()); + assertEquals("stop", bot.calls().get(0).name); + assertEquals(Boolean.TRUE, bot.calls().get(0).args[0]); } @Test - @DisplayName("ROUTE-005 positive: turning the radar reaches the radar call in degrees") - void testROUTE005_UnitPositive_RoutesRadarTurnInDegrees() { + @DisplayName("ROUTE-013 positive: turning the radar reaches the radar call in degrees") + void testROUTE013_UnitPositive_RoutesRadarTurnInDegrees() { peer.turnRadar(toRadians(120)); assertEquals(120.0, bot.onlyCall("turnRadarRight").doubleArg(0), EPSILON); } @Test - @DisplayName("ROUTE-005 positive: each independence flag reaches its own Bot API setter") - void testROUTE005_UnitPositive_RoutesEachIndependenceFlagToItsOwnSetter() { + @DisplayName("ROUTE-013 positive: each independence flag reaches its own Bot API setter") + void testROUTE013_UnitPositive_RoutesEachIndependenceFlagToItsOwnSetter() { peer.setAdjustGunForBodyTurn(true); assertEquals(true, bot.onlyCall("setAdjustGunForBodyTurn").args[0]); @@ -77,8 +85,8 @@ void testROUTE005_UnitPositive_RoutesEachIndependenceFlagToItsOwnSetter() { } @Test - @DisplayName("ROUTE-005 negative: setting one independence flag sets no other") - void testROUTE005_UnitNegative_SettingOneIndependenceFlagLeavesTheOthersAlone() { + @DisplayName("ROUTE-013 negative: setting one independence flag sets no other") + void testROUTE013_UnitNegative_SettingOneIndependenceFlagLeavesTheOthersAlone() { peer.setAdjustRadarForGunTurn(true); assertFalse(bot.called("setAdjustGunForBodyTurn"), bot.names()); @@ -86,8 +94,8 @@ void testROUTE005_UnitNegative_SettingOneIndependenceFlagLeavesTheOthersAlone() } @Test - @DisplayName("ROUTE-005 positive: the flag value is passed through rather than assumed true") - void testROUTE005_UnitPositive_PassesTheFlagValueThroughRatherThanAssumingTrue() { + @DisplayName("ROUTE-013 positive: the flag value is passed through rather than assumed true") + void testROUTE013_UnitPositive_PassesTheFlagValueThroughRatherThanAssumingTrue() { // A routing that ignored its argument would pass every test that only ever sets true, // and would leave a robot unable to turn the independence off again. peer.setAdjustGunForBodyTurn(false); @@ -96,8 +104,8 @@ void testROUTE005_UnitPositive_PassesTheFlagValueThroughRatherThanAssumingTrue() } @Test - @DisplayName("ROUTE-005 positive: reading an independence flag reads the matching Bot API flag") - void testROUTE005_UnitPositive_ReadsEachIndependenceFlagFromItsOwnSource() { + @DisplayName("ROUTE-013 positive: reading an independence flag reads the matching Bot API flag") + void testROUTE013_UnitPositive_ReadsEachIndependenceFlagFromItsOwnSource() { bot.returning("isAdjustGunForBodyTurn", true) .returning("isAdjustRadarForGunTurn", false) .returning("isAdjustRadarForBodyTurn", true); From 30ded3408867c23401c3f2a37c908dbde5cf22f5 Mon Sep 17 00:00:00 2001 From: "Flemming N. Larsen" Date: Mon, 19 Oct 2026 21:01:07 +0200 Subject: [PATCH 4/7] Record Oddball stop overwrite retest --- changes/CH-020-stop-overwrite-route/tasks.md | 2 +- compat-test/parity-registry.json | 388 ++++++++++++++++++- compat-test/parity-registry.md | 6 +- 3 files changed, 390 insertions(+), 6 deletions(-) diff --git a/changes/CH-020-stop-overwrite-route/tasks.md b/changes/CH-020-stop-overwrite-route/tasks.md index 16f4be2..3b289d3 100644 --- a/changes/CH-020-stop-overwrite-route/tasks.md +++ b/changes/CH-020-stop-overwrite-route/tasks.md @@ -5,6 +5,6 @@ - [x] Add focused positive and negative unit evidence for overwrite-stop routing and prove no neighboring peer call is used. - [x] Update the CAP-008 design and `CHANGELOG.md` to describe the restored Classic behavior. - [x] Run `./gradlew :robocode-api:test` and build the bridge and wrapper jars. -- [ ] Retest `jaybot.bots.Oddball` with official Melee parameters, record repair-linked evidence in the parity registry, and diagnose any remaining difference. +- [x] Retest `jaybot.bots.Oddball` with official Melee parameters, record repair-linked evidence in the parity registry, and diagnose the remaining opponent-pool difference. - [ ] Run the required Cliewen validation and review loop on the committed candidate. - [ ] Digest the accepted capability and registry changes, then remove this change workspace. diff --git a/compat-test/parity-registry.json b/compat-test/parity-registry.json index f215fdd..a627e3f 100644 --- a/compat-test/parity-registry.json +++ b/compat-test/parity-registry.json @@ -184319,6 +184319,12 @@ "id": "diagnosis-1", "owner": "bridge", "recorded_at": "2026-10-19T18:54:25Z" + }, + { + "cause": "melee-opponent-pool-contamination", + "id": "diagnosis-2", + "owner": "harness", + "recorded_at": "2026-10-19T19:00:51Z" } ], "identity": { @@ -184329,7 +184335,7 @@ "key": "meleerumble/jaybot.bots.Oddball_4.0.jar", "kind": "robot" }, - "latest_observation": "e15d719a76e461c3", + "latest_observation": "50ea318f51f84718", "observations": [ { "classic": { @@ -184638,9 +184644,387 @@ "status": "incomplete" } } + }, + { + "classic": { + "elapsed": 5.7, + "error_count": 384, + "error_signatures": [ + { + "exception": "java.lang.ArrayIndexOutOfBoundsException", + "origin": "amk.guns.Aristocles.prepare" + }, + { + "exception": "java.lang.ArrayIndexOutOfBoundsException", + "origin": "unknown" + }, + { + "exception": "java.lang.SecurityException", + "origin": "amk.ChumbaMini.saveData" + }, + { + "exception": "java.lang.SecurityException", + "origin": "unknown" + } + ], + "errors": [ + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.WinEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.SecurityException occurred on robocode.DeathEvent", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException", + "SYSTEM: java.lang.ArrayIndexOutOfBoundsException occurred on robocode.ScannedRobotEvent", + "java.lang.ArrayIndexOutOfBoundsException" + ], + "has_log": true, + "ok": true, + "score": 115687.0, + "scores": [ + 13361.0, + 13989.0, + 13637.0, + 9013.0, + 12296.0, + 7550.0, + 10773.0, + 11283.0, + 7084.0, + 16701.0 + ], + "selected": "jaybot.bots.Oddball 4.0" + }, + "completed_at": "2026-10-19T19:00:35Z", + "confirmation": null, + "delta_pct": -2.2, + "id": "50ea318f51f84718", + "manifest": { + "artifacts": { + "bot_api_jar": { + "path": "C:\\Code\\tank-royale\\bot-api\\java\\build\\libs\\robocode-tankroyale-bot-api-1.4.0.jar", + "sha256": "ab65c4d5cec1808adeb71375adae6d15341ae250def89a6c10fc9da879de0752" + }, + "bridge_api_jar": { + "path": "C:\\Code\\robocode-api-bridge\\robocode-api\\build\\libs\\robocode-api-0.5.0.jar", + "sha256": "154d52aa5024d135754acc0cf988877b31445dc5ed2606f1329ab314a8c5a703" + }, + "runner_jar": { + "path": "C:\\Code\\tank-royale\\runner\\examples\\lib\\robocode-tankroyale-runner.jar", + "sha256": "4f208f8047d0f0d49d119255fc713b042fb9c34fb1d01c585fcfa8730cb940fc" + }, + "wrapper_jar": { + "path": "C:\\Code\\robocode-api-bridge\\robots-wrapper\\build\\libs\\robots-wrapper-0.3.1.jar", + "sha256": "c1e9c32a7ec454fc722c4b7f0c3df38ec8fba510b9cacfceaf50d4cfcda0b0a4" + } + }, + "bridge_commit": "55de3fc5a191daadb83e455663ca4473bf6656c4", + "official_parameters": true, + "robocode_version": "1.11.1", + "tank_royale_commit": "d5a9e3acc4b65466ab8668c0d3884c3eb3b35621", + "threshold": 25.0 + }, + "retest": { + "cause": "classic-stop-overwrite-explicitly-rejected-by-bridge", + "diagnosis_id": "diagnosis-1", + "owner": "bridge", + "repair": "55de3fc" + }, + "setup": { + "height": 1000, + "opponent_pool": [ + { + "jar": "adt.Ar1_2.1.jar", + "sha256": "37857b3fe3d082f121da8dd8ca81a5ea58edcab65fad3c552d71dfa65f58b14e" + }, + { + "jar": "adt.Ar2_1.0.jar", + "sha256": "2adf54760aefa12c1e79667c064a9529b85aed2218e8a7457c335fb91153394e" + }, + { + "jar": "amk.ChumbaMini_0.2.jar", + "sha256": "5770270c23f9223e4df93f5455fcf461ecd30309fc318f3d53cbbdf93e133d6b" + }, + { + "jar": "amk.ChumbaWumba_0.3.jar", + "sha256": "f7594cdfa02419ae112013ec923387736a89840712162020ecb899e39d6127e9" + }, + { + "jar": "amk.Punbot.Punbot_0.01.jar", + "sha256": "44e10755757c7cb523ad7f6a746f5524f6a054fe7d047528da8330829284b389" + }, + { + "jar": "amk.ShizzleStiX.ShizzleStiX_0.6.jar", + "sha256": "3e93e50b7380b8b2f98ab1c30911bc56a98c6eb27ccb5125d1aa8cbbc5987850" + }, + { + "jar": "amk.jointstrike.JointStrike_0.2.jar", + "sha256": "3f45fd832f7bb6b6ceb3841c1ab108583ba11b49ba06cbde2f8e61637dc28297" + }, + { + "jar": "ap.Frederick_1.1.jar", + "sha256": "d7f1709e4ea064f0662f383c339f57390977292fdd921933adc36e305a375899" + }, + { + "jar": "apc.botM_3.0.jar", + "sha256": "9348a9b3c2e0f175bacf361dc3b20a0842f186c228564bcafd8b6d853d345d94" + }, + { + "jar": "ara.Shera_0.88.jar", + "sha256": "9474b68598ae5e71010b835259467b6dc35427e2826ace23e484a6a11160a040" + }, + { + "jar": "arthord.NanoSatanMelee_Beta.jar", + "sha256": "a0737bc6d25f6b89618c119a6df62ae89a44d9a2a7d662056dddefdde04f37fe" + }, + { + "jar": "axeBots.HataMoto_3.09.jar", + "sha256": "293a92846b40195a5de25c7379f72e0dcb08297f79d2b6fffd7d3a95b50afb2c" + } + ], + "opponents": [ + { + "jar": "adt.Ar1_2.1.jar", + "sha256": "37857b3fe3d082f121da8dd8ca81a5ea58edcab65fad3c552d71dfa65f58b14e" + }, + { + "jar": "adt.Ar2_1.0.jar", + "sha256": "2adf54760aefa12c1e79667c064a9529b85aed2218e8a7457c335fb91153394e" + }, + { + "jar": "amk.ChumbaMini_0.2.jar", + "sha256": "5770270c23f9223e4df93f5455fcf461ecd30309fc318f3d53cbbdf93e133d6b" + }, + { + "jar": "amk.ChumbaWumba_0.3.jar", + "sha256": "f7594cdfa02419ae112013ec923387736a89840712162020ecb899e39d6127e9" + }, + { + "jar": "amk.Punbot.Punbot_0.01.jar", + "sha256": "44e10755757c7cb523ad7f6a746f5524f6a054fe7d047528da8330829284b389" + }, + { + "jar": "amk.ShizzleStiX.ShizzleStiX_0.6.jar", + "sha256": "3e93e50b7380b8b2f98ab1c30911bc56a98c6eb27ccb5125d1aa8cbbc5987850" + }, + { + "jar": "amk.jointstrike.JointStrike_0.2.jar", + "sha256": "3f45fd832f7bb6b6ceb3841c1ab108583ba11b49ba06cbde2f8e61637dc28297" + }, + { + "jar": "ap.Frederick_1.1.jar", + "sha256": "d7f1709e4ea064f0662f383c339f57390977292fdd921933adc36e305a375899" + }, + { + "jar": "apc.botM_3.0.jar", + "sha256": "9348a9b3c2e0f175bacf361dc3b20a0842f186c228564bcafd8b6d853d345d94" + } + ], + "participants": 10, + "rounds": 35, + "width": 1000 + }, + "source_identity": { + "classic_selected": "jaybot.bots.Oddball 4.0", + "division": "meleerumble", + "jar": "jaybot.bots.Oddball_4.0.jar", + "jar_sha256": "12d0d549ecee200b1bb2a0b9dcd0774ca1d53a2b562c7f5d0bbece999e1c09ca", + "key": "meleerumble/jaybot.bots.Oddball_4.0.jar", + "kind": "robot" + }, + "status": "DISCREPANCY (errors)", + "tank_royale": { + "bridge_only_signatures": null, + "elapsed": 34.2, + "error_count": 30, + "error_signatures": [ + { + "exception": "java.lang.SecurityException", + "origin": "amk.ChumbaMini.saveData" + }, + { + "exception": "java.lang.SecurityException", + "origin": "unknown" + } + ], + "errors": [ + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time.", + "java.lang.SecurityException: You may only have 5 streams open at a time." + ], + "has_log": true, + "ok": true, + "score": 113137.0, + "scores": [ + 18209.0, + 13575.0, + 13531.0, + 13373.0, + 12809.0, + 10913.0, + 9872.0, + 8754.0, + 7985.0, + 4116.0 + ], + "skipped": null, + "skipped_turn_telemetry": { + "events": [ + { + "bot_id": 1, + "round": 1, + "turn": 1 + }, + { + "bot_id": 2, + "round": 1, + "turn": 1 + }, + { + "bot_id": 3, + "round": 1, + "turn": 1 + }, + { + "bot_id": 6, + "round": 1, + "turn": 1 + }, + { + "bot_id": 8, + "round": 1, + "turn": 1 + }, + { + "bot_id": 10, + "round": 1, + "turn": 1 + } + ], + "status": "captured" + } + } } ], - "status": "DISCREPANCY (outcome)" + "status": "DISCREPANCY (errors)" }, "meleerumble/jcs.Seth_1.8.jar": { "diagnosis_events": [ diff --git a/compat-test/parity-registry.md b/compat-test/parity-registry.md index 85cc399..b746de4 100644 --- a/compat-test/parity-registry.md +++ b/compat-test/parity-registry.md @@ -7,9 +7,9 @@ This generated table is the reviewed index of the append-only observations in `p | Status | Subjects | |---|---:| | CONFIRMED (score) | 233 | -| DISCREPANCY (errors) | 114 | +| DISCREPANCY (errors) | 115 | | DISCREPANCY (no score) | 9 | -| DISCREPANCY (outcome) | 67 | +| DISCREPANCY (outcome) | 66 | | MATCHED (failure) | 49 | | MATCHED (score noise) | 139 | | PASS | 712 | @@ -168,7 +168,7 @@ This generated table is the reviewed index of the append-only observations in `p | meleerumble/jab.DiamondStealer_5.jar | meleerumble | robot | DISCREPANCY (errors) | fae68a2757f1e40a | melee-opponent-pool-contamination | harness | | meleerumble/jangs.ns51_1.0.jar | meleerumble | robot | DISCREPANCY (errors) | f6f5b19abc44f9b5 | melee-opponent-pool-contamination | harness | | meleerumble/jaybot.adv.bots.JayBot_2.0.jar | meleerumble | robot | DISCREPANCY (errors) | 737e8e86d63ba6d5 | melee-opponent-pool-contamination | harness | -| meleerumble/jaybot.bots.Oddball_4.0.jar | meleerumble | robot | DISCREPANCY (outcome) | e15d719a76e461c3 | classic-stop-overwrite-explicitly-rejected-by-bridge | bridge | +| meleerumble/jaybot.bots.Oddball_4.0.jar | meleerumble | robot | DISCREPANCY (errors) | 50ea318f51f84718 | melee-opponent-pool-contamination | harness | | meleerumble/jcs.Seth_1.8.jar | meleerumble | robot | DISCREPANCY (errors) | 9b9138a2f5fc680b | melee-opponent-pool-contamination | harness | | meleerumble/jdw.Hurricane_1.4.jar | meleerumble | robot | DISCREPANCY (errors) | 0c2ae0cbac2e6851 | melee-opponent-pool-contamination | harness | | meleerumble/jekl.StoneGhost_0.7.jar | meleerumble | robot | DISCREPANCY (errors) | 8de300b1a4e97d53 | melee-opponent-pool-contamination | harness | From 5a873c28d98613e9c127468a17ee322964dcd864 Mon Sep 17 00:00:00 2001 From: "Flemming N. Larsen" Date: Mon, 19 Oct 2026 21:01:43 +0200 Subject: [PATCH 5/7] Complete stop overwrite implementation tasks --- changes/CH-020-stop-overwrite-route/tasks.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/changes/CH-020-stop-overwrite-route/tasks.md b/changes/CH-020-stop-overwrite-route/tasks.md index 3b289d3..5973d38 100644 --- a/changes/CH-020-stop-overwrite-route/tasks.md +++ b/changes/CH-020-stop-overwrite-route/tasks.md @@ -6,5 +6,3 @@ - [x] Update the CAP-008 design and `CHANGELOG.md` to describe the restored Classic behavior. - [x] Run `./gradlew :robocode-api:test` and build the bridge and wrapper jars. - [x] Retest `jaybot.bots.Oddball` with official Melee parameters, record repair-linked evidence in the parity registry, and diagnose the remaining opponent-pool difference. -- [ ] Run the required Cliewen validation and review loop on the committed candidate. -- [ ] Digest the accepted capability and registry changes, then remove this change workspace. From ed6c51530796d7aebbbf2a75f4f5959a81a8e9b4 Mon Sep 17 00:00:00 2001 From: "Flemming N. Larsen" Date: Mon, 19 Oct 2026 21:04:21 +0200 Subject: [PATCH 6/7] Digest stop overwrite routing change --- .clue/id-ledger.yaml | 2 ++ .../open-questions.md | 3 -- .../CH-020-stop-overwrite-route/proposal.md | 29 ------------------- changes/CH-020-stop-overwrite-route/tasks.md | 8 ----- 4 files changed, 2 insertions(+), 40 deletions(-) delete mode 100644 changes/CH-020-stop-overwrite-route/open-questions.md delete mode 100644 changes/CH-020-stop-overwrite-route/proposal.md delete mode 100644 changes/CH-020-stop-overwrite-route/tasks.md diff --git a/.clue/id-ledger.yaml b/.clue/id-ledger.yaml index 4c04cf1..25b5ae0 100644 --- a/.clue/id-ledger.yaml +++ b/.clue/id-ledger.yaml @@ -1614,6 +1614,8 @@ events: - {id: AN-705, kind: numeric, state: live, prefix: AN, component: "705"} - {id: CH-020, kind: numeric, state: reserved, prefix: CH, component: "20"} - {id: ROUTE-013, kind: numeric, state: reserved, prefix: ROUTE, component: "13"} + - {id: ROUTE-013, kind: numeric, state: live, prefix: ROUTE, component: "13"} + - {id: CH-020, kind: numeric, state: live, prefix: CH, component: "20"} high-water: - {id: ADR-002, kind: numeric, state: reserved, prefix: ADR, component: "2"} - {id: AN-014, kind: numeric, state: reserved, prefix: AN, component: "14"} diff --git a/changes/CH-020-stop-overwrite-route/open-questions.md b/changes/CH-020-stop-overwrite-route/open-questions.md deleted file mode 100644 index 7e04d04..0000000 --- a/changes/CH-020-stop-overwrite-route/open-questions.md +++ /dev/null @@ -1,3 +0,0 @@ -# Open questions - -No blocking open questions have been identified. The remaining semantic risk is whether Tank Royale's overwrite-stop state matches Classic after an earlier stop; the official robot retest will check that risk. diff --git a/changes/CH-020-stop-overwrite-route/proposal.md b/changes/CH-020-stop-overwrite-route/proposal.md deleted file mode 100644 index 07a856f..0000000 --- a/changes/CH-020-stop-overwrite-route/proposal.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -id: CH-020 -type: change -status: open -links: [P-001, CAP-008, CRIT-008] -title: Route classic stop overwrite through Tank Royale ---- - -# CH-020 — Route classic stop overwrite through Tank Royale - -## What and why - -M-006 found that the legacy `jaybot.bots.Oddball` calls `Robot.stop(true)`, and `BotPeer.stop(boolean)` currently rejects that call even though Tank Royale's `IBot` exposes `setStop(boolean)`. This prevents the robot from producing a Tank Royale result and leaves a bridge-owned discrepancy in the parity registry. - -Route the Classic overwrite flag to `IBot.stop(overwrite)`. Retire `ROUTE-005` and replace it with `ROUTE-013`, which preserves stop overwrite while retaining the existing stop, resume, and independence-flag coverage. - -## Commitment challenge - -The key assumption is that Tank Royale `IBot.stop(boolean)` preserves Classic's overwrite semantics for an already-stopped robot. Its interface documents that `true` overrides a previous saved movement and that `false` behaves like `setStop()`, matching the Classic contract. - -The alternative is to keep `stop(true)` unsupported and record this as a known bridge limitation. That conflicts with M-006's exit criterion, which requires bridge-owned discrepancies to be repaired and retested. - -The cheapest useful check is a peer-routing regression test for both boolean values, followed by the official-parameter retest of `jaybot.bots.Oddball`. Revise or stop the change if Tank Royale's resulting stop/resume behavior differs from Classic in the focused retest. - -An implementation could pass the routing test and still fail the user if the saved command state differs after an earlier stop. The official robot retest is included to detect that failure beyond the unit criterion. - -## Scope - -This change updates the CAP-008 stop-routing criterion, the peer implementation and focused unit evidence, the capability design, the parity registry after retest, and `CHANGELOG.md`. It does not change the frozen `robocode.*` signatures or the M-006 plan promise. diff --git a/changes/CH-020-stop-overwrite-route/tasks.md b/changes/CH-020-stop-overwrite-route/tasks.md deleted file mode 100644 index 5973d38..0000000 --- a/changes/CH-020-stop-overwrite-route/tasks.md +++ /dev/null @@ -1,8 +0,0 @@ -# Tasks - -- [x] Retire `ROUTE-005` and add `ROUTE-013` to CAP-008 for stop overwrite, preserving existing stop, resume, and independence-flag coverage. -- [x] Route `BotPeer.stop(boolean)` through `IBot.stop(overwrite)` while preserving the boolean argument. -- [x] Add focused positive and negative unit evidence for overwrite-stop routing and prove no neighboring peer call is used. -- [x] Update the CAP-008 design and `CHANGELOG.md` to describe the restored Classic behavior. -- [x] Run `./gradlew :robocode-api:test` and build the bridge and wrapper jars. -- [x] Retest `jaybot.bots.Oddball` with official Melee parameters, record repair-linked evidence in the parity registry, and diagnose the remaining opponent-pool difference. From c48bd5a86bbaef5442d146c017cbd45168ab449b Mon Sep 17 00:00:00 2001 From: "Flemming N. Larsen" Date: Mon, 19 Oct 2026 21:25:58 +0200 Subject: [PATCH 7/7] Record user-selected simple route for CH-020 Cliewen-Route: simple Cliewen-Recommendation: full Cliewen-Override: user chose simple; full validation baseline contains 220 pre-existing issues