Files
FT546-WCS/docs/superpowers/plans/2026-08-06-javaTest-dispatch-completion-audit.md

187 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# javaTest 调度闭环完成审计实施计划
> **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:** 保留 `RouteCandidatePlanner` 负责地图候选、`RouteQualityEvaluator` 负责同一交通快照下的字典序质量、`HistoricalDispatchSimulator` 负责真实业务闭环。新增约束集中在质量评价入口;新增业务测试使用小型 `HistoricalSimulationInput` 夹具,避免修改 240 条真实历史基线。报告和页面只验证 Java 已产生的证据,不在前端复制算法。
**Tech Stack:** Java 8、Maven Surefire、JUnit 5、Jackson、现有 vanilla HTML/JavaScript、Playwright 浏览器 QA。
## Global Constraints
- 历史 `path_info` 不得作为新规划输入。
- 历史 `agv_id` 不得强制绑定车辆。
- `finish_date` 和历史完成状态不得推进仿真完成。
- 路线质量不使用故障或等待时间。
- 临时冲突必须 HOLD;只有永久地图不可达才 `NO_ROUTE` 失效关闭。
- 所有修改限制在 `javaTest`、本审计设计/计划文档和本轮新增测试;保留用户已有 `docs/*.html`。
- Java 编译目标保持 8,不新增生产依赖。
---
### Task 1: 锁定路线评价输入和反向活动冲突
**Files:**
- Modify: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficRouteSnapshot.java`
- Modify: `javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteQualityEvaluator.java`
- Modify: `javaTest/src/test/java/com/ft546/wcs/demo/traffic/RouteQualityEvaluatorTest.java`
**Interfaces:**
- `TrafficRouteSnapshot` 新增包内查询 `hasOppositeActiveRoute(String from, String to, String taskId)`。
- `RouteQualityEvaluator.evaluate(...)` 继续返回 `RouteQuality`;非法节点、非邻接边或距离不一致时抛 `IllegalArgumentException`。
- [x] **Step 1: 写失败测试**
增加三个测试:活动路线 `D -> B -> A` 对候选 `A -> B -> D` 计入对向冲突;候选包含未知站点或断边时被拒绝;候选声明距离与地图距离不一致时被拒绝。现有同向活动路线仍只计重合,不重复计对向。
- [x] **Step 2: 运行 RED**
```bash
mvn -f javaTest/pom.xml -Dtest=RouteQualityEvaluatorTest test
```
预期新增断言失败或编译失败,证明测试没有被旧实现意外满足。
- [x] **Step 3: 实现最小修复**
在快照中遍历其他活动路线的有向相邻边,只有 `to -> from` 命中时返回对向;在评价入口调用 `RouteCandidatePlanner.pathDistance(map, path)` 校验路径连续性和距离,使用数值容差 `1e-6`,再执行现有质量元组计算。对已识别的对向边跳过不兼容预约重复计数。
- [x] **Step 4: 运行 GREEN**
```bash
mvn -f javaTest/pom.xml -Dtest=RouteQualityEvaluatorTest,RouteCandidatePlannerTest test
```
预期所有路线单测通过,并保留原有确定性、110%边界和候选上限行为。
- [x] **Step 5: 提交**
```bash
git add javaTest/src/main/java/com/ft546/wcs/demo/traffic/TrafficRouteSnapshot.java javaTest/src/main/java/com/ft546/wcs/demo/traffic/RouteQualityEvaluator.java javaTest/src/test/java/com/ft546/wcs/demo/traffic/RouteQualityEvaluatorTest.java
git commit -m "fix(javaTest): validate route quality inputs"
```
### Task 2: 补齐真实调度边界集成测试
**Files:**
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java`
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskQueueTest.java`
**Interfaces:**
- 不新增生产 API;测试通过现有 `HistoricalSimulationInput`、`SimulationConfig` 和 `HistoricalDispatchSimulator.simulate(...)` 验证业务闭环。
- [x] **Step 1: 写未来到达与优先级测试**
构造两个站点路线和两条任务:低优先级任务在 `t=0` 到达,高优先级任务在仿真时间 `t=5000` 到达。断言 `t<5000` 的事件中不存在高优先级任务 `ASSIGN`,任务到达后它按优先级先获得 `ASSIGN`;另保留队列 aging 单测证明长期低优先级任务不会饥饿。
- [x] **Step 2: 写无路失效关闭测试**
构造已知但被 `GridMap.block(target)` 永久阻断的服务目标,运行模拟并断言该任务为 `FAILED`、reason=`NO_ROUTE`、无 `ASSIGN`/`COMPLETE`,且结果数量仍保持闭环。对未知站点输入继续由 normalizer 形成 `HistoricalDispatchFailure`,断言同样进入明确失败结果而不是等待。
- [x] **Step 3: 写 PLC 重试边界测试**
使用现有 `DeterministicFaultPlan` 注入一次 `SEND_FAILURE`,断言任务保持未移动并在后续 tick 产生 `PLC_RETRY`;使用重试上限夹具验证超过上限时 reason 非空且不伪造 `COMPLETED`。
- [x] **Step 4: 运行专项 GREEN**
```bash
mvn -f javaTest/pom.xml -Dtest=HistoricalDispatchSimulatorTest,SimulationTaskQueueTest,HistoricalDispatchFaultMatrixTest test
```
预期新旧测试全部通过;若生产代码行为与测试暴露的状态不一致,先添加最小生产修复,再重新运行同一命令。
- [x] **Step 5: 提交**
```bash
git add javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationTaskQueueTest.java
git commit -m "test(javaTest): prove history dispatch boundary states"
```
### Task 3: 资源和重规划集成门禁
**Files:**
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/CorridorReservationManagerTest.java`
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/HistoricalDispatchSimulatorTest.java`
- Modify: `javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation/SimulationProgressWatchdogTest.java`
**Interfaces:**
- 保持 `CorridorReservationManager.replaceRoute(...)` 原子接口和 `TrafficHoldTracker` 第三次触发协议不变。
- [x] **Step 1: 锁定旧预约回滚**
在替换失败测试中同时断言旧路线每条边仍由原任务持有、其他同向持有者仍存在、没有新路线残留;在成功测试中断言不再使用的旧边释放且共享边保留。
- [x] **Step 2: 锁定 HOLD 集成行为**
扩展模拟测试断言第三次相同交通 HOLD 产生一次 `REROUTE_TRIGGER`,失败替换产生 `REROUTE_REJECTED` 且原路线继续执行;成功替换后在下一次 MOVE 前不重复产生普通重规划。
- [x] **Step 3: 锁定死锁 watchdog**
增加连续无进展达到阈值才判死锁、未来到达任务不判死锁、车辆 MOVE 后计数清零的测试;确认 `SimulationInvariantSummary.deadlocks` 与异常路径均可追溯。
- [x] **Step 4: 运行专项 GREEN**
```bash
mvn -f javaTest/pom.xml -Dtest=CorridorReservationManagerTest,HistoricalDispatchSimulatorTest,SimulationProgressWatchdogTest,TrafficHoldTrackerTest test
```
- [x] **Step 5: 提交**
```bash
git add javaTest/src/test/java/com/ft546/wcs/shadow/history/simulation
git commit -m "test(javaTest): lock reroute and resource safety gates"
```
### Task 4: 报告、API、浏览器和真实负载验收
**Files:**
- Modify only if an acceptance check fails: `javaTest/src/main/java/com/ft546/wcs/shadow/history/visualizer/*`, `javaTest/src/main/resources/visualizer/*`, `javaTest/scripts/visualizer_browser_qa.py`
- Generated and removed after audit: `javaTest/outputs/acceptance-final`, `javaTest/outputs/browser-qa-final`
**Interfaces:**
- HTTP `GET /api/health` remains `UP/mapLoaded/simulationBusy`.
- Simulation output remains `summary.json`, `route-decisions.json`, `task-results.csv`, `tick-events.csv`, `invariant-results.json`, `manifest.sha256`.
- [x] **Step 1: Run clean full suite**
```bash
mvn -f javaTest/pom.xml clean test
```
Record the actual Surefire count; never reuse an earlier count.
- [x] **Step 2: Run one fresh 240-task replay**
```bash
mvn -f javaTest/pom.xml compile exec:java "-Dexec.mainClass=com.ft546.wcs.shadow.history.simulation.HistoricalDispatchSimulationApplication" "-Dexec.args=outputs/acceptance-final 100"
```
Parse the generated JSON with a structured parser and assert task totals, per-vehicle totals, route candidate bounds, safety invariants, archive count, WMS idempotence and nonblank failure/HOLD/retry reasons.
- [x] **Step 3: Run browser black-box QA**
```bash
python "C:/Users/13623/.agents/skills/webapp-testing/scripts/with_server.py" --server 'mvn compile exec:java "-Dexec.mainClass=com.ft546.wcs.shadow.history.visualizer.HistoricalDispatchVisualizerApplication" "-Dexec.args=18086"' --port 18086 --timeout 120 -- python scripts/visualizer_browser_qa.py http://127.0.0.1:18086 outputs/browser-qa-final
```
Check desktop and mobile map rendering, route layer visibility, full-map viewport, route evidence and console error count.
- [x] **Step 4: Verify health and repository state**
```powershell
Invoke-RestMethod http://127.0.0.1:18086/api/health
git status --short
git diff --check
```
Only pre-existing user `docs/*.html` may remain untracked.
- [x] **Step 5: Commit only implementation/test changes**
Use a focused commit for any production fix and a separate commit for tests. Do not stage generated reports or user documents.
## Completion Audit
Before claiming completion, map every original requirement to fresh evidence: `create_date` admission, priority/aging, vehicle selection, route stages, node/edge/opposite arbitration, HOLD/reroute, PLC retry, MOVE/release, archive/WMS idempotence, fault matrix, no-route closure, report/API/UI evidence, 240-task totals, route quality comparison, timing as operational-only evidence, and offline boundary.