Files
FT546-WCS/docs/superpowers/plans/2026-07-30-wcs-p0-b1-shadow-demo.md

13 KiB

WCS P0-B1 Offline SHADOW Demo 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: Extend javaTest with a deterministic, fail-closed, in-memory P0-B1 SHADOW traffic-control kernel without changing the existing LEGACY demo or production modules.

Architecture: New code lives under com.ft546.wcs.shadow and reads immutable snapshots to produce GRANT/HOLD/YIELD decisions and replayable events. The SHADOW application layer receives read-only resource state and write-forbidden ports, while state-machine and feedback tests exercise simulated HARD/UNKNOWN_HARD contracts independently of authoritative LEGACY state.

Tech Stack: Java 8, Maven, JUnit Jupiter 5.10.2, Jackson Databind 2.17.2, Surefire 3.2.5.

Global Constraints

  • Keep Java source and target compatibility at Java 8.
  • Keep all existing LEGACY behavior and tests passing.
  • Do not modify any ruoyi-* production code.
  • Do not connect SQL Server, PLC, WMS, Spring, or network services.
  • SHADOW must not write PLC commands, LEGACY business state, or authoritative reservations.
  • Traffic zones are coordination/version boundaries, not implicit capacity-one resources.
  • HARD and UNKNOWN_HARD are released only by matching feedback, never by ETA expiry.
  • Unknown cargo, lift signals, restart, disconnect, and feedback mismatch fail closed.
  • The result is offline SHADOW simulation evidence, not field SHADOW, HIL, ACTIVE, or production evidence.

Task 1: Versioned Map and Resource Ledger

Files:

  • Modify: javaTest/pom.xml
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/map/EffectiveTrafficMap.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/map/TrafficMapCompiler.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/resource/ResourceKey.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/resource/ResourceLedger.java
  • Test: javaTest/src/test/java/com/ft546/wcs/shadow/MapAndResourceLedgerTest.java

Interfaces:

  • Produces: TrafficMapCompiler.compile(MapDefinition): EffectiveTrafficMap

  • Produces: ResourceKey.node(String), edge(String,String), conflict(String)

  • Produces: ResourceLedger.evaluate(String, Collection<ResourceKey>): ProtectionResult

  • Step 1: Write failing map and ledger tests

Cover checksum mismatch, unconfirmed zone, canonical undirected edge key, zone non-exclusivity, same-node conflict, opposite-edge conflict, capacity, and non-conflicting parallel candidates.

assertEquals("EDGE:A:B", ResourceKey.edge("B", "A").value());
assertTrue(ledger.evaluate("V1", Arrays.asList(ResourceKey.node("N1"))).isGranted());
assertFalse(ledger.evaluate("V2", Arrays.asList(ResourceKey.node("N1"))).isGranted());
  • Step 2: Run the focused test and verify RED

Run: mvn -f javaTest/pom.xml -Dtest=MapAndResourceLedgerTest test

Expected: compilation failure because the SHADOW types do not exist.

  • Step 3: Implement immutable map compilation and ledger evaluation

EffectiveTrafficMap exposes immutable nodes, edges, capacities, safe wait/yield sites, mapCode, versionId, and checksum. ResourceLedger copies authoritative protection input and mutates only its private simulation state.

  • Step 4: Run focused and existing tests

Run: mvn -f javaTest/pom.xml -Dtest=MapAndResourceLedgerTest test

Run: mvn -f javaTest/pom.xml test

  • Step 5: Commit
git add javaTest/pom.xml javaTest/src/main/java/com/ft546/wcs/shadow/map javaTest/src/main/java/com/ft546/wcs/shadow/resource javaTest/src/test/java/com/ft546/wcs/shadow/MapAndResourceLedgerTest.java
git commit -m "feat: model shadow traffic resources"

Task 2: Segment State and Immutable Snapshot

Files:

  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/segment/ReservationState.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/segment/SegmentState.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/segment/TrafficSegment.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/TrafficVehicleSnapshot.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/TrafficSnapshot.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/snapshot/SnapshotFreshnessPolicy.java
  • Test: javaTest/src/test/java/com/ft546/wcs/shadow/SegmentAndSnapshotTest.java

Interfaces:

  • Produces: TrafficSegment.transition(SegmentEvent): TrafficSegment

  • Produces: SnapshotFreshnessPolicy.validate(previous,current,decisionTime): SnapshotHealth

  • Step 1: Write failing state and snapshot tests

Assert PREPARED cannot jump to EXECUTING, COMMIT uncertainty creates UNKNOWN_HARD, snapshot collections are frozen, stale snapshots are rejected, sequence rollback is rejected, and boot ID change quarantines the vehicle.

  • Step 2: Run focused test and verify RED

Run: mvn -f javaTest/pom.xml -Dtest=SegmentAndSnapshotTest test

  • Step 3: Implement state transitions and snapshot validation

Only allow:

SOFT_PLANNED -> PREPARING -> PREPARED -> COMMITTING -> COMMITTED -> EXECUTING -> COMPLETED
COMMITTING -> COMMIT_UNCERTAIN
COMMITTED/EXECUTING -> FAULT_LOCKED

All snapshot lists and maps are defensive unmodifiable copies.

  • Step 4: Run focused and full tests

Run: mvn -f javaTest/pom.xml -Dtest=SegmentAndSnapshotTest test

Run: mvn -f javaTest/pom.xml test

  • Step 5: Commit
git add javaTest/src/main/java/com/ft546/wcs/shadow/segment javaTest/src/main/java/com/ft546/wcs/shadow/snapshot javaTest/src/test/java/com/ft546/wcs/shadow/SegmentAndSnapshotTest.java
git commit -m "feat: validate shadow segment snapshots"

Task 3: Wait Graph and Rolling Decisions

Files:

  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/decision/DecisionType.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/decision/ShadowCandidate.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/decision/ShadowDecision.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/decision/WaitForGraph.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/decision/RollingDispatchPolicy.java
  • Test: javaTest/src/test/java/com/ft546/wcs/shadow/RollingDispatchPolicyTest.java

Interfaces:

  • Produces: WaitForGraph.wouldCreateCycle(waiter,holders): boolean

  • Produces: RollingDispatchPolicy.decide(List<ShadowCandidate>, ResourceLedger, EffectiveTrafficMap): List<ShadowDecision>

  • Step 1: Write failing deterministic decision tests

Cover stable priority/aging/task/vehicle ordering, same-node and opposite-edge HOLD, non-conflicting parallel GRANT, committed segment non-revocation, cycle rejection, safe YIELD, and no-safe-yield HOLD.

assertEquals(Arrays.asList("V1", "V2"), decisions.stream()
    .map(ShadowDecision::getVehicleId).collect(Collectors.toList()));
assertEquals(DecisionType.HOLD, cycleDecision.getType());
assertEquals("WAIT_CYCLE", cycleDecision.getReasonCode());
  • Step 2: Run focused test and verify RED

Run: mvn -f javaTest/pom.xml -Dtest=RollingDispatchPolicyTest test

  • Step 3: Implement deterministic rolling policy

Sort by committed continuation, emergency, business priority descending, wait age descending, clearance cost ascending, task ID, and vehicle ID. Every non-GRANT decision includes reason code, conflicting resources, and blocking vehicles.

  • Step 4: Run focused and full tests

Run: mvn -f javaTest/pom.xml -Dtest=RollingDispatchPolicyTest test

Run: mvn -f javaTest/pom.xml test

  • Step 5: Commit
git add javaTest/src/main/java/com/ft546/wcs/shadow/decision javaTest/src/test/java/com/ft546/wcs/shadow/RollingDispatchPolicyTest.java
git commit -m "feat: decide shadow traffic safely"

Task 4: Feedback Reconciliation and Fail-Closed Recovery

Files:

  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/feedback/ExecutionFeedback.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/feedback/FeedbackResult.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/feedback/FeedbackReconciler.java
  • Test: javaTest/src/test/java/com/ft546/wcs/shadow/FeedbackReconcilerTest.java

Interfaces:

  • Produces: FeedbackReconciler.reconcile(TrafficSegment, ExecutionFeedback): FeedbackResult

  • Step 1: Write failing feedback tests

Cover A-to-B release, destination retention, duplicate snapshot idempotency, ETA expiry retention, version mismatch, skip, rollback, disconnect, ACK loss, and PLC restart.

  • Step 2: Run focused test and verify RED

Run: mvn -f javaTest/pom.xml -Dtest=FeedbackReconcilerTest test

  • Step 3: Implement matching and release rules

Only matching boot ID, epoch, plan version, segment sequence, increasing snapshot sequence, and legal path suffix can release resources. Every mismatch returns quarantined UNKNOWN_HARD with zero released resources.

  • Step 4: Run focused and full tests

Run: mvn -f javaTest/pom.xml -Dtest=FeedbackReconcilerTest test

Run: mvn -f javaTest/pom.xml test

  • Step 5: Commit
git add javaTest/src/main/java/com/ft546/wcs/shadow/feedback javaTest/src/test/java/com/ft546/wcs/shadow/FeedbackReconcilerTest.java
git commit -m "feat: reconcile feedback fail closed"

Task 5: SHADOW Guard, Events, JSON Replay, and Demo

Files:

  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowWriteForbiddenException.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowWritePort.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/application/ShadowTrafficCoordinator.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionEvent.java
  • Create: javaTest/src/main/java/com/ft546/wcs/shadow/replay/DecisionReplayService.java
  • Create: javaTest/src/test/resources/shadow/golden/basic-conflict.json
  • Create: javaTest/src/test/java/com/ft546/wcs/shadow/ShadowCoordinatorReplayTest.java
  • Modify: javaTest/src/main/java/com/ft546/wcs/demo/DemoApplication.java
  • Modify: javaTest/src/test/java/com/ft546/wcs/demo/DemoScenarioTest.java

Interfaces:

  • Produces: ShadowTrafficCoordinator.run(TrafficSnapshot,List<ShadowCandidate>): DecisionEvent

  • Produces: DecisionReplayService.read(InputStream): DecisionEvent

  • Produces: DecisionReplayService.replay(DecisionEvent): List<ShadowDecision>

  • Step 1: Write failing guard and replay tests

Assert PLC/business/reservation writes all throw, coordinator leaves LEGACY state unchanged, JSON replay reproduces type/reason/resources, and Demo output contains an explicit offline SHADOW summary.

  • Step 2: Run focused tests and verify RED

Run: mvn -f javaTest/pom.xml -Dtest=ShadowCoordinatorReplayTest,DemoScenarioTest test

  • Step 3: Implement coordinator, guard, event hash, and replay

Use Jackson only at the replay boundary. Hash canonical event input with SHA-256. The coordinator records intended decisions but never invokes a mutable external port.

  • Step 4: Run focused tests and executable demo

Run: mvn -f javaTest/pom.xml -Dtest=ShadowCoordinatorReplayTest,DemoScenarioTest test

Run: mvn -f javaTest/pom.xml exec:java

  • Step 5: Commit
git add javaTest/pom.xml javaTest/src/main/java/com/ft546/wcs/shadow/application javaTest/src/main/java/com/ft546/wcs/shadow/replay javaTest/src/test/resources/shadow javaTest/src/main/java/com/ft546/wcs/demo/DemoApplication.java javaTest/src/test
git commit -m "feat: replay guarded shadow decisions"

Task 6: Fixed-Seed Invariants and Documentation

Files:

  • Create: javaTest/src/test/java/com/ft546/wcs/shadow/ShadowInvariantPropertyTest.java
  • Modify: javaTest/README.md

Interfaces:

  • Consumes: RollingDispatchPolicy, ResourceLedger, FeedbackReconciler

  • Produces: repeatable invariant regression output including seed, map version, and input summary.

  • Step 1: Write fixed-seed invariant tests

For seeds 546001 through 546010, generate bounded 2-to-8 vehicle candidate sets and assert capacity never exceeds limits, committed wait graph remains acyclic, the same input gives the same decisions, and fault/unknown feedback never frees resources.

  • Step 2: Run property test

Run: mvn -f javaTest/pom.xml -Dtest=ShadowInvariantPropertyTest test

  • Step 3: Update README

Document package boundaries, mvn clean test, mvn exec:java, covered P0-B1 scenarios, and the explicit exclusions for SQL, PLC, HIL, real SHADOW, ACTIVE, and production.

  • Step 4: Run final verification

Run:

mvn -f javaTest/pom.xml clean test
mvn -f javaTest/pom.xml exec:java

Inspect Surefire XML and require tests > 0, failures = 0, errors = 0, and skipped = 0. Run git diff --check and confirm no changed path under ruoyi-*.

  • Step 5: Commit
git add javaTest/src/test/java/com/ft546/wcs/shadow/ShadowInvariantPropertyTest.java javaTest/README.md
git commit -m "test: verify shadow traffic invariants"