docs(javaTest): design floor transfer orchestration
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
# javaTest Floor Transfer Dispatch 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:** 让中心调度把跨层车辆作为可行候选,幂等创建并等待换层作业,完成后从实际出口重新规划并执行父业务任务。
|
||||
|
||||
**Architecture:** 提升机保持在普通 `GridMap` 之外。`FloorTransferGateway` 是中心调度与现有 WCS 的出站端口,`SimulatedFloorTransferGateway` 提供确定性离线实现;`HistoricalDispatchSimulator` 保存换层中的父任务和车辆锁,完成事实后再创建普通 `ActiveTask`。
|
||||
|
||||
**Tech Stack:** Java 8, JUnit 5, Maven Surefire, Java `HttpServer`, vanilla HTML/CSS/JavaScript.
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- 历史 `agv_id` 与 `path_info` 只用于对照,不参与强制选车和路径结果。
|
||||
- 提升机不能编译成 `GridMap` 普通边。
|
||||
- 同一车辆不能同时绑定换层作业、业务任务或清障任务。
|
||||
- 相同幂等键只能创建一个换层作业;重复完成不能重复移动、归档或回调。
|
||||
- 换层完成后必须从完成事实的实际出口重新规划。
|
||||
- 现有 240 条同层历史负载结果必须保持 240/0/0 和零安全违规。
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Floor transfer domain and deterministic gateway
|
||||
|
||||
**Files:**
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/AssignmentMode.java`
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/FloorTransferJob.java`
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/FloorTransferGateway.java`
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/SimulatedFloorTransferGateway.java`
|
||||
- Create: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/FloorTransferTopology.java`
|
||||
- Test: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulatedFloorTransferGatewayTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `FloorTransferGateway.submit(FloorTransferJob)`, `advance(String)`, `snapshot(String)` and immutable completion facts.
|
||||
- Produces: `FloorTransferTopology.plan(vehicleSite, vehicleFloor, targetFloor, targetSite, GridMap, RouteCandidatePlanner)` returning a feasible source/target port pair.
|
||||
|
||||
- [ ] **Step 1: Write failing gateway idempotency and lifecycle tests**
|
||||
|
||||
```java
|
||||
FloorTransferGateway.Submission first = gateway.submit(job);
|
||||
FloorTransferGateway.Submission duplicate = gateway.submit(job);
|
||||
assertEquals(first.getJob().getIdempotencyKey(), duplicate.getJob().getIdempotencyKey());
|
||||
assertEquals(1, gateway.createdJobCount());
|
||||
assertEquals(FloorTransferStatus.COMPLETED, gateway.advance(job.getIdempotencyKey()).getStatus());
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the focused test and verify RED**
|
||||
|
||||
Run: `mvn -Dtest=SimulatedFloorTransferGatewayTest test`
|
||||
Expected: compilation failure because the floor-transfer types do not exist.
|
||||
|
||||
- [ ] **Step 3: Implement the minimal strong types and in-memory gateway**
|
||||
|
||||
The gateway stores jobs by idempotency key, rejects a different active job when its single simulated lift is occupied, advances deterministically from `SUBMITTED` to `RUNNING` to `COMPLETED`, and returns the configured actual exit site. Every public method receives business-oriented Chinese Javadoc and non-obvious state transitions receive inline comments.
|
||||
|
||||
- [ ] **Step 4: Run focused tests and verify GREEN**
|
||||
|
||||
Run: `mvn -Dtest=SimulatedFloorTransferGatewayTest test`
|
||||
Expected: all gateway lifecycle, duplicate submit and duplicate completion assertions pass.
|
||||
|
||||
### Task 2: Center dispatch orchestration
|
||||
|
||||
**Files:**
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInput.java`
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/HistoricalSimulationInputFactory.java`
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/simulation/PointToPointSimulationInputFactory.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/SimulationTaskResult.java`
|
||||
- Test: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: Task 1 gateway and topology.
|
||||
- Produces: task result fields `AssignmentMode getAssignmentMode()`, `int getFloorTransferCount()`, `List<FloorTransferJob> getFloorTransferJobs()`.
|
||||
- Produces: audit events `FLOOR_TRANSFER_SUBMITTED`, `FLOOR_TRANSFER_RUNNING`, `FLOOR_TRANSFER_HOLD`, `FLOOR_TRANSFER_COMPLETED`, `POST_TRANSFER_REPLAN`.
|
||||
|
||||
- [ ] **Step 1: Write failing same-floor and cross-floor orchestration tests**
|
||||
|
||||
```java
|
||||
assertEquals(AssignmentMode.DIRECT, direct.getAssignmentMode());
|
||||
assertEquals(AssignmentMode.FLOOR_TRANSFER, crossFloor.getAssignmentMode());
|
||||
assertEquals(1, crossFloor.getFloorTransferCount());
|
||||
assertTrue(events.stream().anyMatch(e -> "POST_TRANSFER_REPLAN".equals(e.getType())));
|
||||
```
|
||||
|
||||
The cross-floor fixture has no eligible vehicle on the task floor, uses separate floor-local graph components, and configures `LIFT-1/LIFT-2` outside ordinary edges.
|
||||
|
||||
- [ ] **Step 2: Run the focused simulator test and verify RED**
|
||||
|
||||
Run: `mvn -Dtest=HistoricalDispatchSimulatorTest test`
|
||||
Expected: compilation failure for missing assignment mode and transfer result fields.
|
||||
|
||||
- [ ] **Step 3: Add candidate feasibility without bypassing VehicleAssignmentService**
|
||||
|
||||
Build direct candidates from ordinary approach paths. Build cross-floor candidates only when the topology can reach the source port and target port can reach the task source. Pass both sets to the existing `VehicleAssignmentService`, preserving its stable same-floor preference.
|
||||
|
||||
- [ ] **Step 4: Add transfer lock and completion orchestration**
|
||||
|
||||
On a cross-floor decision, submit one idempotent job, remove the parent from the normal queue, lock the vehicle in `floorTransfers`, and emit submission evidence. Each tick advances the gateway. A submitted job surviving a vehicle fault/restart remains locked; once the vehicle recovers and the gateway reports completion, update the vehicle from the actual exit, atomically occupy the exit node, replan approach/service paths, reserve the route, create `ActiveTask`, and emit completion/replan events.
|
||||
|
||||
- [ ] **Step 5: Cover missing topology, lock, duplicate completion and recovery**
|
||||
|
||||
Add tests proving no second assignment uses a transfer-locked vehicle, missing ports close as `NO_ROUTE`, duplicate gateway facts have one effect, and disconnect/restart during transfer resumes the original job rather than selecting another vehicle.
|
||||
|
||||
- [ ] **Step 6: Run simulator and fault tests and verify GREEN**
|
||||
|
||||
Run: `mvn -Dtest=HistoricalDispatchSimulatorTest,HistoricalDispatchFaultMatrixTest,SimulationAdaptersTest test`
|
||||
Expected: all direct, cross-floor, recovery, resource, archive and WMS assertions pass.
|
||||
|
||||
### Task 3: Visualization and report evidence
|
||||
|
||||
**Files:**
|
||||
- Modify: `javaTest/src/main/java/com/ft546/wcs/shadow/history/visualizer/SimulationVisualizationMapper.java`
|
||||
- Modify: `javaTest/src/main/resources/visualizer/index.html`
|
||||
- Modify: `javaTest/src/main/resources/visualizer/assets/app.js`
|
||||
- Modify: `javaTest/src/main/resources/visualizer/assets/app.css`
|
||||
- Test: `javaTest/src/test/java/com/ft546/wcs/shadow/history/visualizer/SimulationVisualizationMapperTest.java`
|
||||
- Test: `javaTest/src/test/java/com/ft546/wcs/shadow/history/visualizer/PointToPointSimulationServiceTest.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: Task 2 task result and event types.
|
||||
- Produces: JSON task fields `assignmentMode`, `floorTransferCount`, `floorTransferJobs`; event rows retain source/target transfer ports.
|
||||
|
||||
- [ ] **Step 1: Write failing mapper assertions**
|
||||
|
||||
```java
|
||||
assertEquals("FLOOR_TRANSFER", taskPayload.get("assignmentMode"));
|
||||
assertEquals(1, taskPayload.get("floorTransferCount"));
|
||||
assertFalse(((List<?>) taskPayload.get("floorTransferJobs")).isEmpty());
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run mapper/service tests and verify RED**
|
||||
|
||||
Run: `mvn -Dtest=SimulationVisualizationMapperTest,PointToPointSimulationServiceTest test`
|
||||
Expected: new JSON fields are absent.
|
||||
|
||||
- [ ] **Step 3: Map and render transfer evidence**
|
||||
|
||||
Expose the new fields through `SimulationVisualizationMapper`. Add a compact assignment-mode and floor-transfer section to the task inspector. Render transfer events as a cross-floor operation with source and destination floor labels; do not append the lift transition to the normal route polyline.
|
||||
|
||||
- [ ] **Step 4: Run mapper/server tests and verify GREEN**
|
||||
|
||||
Run: `mvn -Dtest=SimulationVisualizationMapperTest,PointToPointSimulationServiceTest,HistoricalDispatchVisualizerServerTest test`
|
||||
Expected: API payloads contain the transfer evidence and all HTTP smoke tests pass.
|
||||
|
||||
### Task 4: Full regression and audit
|
||||
|
||||
**Files:**
|
||||
- Modify only if a verified failure requires a scoped correction.
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: all prior tasks.
|
||||
- Produces: fresh Maven, 240-task replay, browser and independent review evidence.
|
||||
|
||||
- [ ] **Step 1: Run the complete Maven suite**
|
||||
|
||||
Run: `mvn clean test`
|
||||
Expected: all discovered tests pass with zero failures, errors and skips.
|
||||
|
||||
- [ ] **Step 2: Run the 240-task deterministic replay twice**
|
||||
|
||||
Run the existing real-data simulation acceptance test twice and compare `canonicalView`/core evidence. Expected: 240 completed, 0 waiting, 0 failed, no safety violations, no duplicate archive and no duplicate WMS business effect.
|
||||
|
||||
- [ ] **Step 3: Start the visualizer and perform browser QA**
|
||||
|
||||
Start on an available localhost port. Verify desktop `1440x1000` and mobile `390x844`, run a forced cross-floor fixture/request, inspect transfer events, confirm the normal route line does not draw a fake cross-floor edge, and check the browser console for errors.
|
||||
|
||||
- [ ] **Step 4: Request independent code review and resolve findings**
|
||||
|
||||
Provide the reviewer this spec, plan, base SHA and final diff. Fix all Critical and Important findings, rerun the affected focused tests and the complete suite, then record final evidence in the implementation commit.
|
||||
Reference in New Issue
Block a user