Files
FT546-WCS/docs/superpowers/plans/2026-08-07-javaTest-floor-transfer-dispatch.md

9.9 KiB

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

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

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

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.