docs: plan complete center dispatch simulation
This commit is contained in:
@@ -0,0 +1,442 @@
|
||||
# WCS Complete Center Dispatch Simulation 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:** Make all 240 frozen historical tasks complete deterministically through independent center dispatch, full-grid path planning, traffic arbitration, PLC simulation, node movement, archive, and idempotent WMS completion.
|
||||
|
||||
**Architecture:** Extend the frozen dataset with a separately hashed complete `wcs_srgv_map` projection and compile routing topology solely from passable grid cells. Resolve business aliases before scheduling, then use explicit corridor direction ownership and real internal clearance moves to guarantee progress without weakening node/edge safety. Historical vehicle, path, finish time, and completed status remain comparison data only.
|
||||
|
||||
**Tech Stack:** Java 8, Maven, JUnit 5, Jackson, Apache POI, existing in-memory dispatcher/path planner/SHADOW traffic coordinator.
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- Work only under `javaTest` and `docs`; do not modify any `ruoyi-*` production module.
|
||||
- `path_info` must never create a node, edge, endpoint, candidate vehicle, or route-planning decision.
|
||||
- Full-map input is a read-only bounded snapshot of `dbo.wcs_srgv_map`; include no connection strings, addresses, or credentials.
|
||||
- Passability is exactly `value IN (1,2)` and edges are same-floor Manhattan adjacency only.
|
||||
- `tsj` resolves by the production alias rule `07050{floor}`.
|
||||
- Real-data acceptance is exactly `240 COMPLETED / 0 WAITING / 0 FAILED`; watchdog or tick exhaustion fails the test.
|
||||
- Final invariants are archive `240`, WMS attempts `480`, WMS business effects `240`, deadlocks `0`, and all safety violations `0`.
|
||||
- Add every behavior test first, run it, and observe the expected failure before changing implementation.
|
||||
- Keep `map-sites.json` unchanged because legacy replay tests rely on its historical-path semantics.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Freeze and verify the complete grid snapshot
|
||||
|
||||
**Files:**
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalMapCell.java`
|
||||
- Create: `javaTest/src/test/resources/shadow/history/full-map-grid.json`
|
||||
- Modify: `javaTest/src/test/resources/shadow/history/manifest.json`
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueDataset.java`
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/HistoricalQueueLoader.java`
|
||||
- Create: `javaTest/src/test/java/com/ft546/wcs/shadow/history/HistoricalQueueLoaderTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `HistoricalMapCell(String siteId, int x, int y, int z, int value, String axy, String warehouse, String spaceArea)` with getters.
|
||||
- Produces: `HistoricalQueueDataset.getFullMapCells(): List<HistoricalMapCell>`, `getFullMapSha256(): String`, and `getFullMapRows(): int`.
|
||||
- Consumes later: the exact frozen cell list; no later task reads `map-sites.json` for routing.
|
||||
|
||||
- [ ] **Step 1: Add a failing loader contract test**
|
||||
|
||||
```java
|
||||
@Test
|
||||
void loadsAndVerifiesTheIndependentCompleteGridSnapshot() {
|
||||
HistoricalQueueDataset data = new HistoricalQueueLoader().load(
|
||||
getClass().getClassLoader(), "shadow/history");
|
||||
assertEquals(2552, data.getFullMapRows());
|
||||
assertEquals(2552, data.getFullMapCells().size());
|
||||
assertEquals(1175, data.getFullMapCells().stream()
|
||||
.filter(cell -> cell.getValue() == 1 || cell.getValue() == 2).count());
|
||||
assertEquals(64, data.getFullMapSha256().length());
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the focused test and observe RED**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=HistoricalQueueLoaderTest#loadsAndVerifiesTheIndependentCompleteGridSnapshot test`
|
||||
|
||||
Expected: compilation fails because the full-map accessors do not exist.
|
||||
|
||||
- [ ] **Step 3: Export the bounded read-only projection and calculate its canonical hash**
|
||||
|
||||
Use the configured read-only SQL Server connection to query, ordered deterministically:
|
||||
|
||||
```sql
|
||||
SELECT site_id, x, y, z, value, axy, warehouse, space_area
|
||||
FROM dbo.wcs_srgv_map
|
||||
ORDER BY z, y, x, site_id;
|
||||
```
|
||||
|
||||
Write the JSON array to `full-map-grid.json`; verify 2,552 rows, 1,175 passable rows, nonblank unique passable IDs, and unique passable `(x,y,z)` coordinates. Add `fullMapRows: 2552` and `sha256.full-map-grid.json` to `manifest.json`.
|
||||
|
||||
- [ ] **Step 4: Implement strict parsing and verification**
|
||||
|
||||
Load `full-map-grid.json` beside the existing three resources, call `verifySha256`, reject blank/duplicate passable IDs and duplicate passable coordinates, and reject a manifest row-count mismatch. Preserve all existing constructor data and make both new lists immutable.
|
||||
|
||||
- [ ] **Step 5: Run loader and legacy replay tests GREEN**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=HistoricalQueueLoaderTest,HistoricalQueueDatabaseReplayTest test`
|
||||
|
||||
Expected: all tests pass and the old 240-row replay contract is unchanged.
|
||||
|
||||
- [ ] **Step 6: Commit the data contract**
|
||||
|
||||
```bash
|
||||
git add javaTest/src/main/java/com/ft546/wcs/shadow/history javaTest/src/test/resources/shadow/history javaTest/src/test/java/com/ft546/wcs/shadow/history/HistoricalQueueLoaderTest.java
|
||||
git commit -m "test(javaTest): freeze complete WCS grid snapshot"
|
||||
```
|
||||
|
||||
### Task 2: Compile routing topology from grid semantics only
|
||||
|
||||
**Files:**
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompiler.java`
|
||||
- Create: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompilerTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `List<HistoricalMapCell>` from Task 1.
|
||||
- Produces: `HistoricalGridMapCompiler.compile(List<HistoricalMapCell>): CompiledHistoricalMap`.
|
||||
- Produces: `CompiledHistoricalMap.getGridMap(): GridMap`, `getTrafficMap(): EffectiveTrafficMap`, `getPassableSites(): Map<String,HistoricalMapCell>`, and `getComponentId(String): int`.
|
||||
|
||||
- [ ] **Step 1: Add failing grid-only topology tests**
|
||||
|
||||
```java
|
||||
@Test
|
||||
void connectsOnlyPassableSameFloorManhattanNeighbors() {
|
||||
List<HistoricalMapCell> cells = Arrays.asList(
|
||||
cell("A", 1, 1, 1, 1), cell("B", 2, 1, 1, 2),
|
||||
cell("BLOCK", 1, 2, 1, 0), cell("DIAGONAL", 2, 2, 1, 1),
|
||||
cell("UP", 1, 1, 2, 1));
|
||||
CompiledHistoricalMap map = new HistoricalGridMapCompiler().compile(cells);
|
||||
assertEquals(new LinkedHashSet<String>(Arrays.asList("A", "B", "DIAGONAL")),
|
||||
map.getGridMap().getSites().keySet());
|
||||
assertTrue(map.getGridMap().getNeighbors("A").contains("B"));
|
||||
assertFalse(map.getGridMap().getNeighbors("A").contains("DIAGONAL"));
|
||||
assertFalse(map.getGridMap().getSites().containsKey("UP"));
|
||||
}
|
||||
```
|
||||
|
||||
Add a second fixture whose `HistoricalSimulationTask.historicalNodes` contains a fake adjacency and prove compilation is unchanged because the compiler accepts cells only.
|
||||
|
||||
- [ ] **Step 2: Run the test and observe RED**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=HistoricalGridMapCompilerTest test`
|
||||
|
||||
Expected: compilation fails because the compiler and result type do not exist.
|
||||
|
||||
- [ ] **Step 3: Implement deterministic map compilation**
|
||||
|
||||
Index passable cells by coordinate, add a `Site` for each, connect only the positive X and positive Y neighbors on the same floor, construct a capacity-1 `TrafficMapCompiler.MapDefinition`, and calculate connected components in site-ID-stable order. Reject duplicate IDs, duplicate coordinates, and edges with missing endpoints.
|
||||
|
||||
- [ ] **Step 4: Run focused tests GREEN**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=HistoricalGridMapCompilerTest test`
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompiler.java javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalGridMapCompilerTest.java
|
||||
git commit -m "feat(javaTest): compile routing map from full grid"
|
||||
```
|
||||
|
||||
### Task 3: Resolve physical endpoints independently of historical paths
|
||||
|
||||
**Files:**
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/PhysicalEndpointResolver.java`
|
||||
- Create: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/PhysicalEndpointResolverTest.java`
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactory.java`
|
||||
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactoryTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `PhysicalEndpointResolver.resolve(HistoricalQueueRecord, Map<String,HistoricalMapCell>): ResolvedEndpoints`.
|
||||
- Produces: `ResolvedEndpoints.getSource()`, `getTarget()`, and `getFloor()`.
|
||||
- Consumes: `CompiledHistoricalMap` from Task 2; factory builds tasks with historical nodes only for later comparison.
|
||||
|
||||
- [ ] **Step 1: Add failing alias and path-independence tests**
|
||||
|
||||
```java
|
||||
@ParameterizedTest
|
||||
@CsvSource({"1,070501", "2,070502", "3,070503"})
|
||||
void resolvesTsjByTheProductionFloorRule(int floor, String expected) {
|
||||
assertEquals(expected, resolver.resolve(record("START" + floor, "tsj", floor), sites).getTarget());
|
||||
}
|
||||
|
||||
@Test
|
||||
void changingOrRemovingHistoricalPathDoesNotChangePlannedInput() {
|
||||
HistoricalSimulationInput original = factory.create(dataset);
|
||||
HistoricalSimulationInput mutated = factory.create(copyWithMutatedPathInfo(dataset));
|
||||
assertEquals(planningView(original), planningView(mutated));
|
||||
}
|
||||
```
|
||||
|
||||
Also replace the old `238 schedulable / 2 failed` expectation with `240 / 0`, and assert all 240 resolved pairs belong to the same connected component.
|
||||
|
||||
- [ ] **Step 2: Run both tests and observe RED**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=PhysicalEndpointResolverTest,HistoricalSimulationInputFactoryTest test`
|
||||
|
||||
Expected: alias assertions or the `240 / 0` assertion fail because the factory still normalizes `path_info` into topology/endpoints.
|
||||
|
||||
- [ ] **Step 3: Implement endpoint resolution and refactor the factory**
|
||||
|
||||
Compile the full map once. Resolve ordinary IDs directly; for `tsj`, use the start cell floor and `07050` prefix. Reject unknown or cross-component endpoints as dataset contract errors. Sort records by `create_date/task_no/guid`, preserve historical path/time/vehicle fields in `HistoricalSimulationTask`, but never ask `HistoricalQueueNormalizer` to decide schedulability or topology.
|
||||
|
||||
- [ ] **Step 4: Initialize the fleet without constraining selection to historical AGVs**
|
||||
|
||||
Keep stable vehicle IDs `1`, `2`, `3` as the available fleet and place each at a deterministic passable start cell. Historical `agv_id` remains only in `HistoricalQueueRecord` for reassignment reporting.
|
||||
|
||||
- [ ] **Step 5: Run factory and planner tests GREEN**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=PhysicalEndpointResolverTest,HistoricalGridMapCompilerTest,HistoricalSimulationInputFactoryTest,HistoricalDispatchSimulatorTest test`
|
||||
|
||||
- [ ] **Step 6: 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): plan history tasks from physical endpoints"
|
||||
```
|
||||
|
||||
### Task 4: Replace whole-route rejection with deterministic corridor ownership
|
||||
|
||||
**Files:**
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManager.java`
|
||||
- Create: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManagerTest.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`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `reserve(taskId, directedRoute, effectivePriority, arrivalMillis): ReservationDecision`.
|
||||
- Produces: `releasePassedEdge(taskId, from, to)`, `releaseTask(taskId)`, and `ownerFor(edge): String`.
|
||||
- `ReservationDecision` exposes `isGranted()`, `getOwnerTaskId()`, and `getReason()`.
|
||||
|
||||
- [ ] **Step 1: Add failing ownership and starvation tests**
|
||||
|
||||
```java
|
||||
@Test
|
||||
void oppositeDirectionsHaveOneStableOwnerUntilTheConflictExit() {
|
||||
assertTrue(manager.reserve("HIGH", route("A","B","C"), 1, 20).isGranted());
|
||||
assertFalse(manager.reserve("LOW", route("C","B","A"), 5, 10).isGranted());
|
||||
manager.releasePassedEdge("HIGH", "B", "C");
|
||||
manager.releaseTask("HIGH");
|
||||
assertTrue(manager.reserve("LOW", route("C","B","A"), 0, 10).isGranted());
|
||||
}
|
||||
```
|
||||
|
||||
Add an integration assertion that same-direction routes can enter while next-segment capacity still serializes physical movement.
|
||||
|
||||
- [ ] **Step 2: Run tests and observe RED**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=CorridorReservationManagerTest,HistoricalDispatchSimulatorTest test`
|
||||
|
||||
- [ ] **Step 3: Implement reservations and integrate them**
|
||||
|
||||
Canonicalize each undirected edge, compare requested direction, choose ownership by effective priority then original arrival then task ID, and retain ownership until the current owner passes the last shared edge. Remove `hasOppositeRouteConflict`; keep the existing per-tick opposite-edge and `ResourceLedger` checks as authoritative safety guards.
|
||||
|
||||
- [ ] **Step 4: Preserve queue age on HOLD and redispatch**
|
||||
|
||||
Use `SimulationTaskQueue.requeue` without changing original arrival. Emit `HOLD` with `CORRIDOR_DIRECTION_OWNED` and `REDISPATCH` after the configured threshold, but do not count repeated HOLD as watchdog progress.
|
||||
|
||||
- [ ] **Step 5: Run focused tests GREEN and commit**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=CorridorReservationManagerTest,HistoricalDispatchSimulatorTest,SimulationTaskQueueTest test`
|
||||
|
||||
```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): arbitrate corridor direction ownership"
|
||||
```
|
||||
|
||||
### Task 5: Move idle blockers through real clearance tasks
|
||||
|
||||
**Files:**
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/ClearanceMovePlanner.java`
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/ClearanceMove.java`
|
||||
- Create: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/ClearanceMovePlannerTest.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`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `ClearanceMovePlanner.plan(blockingVehicle, ownerRemainingRoute, occupiedSites, reservedEdges, gridMap): Optional<ClearanceMove>`.
|
||||
- `ClearanceMove` exposes vehicle ID, source, target, planned nodes, inherited owner task ID, current node index, protocol attempt count, and completion state.
|
||||
|
||||
- [ ] **Step 1: Add a failing three-vehicle corridor scenario**
|
||||
|
||||
```java
|
||||
@Test
|
||||
void movesAnIdleBlockerNodeByNodeAndCompletesBothBusinessDirections() {
|
||||
HistoricalDispatchSimulationResult result = simulator.simulate(
|
||||
threeVehicleBlockedCorridorInput(), config, DeterministicFaultPlan.none());
|
||||
assertEquals(2, result.getCompletedCount());
|
||||
assertTrue(result.getEvents().stream().anyMatch(e -> "CLEARANCE_PLANNED".equals(e.getType())));
|
||||
assertTrue(result.getEvents().stream().anyMatch(e -> "CLEARANCE_MOVE".equals(e.getType())));
|
||||
assertEquals(0, result.getInvariants().getOppositeEdgeViolations());
|
||||
assertEquals(0, result.getInvariants().getNodeDoubleOccupancyViolations());
|
||||
}
|
||||
```
|
||||
|
||||
Assert every consecutive clearance event pair is adjacent in `GridMap`, proving no teleport.
|
||||
|
||||
- [ ] **Step 2: Run the scenario and observe RED**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=HistoricalDispatchSimulatorTest#movesAnIdleBlockerNodeByNodeAndCompletesBothBusinessDirections test`
|
||||
|
||||
Expected: no clearance event is produced and the scenario reaches HOLD/tick exhaustion.
|
||||
|
||||
- [ ] **Step 3: Implement deterministic clearance target selection**
|
||||
|
||||
Exclude the owner route, all vehicle positions, and reserved nodes/edges. Route to every remaining reachable candidate with the center path planner, then sort by path length, non-trunk preference, and site ID. Return empty only when the map has no legal clearance destination.
|
||||
|
||||
- [ ] **Step 4: Execute clearance through the normal movement chain**
|
||||
|
||||
Create an internal move when an idle vehicle blocks the owner route. Run every step through SHADOW arbitration, `ResourceLedger`, PLC send/ACK, vehicle move, and segment release. Do not archive or WMS-callback a clearance move. On completion, release it and replan the waiting business task.
|
||||
|
||||
- [ ] **Step 5: Add recovery behavior**
|
||||
|
||||
On disconnect, restart, low battery, vehicle fault, send failure, or exhausted ACK retry, release the unexecuted segment and replan or reschedule without changing the business task's original arrival time.
|
||||
|
||||
- [ ] **Step 6: Run scenario and fault matrix GREEN, then commit**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=ClearanceMovePlannerTest,HistoricalDispatchSimulatorTest,HistoricalDispatchFaultMatrixTest test`
|
||||
|
||||
```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): clear blocked routes with real vehicle moves"
|
||||
```
|
||||
|
||||
### Task 6: Enforce complete deterministic real-data acceptance
|
||||
|
||||
**Files:**
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulationProgressWatchdog.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/SimulationProgressWatchdogTest.java`
|
||||
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationRealDataTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Watchdog progress events are exactly business terminal transition, authorized vehicle node movement, or completed clearance move.
|
||||
- Real-data simulation throws `IllegalStateException` on watchdog/tick exhaustion rather than returning acceptable WAITING snapshots.
|
||||
|
||||
- [ ] **Step 1: Tighten the real-data test before implementation**
|
||||
|
||||
```java
|
||||
assertEquals(240, result.getCompletedCount());
|
||||
assertEquals(0, result.getWaitingCount());
|
||||
assertEquals(0, result.getFailedCount());
|
||||
assertEquals(240, result.getArchiveCount());
|
||||
assertEquals(480, result.getWmsDeliveryAttempts());
|
||||
assertEquals(240, result.getWmsBusinessEffects());
|
||||
assertEquals(0, result.getInvariants().getDeadlocks());
|
||||
assertEquals(0, result.getInvariants().totalSafetyViolations());
|
||||
assertEquals(result.canonicalView(), secondRun.canonicalView());
|
||||
```
|
||||
|
||||
Add assertions that all 240 planned paths contain only grid-adjacent cells and that mutating all historical `path_info` values leaves the canonical planned-route view unchanged.
|
||||
|
||||
- [ ] **Step 2: Run the real-data test and observe RED**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=HistoricalDispatchSimulationRealDataTest test`
|
||||
|
||||
Expected: at least the `240/0/0` assertion fails until direction ownership and clearance progress are complete.
|
||||
|
||||
- [ ] **Step 3: Distinguish progress from churn and fail fast**
|
||||
|
||||
Feed the watchdog only on the three approved progress events. Include active task IDs, owners, vehicle positions, and held reasons in the exception message. Make tick-limit exhaustion an exception for this acceptance configuration.
|
||||
|
||||
- [ ] **Step 4: Run twice and reconcile exact results**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=HistoricalDispatchSimulationRealDataTest test`
|
||||
|
||||
Expected: two identical runs, `240/0/0`, archive `240`, WMS `480/240`, deadlocks `0`, safety `0`.
|
||||
|
||||
- [ ] **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 "test(javaTest): require all history tasks to complete"
|
||||
```
|
||||
|
||||
### Task 7: Publish complete center-dispatch evidence
|
||||
|
||||
**Files:**
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationResult.java`
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriter.java`
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationApplication.java`
|
||||
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulationReportWriterTest.java`
|
||||
- Modify: `javaTest/README.md`
|
||||
- Create at runtime: `javaTest/outputs/wcs-history-driven-center-dispatch-<runId>/`
|
||||
|
||||
**Interfaces:**
|
||||
- Summary adds `fullMapRows`, `passableMapRows`, `fullMapSha256`, `plannerVersion`, and `pathInfoUsedForPlanning=false`.
|
||||
- Task CSV adds business/physical endpoints, historical/simulated vehicles, historical/new paths, wait/completion durations, HOLD/retry causes, archive count, and WMS attempt/effect counts.
|
||||
- Workbook contains overview, task detail, vehicle totals, HOLD/retry detail, safety invariants, and scope statement.
|
||||
|
||||
- [ ] **Step 1: Add failing report assertions**
|
||||
|
||||
```java
|
||||
assertEquals(240, summary.path("completedCount").asInt());
|
||||
assertFalse(summary.path("pathInfoUsedForPlanning").asBoolean(true));
|
||||
assertEquals(2552, summary.path("fullMapRows").asInt());
|
||||
assertEquals(480, summary.path("wmsDeliveryAttempts").asInt());
|
||||
assertTrue(Files.exists(output.resolve("readable-report.xlsx")));
|
||||
```
|
||||
|
||||
Open the workbook with POI and assert the overview contains status totals, per-vehicle totals, average/P95/P99 waits and completions, HOLD/retry causes, historical-vs-simulated duration difference, safety results, archive count, and WMS idempotency totals.
|
||||
|
||||
- [ ] **Step 2: Run report test and observe RED**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=HistoricalDispatchSimulationReportWriterTest test`
|
||||
|
||||
- [ ] **Step 3: Implement report fields and workbook**
|
||||
|
||||
Calculate percentile indexes deterministically from sorted millisecond durations. Derive HOLD/retry causes from events rather than hard-coded labels. Preserve full historical and planned paths in detail output. Include the statement `真实历史负载驱动纯内存仿真,不是现场 SHADOW/HIL/ACTIVE 验收` on the workbook overview.
|
||||
|
||||
- [ ] **Step 4: Generate a new evidence directory**
|
||||
|
||||
Run: `cd javaTest && mvn compile exec:java -Dexec.mainClass=com.ft546.wcs.shadow.history.simulation.HistoricalDispatchSimulationApplication -Dexec.args="outputs/wcs-history-driven-center-dispatch-20260731 100"`
|
||||
|
||||
Do not overwrite the old `18/112/110` output. Verify `manifest.sha256` covers `summary.json`, `task-results.csv`, `tick-events.csv`, `invariant-results.json`, and `readable-report.xlsx`.
|
||||
|
||||
- [ ] **Step 5: Run report test GREEN and commit**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=HistoricalDispatchSimulationReportWriterTest test`
|
||||
|
||||
```bash
|
||||
git add javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation javaTest/README.md javaTest/outputs/wcs-history-driven-center-dispatch-20260731
|
||||
git commit -m "docs(javaTest): publish complete center dispatch evidence"
|
||||
```
|
||||
|
||||
### Task 8: Full verification and independent review
|
||||
|
||||
**Files:**
|
||||
- Modify only files required by concrete review findings.
|
||||
|
||||
**Interfaces:**
|
||||
- Produces the final reproducible acceptance evidence and a clean worktree.
|
||||
|
||||
- [ ] **Step 1: Run the entire module suite**
|
||||
|
||||
Run: `cd javaTest && mvn clean test`
|
||||
|
||||
Expected: all tests pass with zero failures, errors, or skips.
|
||||
|
||||
- [ ] **Step 2: Run the real workload one more time after `clean`**
|
||||
|
||||
Run: `cd javaTest && mvn -Dtest=HistoricalDispatchSimulationRealDataTest test`
|
||||
|
||||
Expected: `240/0/0`, deterministic canonical view, archive `240`, WMS `480/240`, deadlocks and safety violations `0`.
|
||||
|
||||
- [ ] **Step 3: Reconcile evidence hashes and counts independently**
|
||||
|
||||
Recalculate SHA-256 for every manifest entry, count 240 task-result rows, check unique simulation IDs/task archive keys, count exactly 480 WMS delivery events and 240 business effects, and confirm no invariant row is nonzero.
|
||||
|
||||
- [ ] **Step 4: Request code review**
|
||||
|
||||
Use `superpowers:requesting-code-review` against the complete diff. Require findings to cite file and line and specifically inspect `path_info` data flow, full-map hash verification, clearance movement adjacency, corridor release, watchdog semantics, archive uniqueness, and WMS idempotency.
|
||||
|
||||
- [ ] **Step 5: Apply verified findings and rerun affected plus full tests**
|
||||
|
||||
Use `superpowers:receiving-code-review` for any finding. Reproduce it, add or adjust a failing test, make the smallest correction, then run `cd javaTest && mvn clean test` again.
|
||||
|
||||
- [ ] **Step 6: Check repository state**
|
||||
|
||||
Run: `git status --short && git log --oneline -8`
|
||||
|
||||
Expected: no uncommitted changes and all task commits present on `optimize/wcs`.
|
||||
Reference in New Issue
Block a user