docs(javaTest): plan bounded conflict-aware routing
This commit is contained in:
@@ -0,0 +1,480 @@
|
|||||||
|
# javaTest Bounded Conflict-Aware Routing Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Replace the historical replay's final BFS route choice with deterministic, 110%-bounded, traffic-aware approach and service route selection, add safe third-HOLD rerouting, and expose auditable evidence in reports and the full-map browser.
|
||||||
|
|
||||||
|
**Architecture:** Keep `GridPathPlanner` unchanged as the compatibility shortest-edge baseline. Add a pure traffic-package candidate generator and quality evaluator, then adapt the historical simulator through immutable planning evidence and an atomic corridor-reservation replacement operation. Reporting and the browser consume stored decisions and events; neither layer reruns the planner or invents route evidence.
|
||||||
|
|
||||||
|
**Tech Stack:** Java 8, Maven, JUnit 5, Jackson already present in `javaTest`, vanilla HTML/CSS/JavaScript, Playwright/browser verification, no new production dependency.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Map
|
||||||
|
|
||||||
|
New traffic-domain files:
|
||||||
|
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RoutePlanningPolicy.java`: immutable 110% and 32-candidate limits.
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteCandidate.java`: one immutable loopless path and coordinate distance.
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteCandidateSet.java`: shortest baseline plus bounded candidates and limit evidence.
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteCandidatePlanner.java`: deterministic Dijkstra baseline and K-shortest loopless enumeration.
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficRouteSnapshot.java`: immutable occupied-node, directed-reservation and active-route evidence.
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteQuality.java`: comparable business tuple.
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteCandidateEvaluation.java`: candidate plus quality.
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RoutePlanDecision.java`: selected candidate and all decision evidence.
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteQualityEvaluator.java`: metric calculation and lexicographic selection.
|
||||||
|
|
||||||
|
New simulation-domain files:
|
||||||
|
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/RoutePlanningEvidence.java`: immutable approach/service planning record with version and reroute outcome.
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/TrafficHoldTracker.java`: exact three-consecutive-cycle trigger keyed by task, vehicle, resource and reason.
|
||||||
|
- `javaTest/src/main/java/com/ft546/wcs/shadow/history/visualizer/HistoricalRouteQualityMapper.java`: authoritative historical comparability and quality classification.
|
||||||
|
|
||||||
|
Modified files:
|
||||||
|
|
||||||
|
- `CorridorReservationManager.java`: reservation snapshot plus atomic `replaceRoute`.
|
||||||
|
- `HistoricalDispatchSimulator.java`: candidate-based initial planning, traffic snapshot construction, third-HOLD rerouting, movable active route, evidence capture.
|
||||||
|
- `SimulationTaskResult.java`: expose approach/service decisions and reroute count without changing existing fields.
|
||||||
|
- `HistoricalDispatchSimulationReportWriter.java`: add route-quality/comparability and reroute sections.
|
||||||
|
- `SimulationVisualizationMapper.java`: add decision evidence and fair historical comparison to JSON.
|
||||||
|
- `RouteTopologyEvidenceMapper.java`: reuse authoritative endpoint/edge validation for comparability.
|
||||||
|
- `javaTest/src/main/resources/history-visualizer/index.html`: add route decision and reroute inspector sections.
|
||||||
|
- `javaTest/src/main/resources/history-visualizer/app.js`: render selected candidates, path versions, HOLD point and before/after reroute.
|
||||||
|
- `javaTest/src/main/resources/history-visualizer/app.css`: restrained table, badge and route-layer styling.
|
||||||
|
|
||||||
|
## Task 1: Deterministic Bounded Candidate Generation
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
|
||||||
|
- Create: `javaTest/src/test/java/com/ft546/wcs/demo/traffic/RouteCandidatePlannerTest.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RoutePlanningPolicy.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteCandidate.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteCandidateSet.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteCandidatePlanner.java`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Write focused failing tests**
|
||||||
|
|
||||||
|
Create hand-checked fixtures covering Euclidean distance, an exactly-110% route, an over-limit route, loop rejection, stable canonical ordering, 32-candidate truncation, unknown endpoints and permanent blocked nodes. The primary public contract is:
|
||||||
|
|
||||||
|
```java
|
||||||
|
RouteCandidateSet result = new RouteCandidatePlanner().plan(
|
||||||
|
map, "A", "D", Collections.<String>emptySet(),
|
||||||
|
new RoutePlanningPolicy(1.10d, 32));
|
||||||
|
assertEquals(Arrays.asList("A", "B", "D"), result.getShortestPath());
|
||||||
|
assertEquals(2.0d, result.getShortestPhysicalDistance(), 0.000001d);
|
||||||
|
assertEquals(Arrays.asList("A", "B", "D"), result.getCandidates().get(0).getPath());
|
||||||
|
assertTrue(result.getCandidates().stream()
|
||||||
|
.allMatch(candidate -> candidate.getPhysicalDistance() <= 2.2d + 0.000001d));
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify RED**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=RouteCandidatePlannerTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: compilation fails because `RouteCandidatePlanner` and its DTOs do not exist.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement the pure candidate module**
|
||||||
|
|
||||||
|
Use Euclidean edge distance from `Site.x/y`. Compute the deterministic Dijkstra baseline with `(distance, canonicalPath)` ordering. Implement Yen's K-shortest loopless algorithm: for each accepted path, remove the root-prefix edges/nodes needed for each spur calculation, run the same deterministic Dijkstra for the spur path, deduplicate by complete node sequence, and order the candidate heap by `(distance, canonicalPath)`. Discard candidates above `shortestDistance * detourRatio`, stop after 32 accepted candidates, and set `candidateLimitReached` only if another admissible path exists. Treat `GridMap.getBlockedSites()` plus the supplied permanent-block set as static exclusions, while allowing the start node itself.
|
||||||
|
|
||||||
|
Public signatures:
|
||||||
|
|
||||||
|
```java
|
||||||
|
public RouteCandidateSet plan(GridMap map, String source, String target,
|
||||||
|
Set<String> permanentlyBlockedSites,
|
||||||
|
RoutePlanningPolicy policy);
|
||||||
|
public double pathDistance(GridMap map, List<String> path);
|
||||||
|
```
|
||||||
|
|
||||||
|
All returned lists are defensive, unmodifiable copies. Empty candidates and empty shortest path mean permanent map unreachability.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Verify GREEN and compatibility**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=RouteCandidatePlannerTest,TrafficControllerTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: all selected tests pass; existing BFS tests remain unchanged.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add javaTest/src/main/java/com/ft546/wcs/demo/traffic javaTest/src/test/java/com/ft546/wcs/demo/traffic/RouteCandidatePlannerTest.java
|
||||||
|
git commit -m "feat(javaTest): generate bounded route candidates"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 2: Traffic Snapshot and Lexicographic Route Quality
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
|
||||||
|
- Create: `javaTest/src/test/java/com/ft546/wcs/demo/traffic/RouteQualityEvaluatorTest.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficRouteSnapshot.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteQuality.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteCandidateEvaluation.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RoutePlanDecision.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteQualityEvaluator.java`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Write focused failing tests**
|
||||||
|
|
||||||
|
Build literal two-route fixtures proving the fixed priority order independently: opposite direction beats every lower metric; occupied nodes beat reserved-edge conflicts; reserved-edge conflicts beat active overlap; overlap beats turns; turns beat distance; distance beats canonical path. Also prove self-owned resources and the current vehicle's first node do not count, reverse reservations are not double-counted as incompatible, active-route overlap is undirected, and repeated evaluation is deterministic.
|
||||||
|
|
||||||
|
```java
|
||||||
|
RoutePlanDecision decision = evaluator.select(
|
||||||
|
map, candidates, TrafficRouteSnapshot.builder()
|
||||||
|
.occupyNode("B", "OTHER-AGV")
|
||||||
|
.reserveEdge("A", "B", "OTHER-TASK")
|
||||||
|
.activeRoute("OTHER-TASK", Arrays.asList("A", "B", "D"))
|
||||||
|
.build(),
|
||||||
|
"TASK-1", "AGV-1");
|
||||||
|
assertEquals(Arrays.asList("A", "C", "D"), decision.getSelectedPath());
|
||||||
|
assertEquals(0, decision.getSelectedQuality().getOppositeDirectionConflictCount());
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify RED**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=RouteQualityEvaluatorTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: compilation fails because the snapshot/evaluation contracts do not exist.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement immutable evidence and evaluator**
|
||||||
|
|
||||||
|
`RouteQuality.compareTo` compares exactly:
|
||||||
|
|
||||||
|
```java
|
||||||
|
oppositeDirectionConflictCount;
|
||||||
|
occupiedNodeCount;
|
||||||
|
incompatibleReservedEdgeCount;
|
||||||
|
activeRouteOverlapEdgeCount;
|
||||||
|
turnCount;
|
||||||
|
physicalDistance;
|
||||||
|
canonicalPath;
|
||||||
|
```
|
||||||
|
|
||||||
|
Count future nodes from path index 1. Count each candidate edge once per category. A turn occurs when normalized integer direction vectors for three consecutive same-floor sites differ. Return every evaluated candidate, the selected entry, `detourRatio`, and a stable reason naming the first metric that distinguishes the winner from the physical shortest candidate.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Verify GREEN**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=RouteCandidatePlannerTest,RouteQualityEvaluatorTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: all tests pass.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add javaTest/src/main/java/com/ft546/wcs/demo/traffic javaTest/src/test/java/com/ft546/wcs/demo/traffic
|
||||||
|
git commit -m "feat(javaTest): rank routes by live traffic quality"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 3: Atomic Corridor Reservation Replacement
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
|
||||||
|
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManagerTest.java`
|
||||||
|
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManager.java`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add failing reservation tests**
|
||||||
|
|
||||||
|
Add real-manager tests for successful replacement, rejection that leaves every old edge owned, preservation of shared same-direction holders, rank preservation, and snapshot direction/owner evidence.
|
||||||
|
|
||||||
|
```java
|
||||||
|
manager.reserve("T1", Arrays.asList("A", "B", "C"), 1, 10L);
|
||||||
|
manager.reserve("T2", Arrays.asList("D", "C"), 1, 20L);
|
||||||
|
ReservationDecision denied = manager.replaceRoute(
|
||||||
|
"T1", Arrays.asList("A", "D", "C"), 1, 10L);
|
||||||
|
assertFalse(denied.isGranted());
|
||||||
|
assertEquals("T1", manager.ownerFor("A", "B"));
|
||||||
|
assertEquals("T1", manager.ownerFor("B", "C"));
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify RED**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=CorridorReservationManagerTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: compilation fails because `replaceRoute` and `snapshot` are missing.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement precheck-then-commit replacement**
|
||||||
|
|
||||||
|
Add:
|
||||||
|
|
||||||
|
```java
|
||||||
|
public ReservationDecision replaceRoute(String taskId, List<String> newRoute,
|
||||||
|
int effectivePriority, long arrivalMillis);
|
||||||
|
public List<CorridorReservationSnapshot> snapshot();
|
||||||
|
```
|
||||||
|
|
||||||
|
During precheck, ignore the current task's own old holdings but retain other holders. Do not mutate `edges`, `taskEdges`, or `ranks` until all new edges pass. On success, remove only old holdings no longer present, add every new holding, replace the task's edge index and rank, and clean empty reservations. Preserve direction plus all holder IDs in the immutable snapshot.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Verify GREEN**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=CorridorReservationManagerTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: all tests pass.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManager.java javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManagerTest.java
|
||||||
|
git commit -m "feat(javaTest): replace route reservations atomically"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 4: Initial Approach and Service Route Integration
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/RoutePlanningEvidence.java`
|
||||||
|
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskResult.java`
|
||||||
|
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulator.java`
|
||||||
|
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add failing simulator tests**
|
||||||
|
|
||||||
|
Add a compact grid where shortest physical route has a live opposite reservation and a conflict-free path lies within 110%; assert the simulator still uses existing vehicle selection but chooses the safer approach/service route. Add a case where the clean detour exceeds 110%, and one where every candidate has temporary conflicts but the task remains dispatchable rather than `NO_ROUTE`. Assert selected distance, shortest distance, candidate count, stage and path version are stored.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify RED**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=HistoricalDispatchSimulatorTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: new safer-route/evidence assertions fail against BFS-only dispatch.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Integrate planning without changing vehicle assignment**
|
||||||
|
|
||||||
|
In `assignReadyTasks`, generate an approach candidate set for each eligible vehicle only to prove that vehicle can physically reach the source; pass every reachable eligible vehicle unchanged to the existing `VehicleAssignmentService`, whose same-floor/floor/y/x/vehicle-ID ranking remains authoritative. After selection, build one immutable traffic snapshot, independently select the chosen vehicle's approach and the task's service decisions, splice without duplicating the source, and reserve the full selected route. Set `plannedPath` to the selected service path for compatibility and append both decisions to `RoutePlanningEvidence` with `pathVersion=1`.
|
||||||
|
|
||||||
|
Permanent candidate-set emptiness is the only route-planning `NO_ROUTE`. A non-empty set with conflicts remains eligible and is passed to reservation/traffic HOLD behavior.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Verify GREEN and existing fault behavior**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=HistoricalDispatchSimulatorTest,HistoricalDispatchFaultMatrixTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: all tests pass; vehicle eligibility, PLC retry and fault closure behavior remain green.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java
|
||||||
|
git commit -m "feat(javaTest): plan traffic-aware approach and service routes"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 5: Third Traffic HOLD Rerouting
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
|
||||||
|
- Create: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/TrafficHoldTrackerTest.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/TrafficHoldTracker.java`
|
||||||
|
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulator.java`
|
||||||
|
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationTickEvent.java`
|
||||||
|
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add failing policy and integration tests**
|
||||||
|
|
||||||
|
Prove cycles 1 and 2 do not trigger, cycle 3 does, blocking-resource/reason/vehicle changes reset to 1, movement clears the streak, and PLC/fault/disconnect/low-battery events never enter the tracker. In simulator tests assert a strictly better remaining route causes `REROUTE_TRIGGER` then `REROUTE`; no better route yields `REROUTE_REJECTED`; failed atomic replacement preserves old route; a successful reroute cannot reroute again until one MOVE occurs.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify RED**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=TrafficHoldTrackerTest,HistoricalDispatchSimulatorTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: tracker types and reroute events are missing, and existing generic threshold remains 10.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement traffic-only reroute state machine**
|
||||||
|
|
||||||
|
Use key `(taskId, vehicleId, blockingResourceId, holdReason)`. Extract the blocking resource from the exact next node, canonical next edge, or corridor owner evidence. Only traffic-controller node/edge/opposite-direction decisions and `CORRIDOR_DIRECTION_OWNED` call the tracker. On the third identical HOLD:
|
||||||
|
|
||||||
|
1. emit `REROUTE_TRIGGER` with streak/resource/reason;
|
||||||
|
2. snapshot traffic once;
|
||||||
|
3. plan current position to source plus source to target before pickup, or current position to target after pickup;
|
||||||
|
4. compare new and current remaining `RouteQuality` using the same evaluator;
|
||||||
|
5. require a different, strictly better, bounded candidate;
|
||||||
|
6. call `replaceRoute` before replacing the mutable `ActiveTask.route` and route index;
|
||||||
|
7. increment path version and reroute count only after replacement succeeds;
|
||||||
|
8. require a subsequent MOVE before another ordinary reroute.
|
||||||
|
|
||||||
|
Store old/new remaining paths and both quality tuples in structured event detail rather than compressing them into display text. Keep the existing protocol-retry exhaustion and vehicle-fault redispatch paths separate.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Verify GREEN and safety tests**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=TrafficHoldTrackerTest,HistoricalDispatchSimulatorTest,CorridorReservationManagerTest,SimulationInvariantSummaryTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: all tests pass.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation
|
||||||
|
git commit -m "feat(javaTest): reroute after repeated traffic hold"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 6: Fair Historical Comparison and Report/API Evidence
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
|
||||||
|
- Create: `javaTest/src/test/java/com/ft546/wcs/shadow/history/visualizer/HistoricalRouteQualityMapperTest.java`
|
||||||
|
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/visualizer/HistoricalRouteQualityMapper.java`
|
||||||
|
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/visualizer/RouteTopologyEvidenceMapper.java`
|
||||||
|
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/visualizer/SimulationVisualizationMapper.java`
|
||||||
|
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriter.java`
|
||||||
|
- Modify: mapper and report-writer tests.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add failing mapping tests**
|
||||||
|
|
||||||
|
Test all three input classifications with literal paths: valid matching endpoints is `COMPARABLE`; valid map path with wrong endpoints is `ENDPOINT_MISMATCH`; unknown or non-adjacent segment is `INVALID_HISTORY_PATH` and takes precedence. For comparable paths assert exact categories: `EXACT_MATCH`, `SHORTER_PHYSICAL_DISTANCE`, `SAME_DISTANCE_BETTER_QUALITY`, `BOUNDED_DETOUR_FEWER_CONFLICTS`, `WORSE_QUALITY`. Assert non-comparable tasks are excluded from optimization counts.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify RED**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=HistoricalRouteQualityMapperTest,SimulationVisualizationMapperTest,HistoricalDispatchSimulationReportWriterTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: new classification and evidence fields are absent.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Extend stored result mapping and text report**
|
||||||
|
|
||||||
|
Expose per task:
|
||||||
|
|
||||||
|
```text
|
||||||
|
routeComparability, routeQualityComparison,
|
||||||
|
approachPlanningEvidence, servicePlanningEvidence,
|
||||||
|
pathVersions, rerouteCount, rerouteEvents
|
||||||
|
```
|
||||||
|
|
||||||
|
Expose summary counts for all comparability/quality categories, bounded-route violations, candidate-limit hits, reroute triggers/success/rejection reasons. Preserve raw `plannedPath` and `pathChanged`, label them explicitly as compatibility evidence, and update `plannerVersion` to the bounded conflict-aware version. Keep timing and PLC retry under operational evidence, never route score.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Verify GREEN**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=HistoricalRouteQualityMapperTest,RouteTopologyEvidenceMapperTest,SimulationVisualizationMapperTest,HistoricalDispatchSimulationReportWriterTest test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: all tests pass.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add javaTest/src/main/java/com/ft546/wcs/shadow/history javaTest/src/test/java/com/ft546/wcs/shadow/history
|
||||||
|
git commit -m "feat(javaTest): report auditable route quality evidence"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 7: Full-Map Route Decision and Reroute Inspector
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
|
||||||
|
- Modify: `javaTest/src/main/resources/history-visualizer/index.html`
|
||||||
|
- Modify: `javaTest/src/main/resources/history-visualizer/app.js`
|
||||||
|
- Modify: `javaTest/src/main/resources/history-visualizer/app.css`
|
||||||
|
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/visualizer/HistoricalSimulationVisualizerServerTest.java` or the existing visualizer HTTP test that owns these resources.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add failing API/resource interaction assertions**
|
||||||
|
|
||||||
|
Extend the real visualizer integration fixture so its result JSON includes stage decisions and reroute versions. Assert the HTML has stable inspector containers and the script renders from `approachPlanningEvidence`, `servicePlanningEvidence`, and `rerouteEvents`, not by rerunning path logic in JavaScript.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify RED**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=SimulationVisualizationMapperTest,*Visualizer*Test test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: inspector payload/container assertions fail.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement the inspector**
|
||||||
|
|
||||||
|
Keep the complete floor topology always visible. Add route-layer toggles for historical path, initial selected service route, current path version, actual MOVE trace, and HOLD/REROUTE points. In the task inspector show approach and service evidence in separate compact tables: shortest/selected coordinate distance, detour percent, candidate count/limit, each quality metric, decision reason and path version. Add a reroute timeline that selects a version and draws old/new remaining paths simultaneously with distinct solid/dashed styles. Mark `ENDPOINT_MISMATCH` and `INVALID_HISTORY_PATH` visibly so users cannot mistake raw path inequality for optimization.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Run focused tests and browser QA**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml -Dtest=SimulationVisualizationMapperTest,*Visualizer*Test test
|
||||||
|
```
|
||||||
|
|
||||||
|
Then start the app on `127.0.0.1:18084`, use the real point-to-point and historical result endpoints, and verify at desktop 1440x1000 and mobile 390x844: map nonblank, all route layers toggle, task selection updates evidence, reroute version selection changes overlays, no text overlap, no console error.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add javaTest/src/main/resources/history-visualizer javaTest/src/test/java/com/ft546/wcs/shadow/history/visualizer
|
||||||
|
git commit -m "feat(javaTest): inspect bounded route decisions on full map"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 8: Full Regression, 240-Task Replay and Completion Audit
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
|
||||||
|
- Modify only when a failing acceptance test exposes a real defect; add the reproducing test before the fix.
|
||||||
|
- Update: `javaTest/README.md` with route semantics, launch command and evidence legend.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Stop the visualizer and run clean regression**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -f javaTest/pom.xml clean test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: zero failures/errors/skips. Record total test count from Surefire rather than reusing the old 645-test baseline.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Run the real 240-task replay**
|
||||||
|
|
||||||
|
Run the established historical simulation application/report command and verify directly:
|
||||||
|
|
||||||
|
- completed + waiting + failed = 240;
|
||||||
|
- waiting = 0 and every task is terminal;
|
||||||
|
- selected approach/service distance is at most 110% plus numeric tolerance;
|
||||||
|
- every selected route is the lexicographic winner among emitted candidates;
|
||||||
|
- node double occupancy, edge capacity violation, opposite-direction swap and deadlock are all 0;
|
||||||
|
- archive count equals completed count with zero duplicate archive attempt;
|
||||||
|
- WMS business effects equal completed count with zero duplicate effect;
|
||||||
|
- every failure, HOLD, retry and reroute rejection has a nonblank reason.
|
||||||
|
|
||||||
|
Capture completed/waiting/failed, per-vehicle counts, vehicle changes, comparable-route quality counts, HOLD/retry reasons, waiting/completion average/P95/P99, historical-versus-simulation duration, reroute counts and safety/archive/WMS results.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Verify determinism**
|
||||||
|
|
||||||
|
Execute the same replay twice and compare canonical route-decision output after excluding wall-clock/server metadata. Expected: identical vehicle choices, selected paths, quality tuples, reasons and path versions.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Browser verification and screenshots**
|
||||||
|
|
||||||
|
Restart `127.0.0.1:18084`; inspect at least one exact-match task, one endpoint mismatch, one invalid historical path, one bounded detour if produced, and one rerouted task if produced. Capture desktop and mobile screenshots and check browser console plus canvas/SVG pixel content.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Independent review and defect loop**
|
||||||
|
|
||||||
|
Request a clean-context read-only code review from the design commit through current HEAD. Fix every Critical/Important finding with a failing regression test, rerun focused and full verification, and request a final finding check.
|
||||||
|
|
||||||
|
- [ ] **Step 6: Update README and commit verification documentation**
|
||||||
|
|
||||||
|
Document that this module is offline in-memory validation, route distance is coordinate units, timing is operational evidence, temporary conflicts do not imply `NO_ROUTE`, and production release still requires site/HIL validation.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add javaTest/README.md
|
||||||
|
git commit -m "docs(javaTest): explain conflict-aware route audit"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Final Requirement Audit
|
||||||
|
|
||||||
|
Before completion, re-read the approved design and point each gate to fresh evidence:
|
||||||
|
|
||||||
|
- route bound, deterministic winner, temporary-conflict handling;
|
||||||
|
- traffic-only third-HOLD trigger and anti-oscillation;
|
||||||
|
- atomic replacement and segment-by-segment resource safety;
|
||||||
|
- 240-task terminal/archive/WMS closure;
|
||||||
|
- fair historical comparability;
|
||||||
|
- report/API/UI decision evidence;
|
||||||
|
- full Maven suite, replay, browser interaction, console and visual checks;
|
||||||
|
- independent review with no unresolved Critical or Important finding.
|
||||||
|
|
||||||
|
Do not describe the algorithm as production-proven. The valid conclusion is that the offline Java simulation satisfies its verified gates on the bundled map, task history and deterministic fault plan.
|
||||||
Reference in New Issue
Block a user