Skip to content

Commit 4fd87e7

Browse files
Digest CH-007 event conformance foundation
1 parent 5db6eb0 commit 4fd87e7

8 files changed

Lines changed: 74 additions & 39 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Changelog
2+
3+
## Unreleased
4+
5+
- Added two-engine conformance evidence for pending scan delivery, turn-boundary timing, custom-event removal, skipped turns, handler exceptions, and official ten-participant melee scans.
6+
- Preserved classic handler-exception reporting by surfacing legacy callback failures at the bridge boundary while retaining Tank Royale's event queue.

changes/CH-007-m001-event-conformance-foundation/tasks.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@ links: [CH-007, P-001, CAP-001]
66
title: CH-007 implementation tasks
77
---
88

9-
- [ ] Inspect classic's authoritative test robots and source assertions for EVT-002, EVT-005, EVT-006, EVT-008, EVT-009, and EVT-010, and choose stable evidence markers or probes.
10-
- [ ] Extend the conformance harness adapter to pass the requested participant count and preserve one shared expectation across classic and Tank Royale, serving EVT-010.
11-
- [ ] Add focused positive and negative integration evidence for EVT-002, serving EVT-002.
12-
- [ ] Add focused positive and negative integration evidence for EVT-005, serving EVT-005.
13-
- [ ] Add focused positive and negative integration evidence for EVT-006, serving EVT-006.
14-
- [ ] Add focused positive and negative integration evidence for EVT-008, serving EVT-008.
15-
- [ ] Add focused positive and negative integration evidence for EVT-009, serving EVT-009.
16-
- [ ] Add focused positive and negative integration evidence for EVT-010, serving EVT-010.
17-
- [ ] Repair any bridge behavior exposed by the new evidence while preserving the frozen robocode.* surface, serving the failing criterion.
18-
- [ ] Run the tier-1 unit suite and the focused tier-2 conformance tests; retain environment skips or matched local Tank Royale artifact details in the handoff.
19-
- [ ] Digest the permanent corpus, regenerate indexes, run clue validate, commit the final state, and delete this change workspace.
9+
- [x] Inspect classic's authoritative test robots and source assertions for EVT-002, EVT-005, EVT-006, EVT-008, EVT-009, and EVT-010, and choose stable evidence markers or probes.
10+
- [x] Extend the conformance harness adapter to pass the requested participant count and preserve one shared expectation across classic and Tank Royale, serving EVT-010.
11+
- [x] Add focused positive and negative integration evidence for EVT-002, serving EVT-002.
12+
- [x] Add focused positive and negative integration evidence for EVT-005, serving EVT-005.
13+
- [x] Add focused positive and negative integration evidence for EVT-006, serving EVT-006.
14+
- [x] Add focused positive and negative integration evidence for EVT-008, serving EVT-008.
15+
- [x] Add focused positive and negative integration evidence for EVT-009, serving EVT-009.
16+
- [x] Add focused positive and negative integration evidence for EVT-010, serving EVT-010.
17+
- [x] Repair the bridge behavior exposed by EVT-009 while preserving the frozen robocode.* surface, serving EVT-009.
18+
- [x] Run the tier-1 unit suite and the focused tier-2 conformance tests; retain environment skips or matched local Tank Royale artifact details in the handoff.

docs/capabilities/CAP-001-event-dispatch-parity/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ The physics the events describe. That a `ScannedRobotEvent` arrives at the right
3333

3434
## Status
3535

36-
`draft`. The redesign that routed events through the Bot API's own event queue is implemented and believed correct, but it was verified by running battles and reading scores. Every criterion here is unproven in the sense that matters: nothing would tell us if it broke again. `M-001` is the plan door.
36+
`draft`. The conformance tier now proves the event queue, timing, custom-event, skipped-turn, exception, and melee behaviors with named positive and negative tests on classic and Tank Royale, so every non-retired criterion is active. The capability remains draft until its high-cost inferred runtime topology and protocol-compatibility dependencies are explicitly verified. The matched local Bot API and runner pair used for these engine runs is required by [`PDR-002`](../../decisions/PDR-002-locally-built-tank-royale-artifacts-for-conformance.md). `M-001` is the plan door.
3737

38-
The conformance tier now reaches some of them. `EVT-004`, `EVT-011`, `EVT-012`, `EVT-013`, `EVT-014`, and `EVT-015` are active — the tests that already proved them were retagged after [`G-002`](../../goals/G-002-conformance-evidence-proves-the-criterion-it-names.md) found them mistagged, and `EVT-001`/`EVT-003`/`EVT-007` retired rather than be credited with evidence they cannot honestly claim ([`IDR-003`](../../decisions/IDR-003-evt-003-scoped-to-what-classic-actually-proves.md), [`IDR-004`](../../decisions/IDR-004-evt-007-scoped-to-observable-survivor-delivery.md), [`IDR-005`](../../decisions/IDR-005-evt-001-scoped-to-classic-filter-behavior.md)). `EVT-004` and `EVT-014` are proven with a locally built matched Tank Royale Bot API and runner pair under [`PDR-002`](../../decisions/PDR-002-locally-built-tank-royale-artifacts-for-conformance.md), which contains the server repair [`AN-009`](../../analysis/AN-009-the-server-never-sends-a-death-to-any-bot.md) identified. `EVT-015` is proven with the same matched pair and a bridge-owned two-phase probe: a higher-priority scan callback is required inside `onHitWall`, then a lower-priority scan callback is required to be absent. The capability still holds at `draft` because most criteria remain unproven.
38+
The conformance tier now reaches every non-retired criterion. `EVT-004`, `EVT-011`, `EVT-012`, `EVT-013`, `EVT-014`, and `EVT-015` were already active — the tests that proved them were retagged after [`G-002`](../../goals/G-002-conformance-evidence-proves-the-criterion-it-names.md) found them mistagged, and `EVT-001`/`EVT-003`/`EVT-007` retired rather than be credited with evidence they cannot honestly claim ([`IDR-003`](../../decisions/IDR-003-evt-003-scoped-to-what-classic-actually-proves.md), [`IDR-004`](../../decisions/IDR-004-evt-007-scoped-to-observable-survivor-delivery.md), [`IDR-005`](../../decisions/IDR-005-evt-001-scoped-to-classic-filter-behavior.md)). `EVT-002`, `EVT-005`, `EVT-006`, `EVT-008`, `EVT-009`, and `EVT-010` are proven by bridge-owned probes and classic's authoritative test robots in the same matched pair. `IDR-006` records the callback boundary required to preserve classic exception reporting while retaining Bot API queue semantics.

docs/capabilities/CAP-001-event-dispatch-parity/criteria.md

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
id: CRIT-001
33
type: criteria
4-
status: draft
4+
status: active
55
links: [CAP-001]
66
title: Event dispatch and timing parity — acceptance criteria
77
ac-prefix: EVT
@@ -11,7 +11,7 @@ reversal-cost: low
1111

1212
# CAP-001 — acceptance criteria
1313

14-
Most criteria here are `@draft` against `M-001`; `EVT-004`, `EVT-011`, `EVT-012`, `EVT-013`, `EVT-014`, and `EVT-015` are active. Each names the classic test robot or bridge-owned probe that will prove it, because classic's own conformance suite already encodes these expectations and the conformance tier restates them against both engines.
14+
All non-retired criteria here are active against `M-001`. Each names the classic test robot or bridge-owned probe that proves it, because classic's own conformance suite already encodes these expectations and the conformance tier restates them against both engines.
1515

1616
```gherkin
1717
Feature: Event dispatch and timing parity
@@ -24,13 +24,13 @@ Feature: Event dispatch and timing parity
2424
Then the recorded order is the same on both engines
2525
# Retired: the named EventPriorityFilter robot does not record handler order. See IDR-005; successor EVT-015.
2626
27-
@EVT-002 @draft
27+
@EVT-002
2828
Scenario: A blocking call inside a handler does not discard pending same-priority events
2929
Test-type: Integration
3030
Given a robot that calls a blocking method from within onScannedRobot
3131
When the same battle runs on both engines
3232
Then every scan event the classic run delivered is also delivered under the bridge
33-
# The defect this criterion exists for discarded exactly these events. Plan door: M-001.
33+
# Proven by BlockingScanConformanceTest with the bridge-owned BlockingScanProbe and sample.Target. Positive evidence requires repeated scan callbacks after the blocking handler; negative evidence requires that neither engine complete without a scan callback. Plan door: M-001.
3434
3535
@EVT-003 @retired
3636
Scenario: An interruptible handler is re-entered when a higher-priority event arrives
@@ -52,22 +52,21 @@ Feature: Event dispatch and timing parity
5252
# built matched Tank Royale Bot API and runner pair. AN-009 establishes the original server
5353
# cause; PDR-002 records why bridge evidence uses this local upstream build. Plan door: M-001.
5454
55-
@EVT-005 @draft
55+
@EVT-005
5656
Scenario: New-turn events arrive at the classic point in the turn
5757
Test-type: Integration
5858
Given a robot that records the turn number at each handler entry
5959
When the same battle runs on both engines
6060
Then each handler is entered at the same point in the turn on both engines
61-
# Draft: no test proves per-turn handler timing yet. The two tests once tagged EVT-005
62-
# proved round/battle completion instead and are now EVT-011; see G-002. Plan door: M-001.
61+
# Proven by TurnBoundaryConformanceTest with the bridge-owned TurnBoundaryProbe: each engine records matching event, status-snapshot, and peer turn clocks across multiple turns. The two tests once tagged EVT-005 proved round/battle completion instead and are now EVT-011; see G-002. Plan door: M-001.
6362
64-
@EVT-006 @draft
63+
@EVT-006
6564
Scenario: Custom events fire and can be removed
6665
Test-type: Integration
6766
Given a robot that registers a custom condition, reports when it fires, then removes it
6867
When the same battle runs on both engines
6968
Then the firing and the silence after removal match on both engines
70-
# Proven by the ported CustomEvents robot. Plan door: M-001.
69+
# Proven by CustomEventsConformanceTest with classic's CustomEvents robot for registration and priority delivery, plus the bridge-owned CustomEventRemovalProbe for removal and post-removal silence. Plan door: M-001.
7170
7271
@EVT-007 @retired
7372
Scenario: The death of another robot reaches the survivors
@@ -96,31 +95,30 @@ Feature: Event dispatch and timing parity
9695
Then neither engine's robot output contains the scan marker
9796
# Proven by EventPriorityConformanceTest with a bridge-owned probe and sample.Target fixture. The probe first raises scan priority and requires a scan callback inside onHitWall, then lowers scan priority and requires that callback to be absent. Successor to EVT-001; see IDR-005. Plan door: M-001.
9897
99-
@EVT-008 @draft
98+
@EVT-008
10099
Scenario: Skipped turns are reported to the robot
101100
Test-type: Integration
102101
Given a robot that deliberately overruns its turn and reports each skipped turn
103102
When the same battle runs on both engines
104103
Then skipped turns are reported on both engines
105-
# Proven by the ported SkipTurns robot. Plan door: M-001.
104+
# Proven by SkippedTurnsConformanceTest with a bounded-overrun bridge-owned probe that reports skipped-turn callbacks on both engines and rejects duplicate delivery. Plan door: M-001.
106105
107-
@EVT-009 @draft
106+
@EVT-009
108107
Scenario: An exception thrown out of a handler is handled as classic handles it
109108
Test-type: Integration
110109
Given a robot that throws from inside an event handler
111110
When the same battle runs on both engines
112111
Then the robot survives or dies identically, and the exception is reported on both engines
113-
# Proven by the ported Throwing robot. Plan door: M-001.
112+
# Proven by ThrowingConformanceTest with classic's Throwing robot. Both battles complete and report the same NullPointerException signature; IDR-006 records the bridge callback boundary that makes the failure observable. Plan door: M-001.
114113
115-
@EVT-010 @draft
114+
@EVT-010
116115
Scenario: A melee turn delivers every scan event it carries
117116
Test-type: Integration
118117
Given a robot that counts the scan events it receives per turn
119118
And a melee battle at the official melee parameters
120119
When the same battle runs on both engines
121120
Then the per-turn scan counts match on both engines
122-
# The division the harness has never run, and the one that carries the most
123-
# same-priority events per turn. Plan door: M-001.
121+
# Proven by MeleeScanConformanceTest with the bridge-owned MeleeScanProbe at the official ten-participant melee setup. Both engines emit per-turn counts, and every count is bounded by the nine opponents in the staged battle. Plan door: M-001.
124122
125123
@EVT-011
126124
Scenario: Round and battle completion each reach their handler exactly once

docs/capabilities/CAP-001-event-dispatch-parity/design.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
id: DES-001
33
type: design
44
status: active
5-
links: [CAP-001, IDR-001, IDR-005, ADR-001, ARCH-002]
5+
links: [CAP-001, IDR-001, IDR-005, IDR-006, ADR-001, ARCH-002]
66
title: Event dispatch and timing parity — design
77
provenance: inferred
88
reversal-cost: low
@@ -32,12 +32,16 @@ Delegating leaves one implementation to be correct. `ADR-001` covers the version
3232

3333
## Timing
3434

35-
Since Bot API 1.0.2, new-turn events dispatch at the end of `execute()`, which is classic Robocode's timing. The bridge previously needed a hook into the turn loop to force dispatch at the right moment; it no longer does, and that hook is gone.
35+
Since Bot API 1.0.2, new-turn events dispatch at the end of `execute()`, which is classic Robocode's timing. The bridge previously needed a hook into the turn loop to force dispatch at the right moment; it no longer does, and that hook is gone. `TurnBoundaryProbe` records the event time, the status snapshot time, and the peer clock on both engines across multiple turns so a dispatch at the wrong boundary is observable.
36+
37+
## Handler exceptions
38+
39+
The Bot API's event publisher catches subscriber exceptions so one callback cannot prevent other subscribers from receiving the event. That is compatible with classic's continued battle processing, but it hides the failure from the process logs that form conformance evidence. `BotPeer` therefore reports throwables at the legacy callback boundary and then returns to the Bot API queue; `IDR-006` records this narrow exception-reporting rule.
3640

3741
## The guard
3842

3943
`setInterruptible` is null-guarded. The Bot API permits the call at points where no event is currently being dispatched, and a robot may reach it through a code path where the current event is absent. The upstream fix landed in the Bot API across its language implementations under `C-006`; the guard here is the local defence.
4044

4145
## Where this design is most likely to be wrong
4246

43-
Melee. Everything above was reasoned about, and verified against, one-versus-one battles. A melee turn carries many same-priority scan events, and both the queue behaviour and the interaction between dispatch and blocking calls have more room to differ there. `EVT-010` exists because that case is unmeasured rather than because it is suspected.
47+
Melee. Everything above was reasoned about, and verified against, one-versus-one battles. A melee turn carries many same-priority scan events, and both the queue behaviour and the interaction between dispatch and blocking calls have more room to differ there. `EVT-010` now exercises the official ten-participant setup with a per-turn scan-count probe; the harness passes the participant count through to both engine runners.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
id: IDR-006
3+
type: decision
4+
status: inferred
5+
author: agent
6+
accepted-by: []
7+
links: [CAP-001, ARCH-003]
8+
title: Report legacy handler exceptions at the bridge callback boundary
9+
---
10+
11+
# IDR-006 — Report legacy handler exceptions at the bridge callback boundary
12+
13+
## Decision
14+
15+
`BotPeer` invokes every legacy robot event callback inside a bridge-owned boundary. If the callback throws, the boundary prints the throwable to the bot process's standard error and returns so the surrounding event queue can continue dispatching.
16+
17+
## Context
18+
19+
The matched Tank Royale Bot API catches subscriber exceptions during event publication and otherwise provides no observable error to the conformance harness. Classic Robocode reports a `NullPointerException` thrown from `onStatus` while continuing the battle, so delegating event ordering to the Bot API is not enough to preserve the classic observable contract.
20+
21+
## Why this way
22+
23+
The boundary is the narrowest place that sees the legacy callback before the Bot API swallows its exception. Reporting there preserves the Bot API's priority and queue implementation, keeps the robot lifecycle unchanged, and gives the harness the same error signature that classic exposes. Replacing the upstream dispatcher or stopping the bot would alter unrelated event and lifecycle behavior.
24+
25+
## Consequences
26+
27+
Future event adapters must route legacy callbacks through this boundary so handler failures remain observable. Error evidence comes from the isolated bot process logs under `ARCH-003`; the bridge does not add a second event queue or change the frozen `robocode.*` surface.

docs/decisions/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ A decision that changes a methodology contract inventories every live carrier th
2929
- [PDR-002 — Conformance uses locally built Tank Royale artifacts rather than waiting for releases](PDR-002-locally-built-tank-royale-artifacts-for-conformance.md) · `verified` — When bridge conformance needs a Tank Royale repair that is not released, build the Tank Royale Bot API and runner locally from the same upstream revision and use that pair for the comparison.
3030
- [IDR-004 — EVT-007's cross-engine death-order claim is retired; survivor delivery is measured directly](IDR-004-evt-007-scoped-to-observable-survivor-delivery.md) · `inferred` — Retire `EVT-007` and mint `EVT-014`: a surviving robot receives another robot's death event on each engine.
3131
- [IDR-005 — EVT-001's priority-order claim is retired; the filter boundary is measured directly](IDR-005-evt-001-scoped-to-classic-filter-behavior.md) · `inferred``EVT-001` retires and `EVT-015` measures the observable filter behavior.
32+
- [IDR-006 — Report legacy handler exceptions at the bridge callback boundary](IDR-006-report-legacy-handler-exceptions-at-the-bridge-boundary.md) · `inferred``BotPeer` invokes every legacy robot event callback inside a bridge-owned boundary.
3233
<!-- clue:index:end -->

0 commit comments

Comments
 (0)