45 KiB
FT546 Tidy Workflow and Historical Batch Replay 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: Add persisted automatic/manual tidy execution with exclusive manual mode, then prove inbound, outbound, relocation, and tidy correctness by replaying site history through simulated PDA/WCS interfaces.
Architecture: Keep TidyPlanner pure in fortucky-algorithm and add WMS-specific persistence/orchestration under ruoyi-admin/com/ruoyi/algorithm/wms/tidy. SQL Server is authoritative for mode, queues, workflows, callback events, and locks; all legacy and algorithm allocation routes pass through one admission service. WCS exposes a read-only vehicle snapshot, while a run-scoped simulator and PowerShell harness drive the development-database replay and reconciliation.
Tech Stack: Java 17, Spring Boot, Spring transactions/scheduling, MyBatis, SQL Server, JUnit 5, Mockito, AssertJ, Vue 2 + Element UI, Node.js built-in HTTP server, PowerShell 7/System.Data.SqlClient.
Global Constraints
- Work in
D:/workSpace/PROJECT_SPACE/FT546/FT546MWS/FT546MWSfor WMS andD:/workSpace/PROJECT_SPACE/FT546/FT546-WCSfor WCS; both are dirty repositories, so never revert or stage unrelated changes. - Preserve the
fortucky-algorithmmodule boundary and the configured WMS primaryDataSource/PlatformTransactionManager. - Keep the normal deployment default
FORTUCKY_ALGORITHM_MODE=SHADOW; only the confirmed development database may use the run-scoped replay override. - Automatic tidy runs only in
NORMAL, never alongside inbound/outbound/outbound-relocation work, and has a global maximum of one active workflow. - Manual mode follows
NORMAL -> ENTERING_TIDY -> TIDY_ACTIVE -> EXITING_TIDY -> NORMAL; business documents remain accepted but execution allocation is blocked outsideNORMAL. - Manual capacity is
online + healthy + (idle or already assigned to manual tidy)minus active manual workflows; safety predicates and resource locks override capacity filling. - Every move job with
in_or_out=28must resolve to exactly one origin:AUTO_TIDY,MANUAL_TIDY, orOUTBOUND_RELOCATION. - Do not delete or mutate imported finish tables. Before live replay, create and verify a new restorable backup after migrations; restore it after evidence generation.
- Implement every production change test-first and commit only exact task paths.
File Structure
WMS algorithm and persistence
- Modify
fortucky-algorithm/src/main/resources/db/sqlserver/install.sql: idempotent outbound/tidy schema, queue handoff, resource locking, and sequence synchronization procedures. - Modify
fortucky-algorithm/src/main/resources/db/sqlserver/diagnostics.sql: mode/workflow/queue/origin/lock integrity diagnostics. - Modify
fortucky-algorithm/src/main/resources/db/sqlserver/uninstall.sql: reverse only new algorithm objects in dependency order. - Modify
fortucky-algorithm/src/test/java/com/ruoyi/algorithm/repository/SqlServerMigrationScriptTest.java: migration contract tests. - Modify
fortucky-algorithm/src/main/java/com/ruoyi/algorithm/integration/AlgorithmProperties.java: tidy scan/reconcile/lease and WCS snapshot URL configuration. - Modify
fortucky-algorithm/src/main/java/com/ruoyi/algorithm/integration/SchedulingFacade.java: exposeplanTidywithout adding WMS persistence to the algorithm module.
WMS tidy runtime
- Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyEffectiveState.java: persisted mode enum. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyOrigin.java: job/workflow origin enum. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ExecutionWorkType.java: gate input enum. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyModeSnapshot.java: immutable status DTO. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowState.java: mapper projection for workflow/step state. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/VehicleSnapshot.java: per-vehicle WCS contract. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyVehicleCapacity.java: capacity calculation. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyModeService.java: switch transitions and startup reconciliation. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ExecutionAdmissionService.java: shared business/tidy admission gate. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ExecutionBlockedByTidyModeException.java: stable blocked-allocation exception. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowStarter.java: scheduler-to-coordinator boundary. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/WcsTaskState.java: restart-reconciliation WCS task state. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowTransaction.java: transactional claim, job creation, callback, recovery, and release. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowCoordinator.java: automatic singleton and manual capacity filling. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyScheduler.java: 10-minute automatic scan and short mode reconciliation. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/WcsVehicleSnapshotClient.java: production WCS snapshot adapter. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ReplayExecutionGuard.java: validates a run-scoped ACTIVE process againstDB_NAME()before writes. - Modify
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsAlgorithmMapper.javaandruoyi-admin/src/main/resources/mapper/algorithm/WmsAlgorithmMapper.xml: all tidy SQL operations and origin queries. - Modify
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsInboundAllocationService.javaandWmsOutboundAllocationService.java: shared gate before algorithm and legacy paths. - Modify
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/OutboundWorkflowTransaction.java: origin linkage and shared resource admission. - Modify
ruoyi-admin/src/main/java/com/ruoyi/api/service/impl/ToWmsServiceImpl.java: route idempotent job-finish callbacks to outbound then tidy coordinators.
WCS capacity endpoint
- Create
FT546-WCS/ruoyi-admin/src/main/java/com/ruoyi/api/domain/wcs2wms/SrgvVehicleSnapshot.java: read-only transport DTO. - Modify
FT546-WCS/ruoyi-admin/src/main/java/com/ruoyi/api/controller/Wcs2WmsController.java:POST /wcs2Wms/api/tidyVehicleSnapshot. - Modify
FT546-WCS/ruoyi-admin/src/main/java/com/ruoyi/api/service/IApiService.javaandimpl/ApiServiceImpl.java: derive online/healthy/idle state fromdevice_srgv.
Operator control
- Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/controller/TidyControlController.java: authenticated status and switch API. - Create
ruoyi-admin/src/main/java/com/ruoyi/algorithm/controller/TidyModeRequest.java: switch request DTO. - Create
ruoyi-ui/src/api/algorithm/tidy.js: status/switch calls. - Create
ruoyi-ui/src/views/algorithm/tidy/index.vue: compact operational status and switch page. - Create
sql/algorithm_tidy_menu.sql: idempotent dynamic menu and permissions.
Replay and evidence
- Create
tools/history-replay/simulators/ft546-wcs-simulator.mjs: three-vehicle WCS snapshot/task simulator with controllable failures. - Create
tools/history-replay/sql/select-batch-fixtures.sql: deterministic eligible history and mapping decisions. - Create
tools/history-replay/sql/reconcile-tidy-batch.sql: per-run inventory, cargo-space, workflow, origin, and lock evidence. - Create
tools/history-replay/Invoke-Ft546TidyBatchReplay.ps1: backup, migration, fixture execution, HTTP simulation, reconciliation, reports, and restore. - Modify
tools/history-replay/README.md: exact preflight/run/resume commands and artifact contract.
Task 1: Add Idempotent SQL Server Tidy Schema
Files:
- Modify:
fortucky-algorithm/src/test/java/com/ruoyi/algorithm/repository/SqlServerMigrationScriptTest.java - Modify:
fortucky-algorithm/src/main/resources/db/sqlserver/install.sql - Modify:
fortucky-algorithm/src/main/resources/db/sqlserver/diagnostics.sql - Modify:
fortucky-algorithm/src/main/resources/db/sqlserver/uninstall.sql
Interfaces:
-
Produces:
alg.tidy_mode,alg.tidy_lane_queue,alg.tidy_workflow,alg.tidy_step,alg.tidy_space_lock,alg.tidy_callback_event. -
Produces:
alg.usp_claim_tidy_lane,alg.usp_release_tidy_lane,alg.usp_sync_replay_sequences. -
Preserves: existing
alg.dirty_lane_queueas the rebuild queue and hands rebuilt lanes toalg.tidy_lane_queueonly after successful rebuild. -
Step 1: Extend migration contract tests and verify red
Add assertions that require these exact fragments:
assertThat(install).contains("CREATE TABLE alg.tidy_mode");
assertThat(install).contains("CREATE TABLE alg.tidy_lane_queue");
assertThat(install).contains("CREATE TABLE alg.tidy_workflow");
assertThat(install).contains("CREATE TABLE alg.tidy_step");
assertThat(install).contains("CREATE TABLE alg.tidy_space_lock");
assertThat(install).contains("CREATE TABLE alg.tidy_callback_event");
assertThat(install).contains("CREATE PROCEDURE alg.usp_claim_tidy_lane");
assertThat(install).contains("sp_getapplock");
assertThat(install).contains("OUTBOUND_RELOCATION");
assertThat(diagnostics).contains("PAUSED_RECOVERY");
assertThat(uninstall).contains("DROP TABLE alg.tidy_mode");
Run:
mvn -pl fortucky-algorithm -Dtest=SqlServerMigrationScriptTest test
Expected: FAIL because tidy objects do not exist.
- Step 2: Add tables, keys, constraints, and queue handoff
Use these persisted values:
effective_state varchar(24) CHECK (effective_state IN
('NORMAL','ENTERING_TIDY','TIDY_ACTIVE','EXITING_TIDY'))
origin varchar(24) CHECK (origin IN ('AUTO_TIDY','MANUAL_TIDY'))
workflow_status varchar(24) CHECK (workflow_status IN
('CLAIMED','WAITING_DISPATCH','DISPATCHED','RUNNING','PAUSED_RECOVERY','COMPLETED','CANCELLED_RECONCILED'))
resource_type varchar(8) CHECK (resource_type IN ('SPACE','LANE','FLOOR'))
Create filtered unique indexes for active resources, WCS task IDs, callback event keys, and singleton active automatic workflow. Add origin='OUTBOUND_RELOCATION' to alg.outbound_workflow. At the successful end of alg.usp_refresh_dirty_lanes, MERGE each row from #dirty into alg.tidy_lane_queue, incrementing dirty_version; retain existing catch/requeue behavior.
- Step 3: Add claim/release and replay-sequence procedures
alg.usp_claim_tidy_lane must claim one PENDING row using UPDLOCK, READPAST, ROWLOCK, ordered by last_dirty_at, warehouse_id, lane_code, and set a lease token/expiry. alg.usp_release_tidy_lane must clear only the claimed version; if a newer version exists, return it to PENDING.
alg.usp_sync_replay_sequences must run under sp_getapplock, compare active and finish tables, and advance bas_job_id/bas_task_no without decreasing them. It must include CK202607210002 as a regression fixture in the SQL test.
- Step 4: Verify migration scripts
Run:
mvn -pl fortucky-algorithm -Dtest=SqlServerMigrationScriptTest test
Expected: PASS with all install/diagnostics/uninstall assertions green.
- Step 5: Commit only migration files
git add fortucky-algorithm/src/main/resources/db/sqlserver/install.sql \
fortucky-algorithm/src/main/resources/db/sqlserver/diagnostics.sql \
fortucky-algorithm/src/main/resources/db/sqlserver/uninstall.sql \
fortucky-algorithm/src/test/java/com/ruoyi/algorithm/repository/SqlServerMigrationScriptTest.java
git commit -m "feat: add persisted tidy workflow schema"
Task 2: Implement Persisted Mode and Shared Admission
Files:
- Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyEffectiveState.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ExecutionWorkType.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyModeSnapshot.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyModeService.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ExecutionAdmissionService.java - Create:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyModeServiceTest.java - Create:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/ExecutionAdmissionServiceTest.java - Modify:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsAlgorithmMapper.java - Modify:
ruoyi-admin/src/main/resources/mapper/algorithm/WmsAlgorithmMapper.xml
Interfaces:
-
Produces:
TidyModeSnapshot status(String warehouseId). -
Produces:
TidyModeSnapshot requestManualMode(String warehouseId, boolean enabled, String actor). -
Produces:
TidyModeSnapshot reconcile(String warehouseId). -
Produces:
void assertAllowed(String warehouseId, ExecutionWorkType workType). -
Consumes mapper operations:
selectTidyModeForUpdate,setTidyModeRequest,countActiveBusinessExecution,countActiveManualTidy. -
Step 1: Write failing state-machine and admission tests
Cover the exact table:
assertThat(service.requestManualMode("01", true, "tester").effectiveState())
.isEqualTo(TidyEffectiveState.ENTERING_TIDY);
when(mapper.countActiveBusinessExecution("01")).thenReturn(0);
assertThat(service.reconcile("01").effectiveState())
.isEqualTo(TidyEffectiveState.TIDY_ACTIVE);
assertThatThrownBy(() -> gate.assertAllowed("01", ExecutionWorkType.INBOUND))
.isInstanceOf(ExecutionBlockedByTidyModeException.class);
gate.assertAllowed("01", ExecutionWorkType.MANUAL_TIDY);
Also test idempotent repeated enable/disable, EXITING_TIDY drain, optimistic-version failure, and acceptance of DOCUMENT_RECEIPT in every state.
Run:
mvn -pl ruoyi-admin -Dtest='TidyModeServiceTest,ExecutionAdmissionServiceTest' test
Expected: FAIL because types/services/mappers are missing.
- Step 2: Add the domain types and service logic
Use this gate contract:
public enum ExecutionWorkType {
DOCUMENT_RECEIPT, INBOUND, OUTBOUND, OUTBOUND_RELOCATION, AUTO_TIDY, MANUAL_TIDY;
public boolean allowedIn(TidyEffectiveState state) {
if (this == DOCUMENT_RECEIPT) return true;
if (state == TidyEffectiveState.NORMAL) return this != MANUAL_TIDY;
return state == TidyEffectiveState.TIDY_ACTIVE && this == MANUAL_TIDY;
}
}
public final class ExecutionAdmissionService {
private final TidyModeService modeService;
public ExecutionAdmissionService(TidyModeService modeService) {
this.modeService = modeService;
}
public void assertAllowed(String warehouseId, ExecutionWorkType workType) {
TidyEffectiveState state = modeService.status(warehouseId).effectiveState();
if (!workType.allowedIn(state)) {
throw new ExecutionBlockedByTidyModeException(state.name());
}
}
}
NORMAL allows business execution and auto tidy; ENTERING_TIDY and EXITING_TIDY allow only document receipt and drain callbacks; TIDY_ACTIVE allows document receipt, manual tidy, and callbacks. State changes and counts must be read inside the WMS transaction manager.
- Step 3: Implement mapper state locking and status projection
selectTidyModeForUpdate uses WITH (UPDLOCK,HOLDLOCK). The status projection includes requested switch, effective state, drain count, active tidy count, status reason, version, updater, and timestamp.
- Step 4: Run focused tests
mvn -pl ruoyi-admin -Dtest='TidyModeServiceTest,ExecutionAdmissionServiceTest,WmsAlgorithmMapperRegistrationTest' test
Expected: PASS.
- Step 5: Commit exact mode files
git add ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyEffectiveState.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ExecutionWorkType.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyModeSnapshot.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyModeService.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ExecutionAdmissionService.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ExecutionBlockedByTidyModeException.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsAlgorithmMapper.java \
ruoyi-admin/src/main/resources/mapper/algorithm/WmsAlgorithmMapper.xml \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyModeServiceTest.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/ExecutionAdmissionServiceTest.java
git commit -m "feat: persist tidy mode admission state"
Task 3: Gate Every Inbound and Outbound Allocation Route
Files:
- Modify:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsInboundAllocationService.java - Modify:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsOutboundAllocationService.java - Modify:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/WmsInboundAllocationServiceTest.java - Modify:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/WmsOutboundAllocationServiceTest.java - Modify:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/AlgorithmShadowConfigurationTest.java
Interfaces:
-
Consumes:
ExecutionAdmissionService.assertAllowed(warehouseId, INBOUND|OUTBOUND). -
Guarantees: the gate runs before both
SchedulingFacadeplanning and legacy stored-procedure fallback. -
Step 1: Add failing router tests
For allocate, reallocate, allocateProject, and allocateExactStock, make the gate throw and verify neither algorithm nor legacy mapper is invoked:
doThrow(new ExecutionBlockedByTidyModeException("TIDY_ACTIVE"))
.when(admission).assertAllowed("01", ExecutionWorkType.OUTBOUND);
assertThatThrownBy(() -> service.allocateProject(stockout, detail))
.isInstanceOf(ExecutionBlockedByTidyModeException.class);
verifyNoInteractions(facade, stockoutMapper, workflowCoordinator);
Run:
mvn -pl ruoyi-admin -Dtest='WmsInboundAllocationServiceTest,WmsOutboundAllocationServiceTest' test
Expected: FAIL because constructors and gate calls are absent.
- Step 2: Inject and call the shared gate
Call the gate once at the top of each shared router after resolving warehouse ID and before any reservation release, planner call, or legacy procedure. Do not add controller-only checks. ToWmsServiceImpl.reMaterial remains covered because it routes through OutStockoutServiceImpl.autoAllot -> WmsOutboundAllocationService.allocateProject.
- Step 3: Verify callback paths remain admitted
Add tests proving jobFinish, completeInbound, outbound confirmation, and existing in-flight advancement do not call the creation gate. They are drain/recovery operations and must remain executable in non-normal states.
- Step 4: Run WMS allocation regression
mvn -pl ruoyi-admin -Dtest='WmsInboundAllocationServiceTest,InboundAllocationTransactionTest,WmsOutboundAllocationServiceTest,OutboundWorkflowTransactionTest,PersistentOutboundWorkflowCoordinatorTest,AlgorithmShadowConfigurationTest' test
Expected: PASS.
- Step 5: Commit allocation gate changes
git add ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsInboundAllocationService.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsOutboundAllocationService.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/WmsInboundAllocationServiceTest.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/WmsOutboundAllocationServiceTest.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/AlgorithmShadowConfigurationTest.java
git commit -m "feat: gate allocation during manual tidy"
Task 4: Add Persistent Tidy-Lane Scheduling
Files:
- Modify:
fortucky-algorithm/src/main/java/com/ruoyi/algorithm/integration/AlgorithmProperties.java - Modify:
fortucky-algorithm/src/main/java/com/ruoyi/algorithm/integration/SchedulingFacade.java - Modify:
fortucky-algorithm/src/test/java/com/ruoyi/algorithm/integration/AlgorithmConfigurationTest.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyLaneClaim.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowStarter.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ReplayExecutionGuard.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyScheduler.java - Create:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidySchedulerTest.java - Create:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/ReplayExecutionGuardTest.java - Modify:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsAlgorithmMapper.java - Modify:
ruoyi-admin/src/main/resources/mapper/algorithm/WmsAlgorithmMapper.xml - Modify:
ruoyi-admin/src/main/resources/application.yml
Interfaces:
-
Produces:
TidyPlan SchedulingFacade.planTidy(String warehouseId, Instant now). -
Produces:
Optional<TidyLaneClaim> claimTidyLane(String warehouseId, String owner, Instant expiresAt). -
Produces:
UUID TidyWorkflowStarter.startAutomatic(TidyLaneClaim claim, TidyCandidate candidate)as the scheduler boundary; Task 5 makes the coordinator implement it. -
Step 1: Add failing scheduler tests
Test these cases explicitly: not NORMAL; active inbound; active outbound relocation; one active tidy; no queue claim; stale candidate; successful single start; lease failure requeues.
when(mode.status("01")).thenReturn(normal);
when(mapper.countActiveBusinessExecution("01")).thenReturn(1);
scheduler.scanAutomatic();
verifyNoInteractions(coordinator);
Run:
mvn -pl fortucky-algorithm -Dtest=AlgorithmConfigurationTest test
mvn -pl ruoyi-admin -Dtest=TidySchedulerTest test
Expected: FAIL because facade/scheduler APIs are absent.
- Step 2: Expose pure tidy planning and properties
Add properties with these defaults:
fortucky:
algorithm:
tidy-auto-scan-ms: 600000
tidy-reconcile-ms: 5000
tidy-claim-lease-seconds: 60
tidy-wcs-snapshot-url: ${FORTUCKY_TIDY_WCS_SNAPSHOT_URL:http://localhost:8081/wcs2Wms/api/tidyVehicleSnapshot}
replay-run-id: ${FT546_REPLAY_RUN_ID:}
replay-database: ${FT546_REPLAY_DATABASE:}
SchedulingFacade.planTidy may run in SHADOW for diagnostics, but workflow creation still requires the run-scoped write gate and ExecutionWorkType.AUTO_TIDY.
ReplayExecutionGuard runs at application startup. When replay-run-id is nonblank, it requires routing mode ACTIVE, database writes enabled, and mapper selectDatabaseName() exactly equal to replay-database; otherwise startup fails before schedulers or HTTP writers run.
- Step 3: Implement scheduler and versioned queue mapper
Use @Scheduled(fixedDelayString = "${fortucky.algorithm.tidy-auto-scan-ms:600000}"). Lock/claim the oldest queue row, invoke the planner, select only a candidate touching the claimed lane, and release/requeue using the claim token and dirty version.
- Step 4: Run planner and scheduler suites
mvn -pl fortucky-algorithm -Dtest='TidyPlannerTest,WarehouseApplicationServiceTest,AlgorithmConfigurationTest' test
mvn -pl ruoyi-admin -Dtest='TidySchedulerTest,ReplayExecutionGuardTest,WmsAlgorithmMapperRegistrationTest' test
Expected: PASS.
- Step 5: Commit scheduling changes
git add fortucky-algorithm/src/main/java/com/ruoyi/algorithm/integration/AlgorithmProperties.java \
fortucky-algorithm/src/main/java/com/ruoyi/algorithm/integration/SchedulingFacade.java \
fortucky-algorithm/src/test/java/com/ruoyi/algorithm/integration/AlgorithmConfigurationTest.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyLaneClaim.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowStarter.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/ReplayExecutionGuard.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyScheduler.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidySchedulerTest.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/ReplayExecutionGuardTest.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsAlgorithmMapper.java \
ruoyi-admin/src/main/resources/mapper/algorithm/WmsAlgorithmMapper.xml \
ruoyi-admin/src/main/resources/application.yml
git commit -m "feat: schedule automatic tidy from dirty lanes"
Task 5: Execute Tidy Through the Existing Move-Job Chain
Superseded on 2026-07-23: WCS task-state lookup and the UNKNOWN-task replay case are replaced by WMS-native evidence recovery. See
docs/superpowers/specs/2026-07-23-wms-native-tidy-recovery-design.mdanddocs/superpowers/plans/2026-07-23-wms-native-tidy-recovery.md. Vehicle snapshot behavior is not superseded.
Files:
- Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyOrigin.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowState.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/WcsTaskState.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowTransaction.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowCoordinator.java - Create:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowTransactionTest.java - Create:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowCoordinatorTest.java - Modify:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsAlgorithmMapper.java - Modify:
ruoyi-admin/src/main/resources/mapper/algorithm/WmsAlgorithmMapper.xml - Modify:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/OutboundWorkflowTransaction.java - Modify:
ruoyi-admin/src/main/java/com/ruoyi/api/service/impl/ToWmsServiceImpl.java
Interfaces:
-
Produces:
UUID start(TidyOrigin origin, String warehouseId, TidyCandidate candidate). -
Produces:
boolean onJobFinished(String jobId, String callbackStage). -
Produces:
TidyWorkflowState reconcile(UUID workflowId, WcsTaskState taskState). -
Implements:
UUID TidyWorkflowStarter.startAutomatic(TidyLaneClaim claim, TidyCandidate candidate). -
Guarantees: one
TidyMovebecomes one orderedin_or_out=28job; only the next dependent step is active. -
Step 1: Add failing workflow transaction tests
Cover: current pallet/space revalidation; transaction-scoped sp_getapplock; disjoint SPACE/LANE/FLOOR resources; ordered multi-move candidate; one job per move; duplicate callback event; out-of-order rejection; terminal release; PAUSED_RECOVERY retained locks.
Define tidy workflow origin narrowly:
public enum TidyOrigin {
AUTO_TIDY, MANUAL_TIDY
}
Outbound workflows persist the separate constant OUTBOUND_RELOCATION; job-origin queries union the two owning workflow types and never pass that value into TidyWorkflowTransaction.start.
UUID workflow = transaction.start(TidyOrigin.MANUAL_TIDY, "01", candidate);
verify(mapper).insertTidyMoveJob(argThat(step -> step.inOrOut() == 28));
assertThat(transaction.onJobFinished("TIDY-1", "FINISHED")).isTrue();
assertThat(transaction.onJobFinished("TIDY-1", "FINISHED")).isFalse();
verify(mapper, times(1)).completeTidyStep(anyString());
Run:
mvn -pl ruoyi-admin -Dtest='TidyWorkflowTransactionTest,TidyWorkflowCoordinatorTest' test
Expected: FAIL because workflow types/mapper methods are missing.
- Step 2: Implement transactional workflow creation
Inside one @Transactional method:
admission.assertAllowed(warehouseId,
origin == TidyOrigin.AUTO_TIDY ? ExecutionWorkType.AUTO_TIDY : ExecutionWorkType.MANUAL_TIDY);
mapper.acquireAlgorithmResourceAppLock(warehouseId, resourceKeys);
mapper.revalidateTidyCandidate(candidate);
mapper.insertTidyWorkflow(...);
mapper.insertTidySteps(...);
mapper.lockTidyResources(...);
mapper.insertTidyMoveJob(firstStep);
Each subsequent callback inserts alg.tidy_callback_event first. A duplicate unique-key event returns the current state without applying inventory/job transitions twice.
- Step 3: Link outbound relocation origin and callback routing
Persist OUTBOUND_RELOCATION on outbound workflows. Extend job query DTOs by workflow join. In ToWmsServiceImpl.jobFinish, try the existing outbound coordinator first, then the tidy coordinator only when outbound returns noMatch; callbacks for unrelated jobs retain existing behavior.
- Step 4: Run outbound and tidy workflow regression
mvn -pl ruoyi-admin -Dtest='OutboundWorkflowTransactionTest,PersistentOutboundWorkflowCoordinatorTest,WmsAlgorithmMapperWorkflowSqlTest,TidyWorkflowTransactionTest,TidyWorkflowCoordinatorTest' test
Expected: PASS, including N MOVE_OUT + OUTBOUND + N RESTORE assertions and tidy callback idempotency.
- Step 5: Commit workflow files
git add ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyOrigin.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowState.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/WcsTaskState.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowTransaction.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowCoordinator.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowTransactionTest.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowCoordinatorTest.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/WmsAlgorithmMapper.java \
ruoyi-admin/src/main/resources/mapper/algorithm/WmsAlgorithmMapper.xml \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/OutboundWorkflowTransaction.java \
ruoyi-admin/src/main/java/com/ruoyi/api/service/impl/ToWmsServiceImpl.java
git commit -m "feat: execute persisted tidy move workflows"
Task 6: Add WCS Vehicle Snapshot and Manual Capacity Filling
Files:
- Create:
D:/workSpace/PROJECT_SPACE/FT546/FT546-WCS/ruoyi-admin/src/main/java/com/ruoyi/api/domain/wcs2wms/SrgvVehicleSnapshot.java - Modify:
D:/workSpace/PROJECT_SPACE/FT546/FT546-WCS/ruoyi-admin/src/main/java/com/ruoyi/api/controller/Wcs2WmsController.java - Modify:
D:/workSpace/PROJECT_SPACE/FT546/FT546-WCS/ruoyi-admin/src/main/java/com/ruoyi/api/service/IApiService.java - Modify:
D:/workSpace/PROJECT_SPACE/FT546/FT546-WCS/ruoyi-admin/src/main/java/com/ruoyi/api/service/impl/ApiServiceImpl.java - Create:
D:/workSpace/PROJECT_SPACE/FT546/FT546-WCS/ruoyi-admin/src/test/java/com/ruoyi/api/service/ApiServiceVehicleSnapshotTest.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/VehicleSnapshot.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyVehicleCapacity.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/WcsVehicleSnapshotClient.java - Create:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyVehicleCapacityTest.java - Create:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyModeRecoveryTest.java - Modify:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyModeService.java - Modify:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowCoordinator.java - Modify:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyScheduler.java
Interfaces:
-
WCS produces:
List<SrgvVehicleSnapshot> tidyVehicleSnapshot(). -
WMS consumes:
List<VehicleSnapshot> fetch(). -
Produces: nested
TidyVehicleCapacity.CapacityResultandCapacityResult calculate(List<VehicleSnapshot> vehicles, int activeManualWorkflows, Set<String> assignedManualVehicleIds), wherenewSlots=max(0,effectiveCapacity-activeManualWorkflows). -
Step 1: Write capacity and mode-recovery tests
Use exactly these semantics:
VehicleSnapshot healthyIdle = new VehicleSnapshot("1", true, true, true, null);
VehicleSnapshot healthyTidy = new VehicleSnapshot("2", true, true, false, "MANUAL_TIDY");
VehicleSnapshot busyInbound = new VehicleSnapshot("3", true, true, false, "INBOUND");
CapacityResult result = capacity.calculate(
List.of(healthyIdle, healthyTidy, busyInbound), 1, Set.of("2"));
assertThat(result.effectiveCapacity()).isEqualTo(2);
assertThat(result.newSlots()).isEqualTo(1);
Test ENTERING_TIDY drain to active, continuous replacement, capacity reduction without cancelling running work, switch-off cancellation of undispatched work, restart at all three non-normal checkpoints, and unknown WCS task -> PAUSED_RECOVERY. With three effective vehicles but only two mutually safe candidates, assert two workflows plus status reason NO_SAFE_CANDIDATE; the switch must remain enabled.
- Step 2: Add the WCS read-only endpoint
Derive fields from device_srgv:
boolean online = "1".equals(device.getAgvStatus());
boolean healthy = online && value(device.getAlarm()) <= 1 && value(device.getErrMsg()) == 0;
boolean idle = healthy && value(device.getTaskNo()) == 0
&& value(device.getLocked()) == 0 && value(device.getChargeFlag()) == 0;
Return stable vehicle ID and current task number/type. Add ApiServiceVehicleSnapshotTest for offline, alarmed, charging, locked, busy, and idle vehicles. Do not write WCS device or queue state from this endpoint.
- Step 3: Add the WMS client and capacity reconciliation
Use configurable ${fortucky.algorithm.tidy-wcs-snapshot-url:http://localhost:8081/wcs2Wms/api/tidyVehicleSnapshot}. During TIDY_ACTIVE, fill newSlots with mutually disjoint candidates. During EXITING_TIDY, cancel only CLAIMED/WAITING_DISPATCH rows without a WCS task and drain dispatched/running rows.
- Step 4: Verify WCS and WMS modules
Run:
git -C D:/workSpace/PROJECT_SPACE/FT546/FT546-WCS diff --check
mvn -f D:/workSpace/PROJECT_SPACE/FT546/FT546-WCS/pom.xml -pl ruoyi-admin -am -Dtest=ApiServiceVehicleSnapshotTest test
mvn -pl ruoyi-admin -Dtest='TidyVehicleCapacityTest,TidyModeRecoveryTest,TidyWorkflowCoordinatorTest' test
Expected: both Maven commands PASS.
- Step 5: Commit exact WCS and WMS capacity files separately
git -C D:/workSpace/PROJECT_SPACE/FT546/FT546-WCS add \
ruoyi-admin/src/main/java/com/ruoyi/api/domain/wcs2wms/SrgvVehicleSnapshot.java \
ruoyi-admin/src/main/java/com/ruoyi/api/controller/Wcs2WmsController.java \
ruoyi-admin/src/main/java/com/ruoyi/api/service/IApiService.java \
ruoyi-admin/src/main/java/com/ruoyi/api/service/impl/ApiServiceImpl.java \
ruoyi-admin/src/test/java/com/ruoyi/api/service/ApiServiceVehicleSnapshotTest.java
git -C D:/workSpace/PROJECT_SPACE/FT546/FT546-WCS commit -m "feat: expose tidy vehicle capacity"
git add ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/VehicleSnapshot.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyVehicleCapacity.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/WcsVehicleSnapshotClient.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyModeService.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowCoordinator.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/wms/tidy/TidyScheduler.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyVehicleCapacityTest.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyModeRecoveryTest.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/wms/tidy/TidyWorkflowCoordinatorTest.java
git commit -m "feat: fill manual tidy vehicle capacity"
Task 7: Add Operator Switch and Status Page
Files:
- Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/controller/TidyModeRequest.java - Create:
ruoyi-admin/src/main/java/com/ruoyi/algorithm/controller/TidyControlController.java - Create:
ruoyi-admin/src/test/java/com/ruoyi/algorithm/controller/TidyControlControllerTest.java - Create:
ruoyi-ui/src/api/algorithm/tidy.js - Create:
ruoyi-ui/src/views/algorithm/tidy/index.vue - Create:
sql/algorithm_tidy_menu.sql
Interfaces:
-
GET /algorithm/tidy/status?warehouseId=01with permissionalgorithm:tidy:query. -
PUT /algorithm/tidy/modebody{ "warehouseId": "01", "enabled": true }with permissionalgorithm:tidy:edit. -
Step 1: Write failing controller tests
mockMvc.perform(get("/algorithm/tidy/status").param("warehouseId", "01"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.effectiveState").value("NORMAL"));
mockMvc.perform(put("/algorithm/tidy/mode")
.contentType(APPLICATION_JSON)
.content("{\"warehouseId\":\"01\",\"enabled\":true}"))
.andExpect(status().isOk());
verify(modeService).requestManualMode(eq("01"), eq(true), anyString());
Run:
mvn -pl ruoyi-admin -Dtest=TidyControlControllerTest test
Expected: FAIL because controller is absent.
- Step 2: Implement secured API and idempotent menu SQL
Controller methods return AjaxResult.success(snapshot) and use @PreAuthorize("@ss.hasPermi('algorithm:tidy:query')") / algorithm:tidy:edit. The menu script uses IF NOT EXISTS by permission string and component algorithm/tidy/index.
- Step 3: Implement compact operational page
Use <el-switch> with confirmation and rollback on error. Show effective state, requested switch, drain count, active tidy, healthy/available vehicles, candidate count, and last reason. Poll every 5 seconds only while document.visibilityState === 'visible'; clear timer/listener in beforeDestroy.
- Step 4: Verify backend and frontend build
mvn -pl ruoyi-admin -Dtest=TidyControlControllerTest test
npm --prefix ruoyi-ui run build:prod
Expected: controller PASS and Vue production build exits 0.
- Step 5: Browser-check the page
Start WMS and UI, then use Playwright at desktop 1440x900 and mobile 390x844. Verify switch confirmation, failed-switch rollback, polling, no overlapping text, and status updates through ENTERING_TIDY/TIDY_ACTIVE/EXITING_TIDY.
- Step 6: Commit UI/control files
git add ruoyi-admin/src/main/java/com/ruoyi/algorithm/controller/TidyModeRequest.java \
ruoyi-admin/src/main/java/com/ruoyi/algorithm/controller/TidyControlController.java \
ruoyi-admin/src/test/java/com/ruoyi/algorithm/controller/TidyControlControllerTest.java \
ruoyi-ui/src/api/algorithm/tidy.js ruoyi-ui/src/views/algorithm/tidy/index.vue \
sql/algorithm_tidy_menu.sql
git commit -m "feat: add manual tidy control page"
Task 8: Build Deterministic PDA/WCS Batch Replay Harness
Files:
- Create:
tools/history-replay/simulators/ft546-wcs-simulator.mjs - Create:
tools/history-replay/sql/select-batch-fixtures.sql - Create:
tools/history-replay/sql/reconcile-tidy-batch.sql - Create:
tools/history-replay/Invoke-Ft546TidyBatchReplay.ps1 - Create:
tools/history-replay/tests/Invoke-Ft546TidyBatchReplay.Tests.ps1 - Modify:
tools/history-replay/README.md
Interfaces:
-
Simulator:
POST /wcs2Wms/api/tidyVehicleSnapshot,/receiveInMydoJob,/receiveOutMydoJob,/sim/vehicles,/sim/complete,/sim/unknown-task. -
Runner:
-PreflightOnly,-ConfirmReplay,-KeepFailedState,-WmsBaseUrl,-SimulatorPort. -
Outputs:
inbound-reconciliation.csv,outbound-reconciliation.csv,tidy-reconciliation.csv,events.json,report.md. -
Step 1: Write failing Pester/static harness tests
Require source hashes/counts, closed warehouse mapping, orphan exclusion, deterministic ordering, 100/300 inbound boundary, 4x25 outbound strata, at least 50 planner-selected cases, callback duplication/out-of-order cases, backup verification, run-scoped override removal, and final restore proof.
Run:
Invoke-Pester .\tools\history-replay\tests\Invoke-Ft546TidyBatchReplay.Tests.ps1 -Output Detailed
Expected: FAIL because runner/simulator/queries do not exist.
- Step 2: Implement deterministic fixture SQL
Eligibility must be expressed in SQL and returned with mapping_decision:
CASE
WHEN NULLIF(LTRIM(RTRIM(source_warehouse)), '') IS NULL THEN 'MAP_BLANK_TO_01'
WHEN source_warehouse = '07' THEN 'MAP_07_TO_01'
WHEN source_warehouse = '01' THEN 'KEEP_01'
ELSE 'UNSUPPORTED_SOURCE_WAREHOUSE'
END
Order by completion time, document ID, detail ID. Exclude CKD202605140015-1. Never update finish rows.
- Step 3: Implement WCS simulator and event journal
Use Node built-in http; default to three online healthy idle vehicles. Every received task and callback gets an immutable sequence number and timestamp. /sim/unknown-task makes the next WMS recovery lookup return unknown without deleting the journal.
- Step 4: Implement guarded replay orchestration
Reuse the existing System.Data.SqlClient helpers and exact six source-count checks. Flow: preflight -> install migration -> COPY_ONLY, CHECKSUM backup -> RESTORE VERIFYONLY -> sequence sync -> create run ID -> start simulator -> start an isolated WMS process -> inbound HTTP loop -> outbound just-in-time strata loop -> automatic tidy cases -> manual three-vehicle/capacity/restart cases -> reconcile -> write artifacts -> stop writers -> restore backup -> verify baseline.
The isolated WMS process receives these process-local values and uses a non-conflicting HTTP port:
$env:FORTUCKY_ALGORITHM_MODE = 'ACTIVE'
$env:FORTUCKY_ALGORITHM_DATABASE_WRITES = 'true'
$env:FT546_REPLAY_RUN_ID = $runId
$env:FT546_REPLAY_DATABASE = 'FT546-wms'
$env:FORTUCKY_TIDY_WCS_SNAPSHOT_URL = "http://127.0.0.1:$SimulatorPort/wcs2Wms/api/tidyVehicleSnapshot"
Before starting Java, the runner proves the resolved JDBC database is exactly FT546-wms, no unrelated active work exists, and every generated business identifier carries $runId. A finally block stops only the process IDs it started and removes these environment values; the normal deployment configuration remains SHADOW.
Every HTTP call records request, response code/body, and related DB snapshot. A mismatch marks the run failed but does not remove its row. -KeepFailedState skips restore only when explicitly supplied for debugging and prints the verified backup path prominently.
- Step 5: Run harness tests and preflight
Invoke-Pester .\tools\history-replay\tests\Invoke-Ft546TidyBatchReplay.Tests.ps1 -Output Detailed
pwsh -File .\tools\history-replay\Invoke-Ft546TidyBatchReplay.ps1 -PreflightOnly
Expected: Pester PASS; preflight prints target FT546-wms, source counts/hashes, topology count, active-work count, migration status, and no mutations.
- Step 6: Commit replay tooling
git add tools/history-replay/simulators/ft546-wcs-simulator.mjs \
tools/history-replay/sql/select-batch-fixtures.sql \
tools/history-replay/sql/reconcile-tidy-batch.sql \
tools/history-replay/Invoke-Ft546TidyBatchReplay.ps1 \
tools/history-replay/tests/Invoke-Ft546TidyBatchReplay.Tests.ps1 \
tools/history-replay/README.md
git commit -m "test: add historical tidy batch replay harness"
Task 9: Run Full Regression and Development-Database Replay
Files:
- Generate only:
outputs/ft546-tidy-batch-replay-<run-id>/* - Update if defects are found: only the owning task files and their tests.
Interfaces:
-
Consumes all preceding tasks.
-
Produces the final pass/fail evidence and restores the imported-history baseline.
-
Step 1: Run all automated Java and frontend checks
mvn -pl fortucky-algorithm,ruoyi-admin -am test
mvn test
mvn package -DskipTests
npm --prefix ruoyi-ui run build:prod
mvn -f D:/workSpace/PROJECT_SPACE/FT546/FT546-WCS/pom.xml -pl ruoyi-admin -am test
Expected: all commands exit 0; record exact test totals and package SHA-256 values in report.md.
- Step 2: Run SQL diagnostics before destructive replay
Execute install.sql and diagnostics.sql against the confirmed development FT546-wms. Stop on any active job/workflow, orphan lock, invalid topology, wrong database identity, unsupported source count, or failed backup verification.
- Step 3: Execute the full replay
pwsh -File .\tools\history-replay\Invoke-Ft546TidyBatchReplay.ps1 -ConfirmReplay
Expected acceptance:
Inbound attempted >= 100, mismatches = 0
Outbound successful = 100 (0 blockers=25, 1=25, 2=25, 3+=25)
Planner-selected outbound >= 50
Automatic tidy max concurrency = 1
Manual tidy capacity: 3 -> refill -> 2 -> no unsafe overfill
Duplicate callback side effects = 0
Restart checkpoints = 4/4 passed
Unexpected PAUSED_RECOVERY = 0
Restore verification = PASS
- Step 4: Investigate failures test-first and rerun from restored baseline
For each failing reconciliation row, first add the smallest reproducing unit/integration test to the owning task, observe red, implement the fix, run focused green, then rerun the full automated suite and replay. Never patch database evidence manually.
- Step 5: Verify final artifacts and clean runtime processes
Confirm all five artifact files exist and contain the run ID, source mapping, per-row evidence, failures (including zero-count sections), backup path, restore counts, and database fingerprint. Stop WMS, simulator, and temporary Redis processes started by the run; do not stop unrelated user processes.
- Step 6: Commit only defect fixes and final documentation
git status --short
git diff --check
Do not commit outputs/ unless the repository's existing policy tracks test evidence. Report WMS and WCS commit IDs, test totals, replay run ID, artifact path, and restored database counts.