docs: complete shadow demo implementation plan
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# WCS P0-B1 Offline SHADOW Demo Implementation Plan
|
# 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.
|
> **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 (`- [x]`) 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.
|
**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.
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
- Produces: `ResourceKey.node(String)`, `edge(String,String)`, `conflict(String)`
|
- Produces: `ResourceKey.node(String)`, `edge(String,String)`, `conflict(String)`
|
||||||
- Produces: `ResourceLedger.evaluate(String, Collection<ResourceKey>): ProtectionResult`
|
- Produces: `ResourceLedger.evaluate(String, Collection<ResourceKey>): ProtectionResult`
|
||||||
|
|
||||||
- [ ] **Step 1: Write failing map and ledger tests**
|
- [x] **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.
|
Cover checksum mismatch, unconfirmed zone, canonical undirected edge key, zone non-exclusivity, same-node conflict, opposite-edge conflict, capacity, and non-conflicting parallel candidates.
|
||||||
|
|
||||||
@@ -47,23 +47,23 @@ assertTrue(ledger.evaluate("V1", Arrays.asList(ResourceKey.node("N1"))).isGrante
|
|||||||
assertFalse(ledger.evaluate("V2", 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**
|
- [x] **Step 2: Run the focused test and verify RED**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=MapAndResourceLedgerTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=MapAndResourceLedgerTest test`
|
||||||
|
|
||||||
Expected: compilation failure because the SHADOW types do not exist.
|
Expected: compilation failure because the SHADOW types do not exist.
|
||||||
|
|
||||||
- [ ] **Step 3: Implement immutable map compilation and ledger evaluation**
|
- [x] **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.
|
`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**
|
- [x] **Step 4: Run focused and existing tests**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=MapAndResourceLedgerTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=MapAndResourceLedgerTest test`
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml test`
|
Run: `mvn -f javaTest/pom.xml test`
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
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 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
|
||||||
@@ -85,15 +85,15 @@ git commit -m "feat: model shadow traffic resources"
|
|||||||
- Produces: `TrafficSegment.transition(SegmentEvent): TrafficSegment`
|
- Produces: `TrafficSegment.transition(SegmentEvent): TrafficSegment`
|
||||||
- Produces: `SnapshotFreshnessPolicy.validate(previous,current,decisionTime): SnapshotHealth`
|
- Produces: `SnapshotFreshnessPolicy.validate(previous,current,decisionTime): SnapshotHealth`
|
||||||
|
|
||||||
- [ ] **Step 1: Write failing state and snapshot tests**
|
- [x] **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.
|
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**
|
- [x] **Step 2: Run focused test and verify RED**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=SegmentAndSnapshotTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=SegmentAndSnapshotTest test`
|
||||||
|
|
||||||
- [ ] **Step 3: Implement state transitions and snapshot validation**
|
- [x] **Step 3: Implement state transitions and snapshot validation**
|
||||||
|
|
||||||
Only allow:
|
Only allow:
|
||||||
|
|
||||||
@@ -105,13 +105,13 @@ COMMITTED/EXECUTING -> FAULT_LOCKED
|
|||||||
|
|
||||||
All snapshot lists and maps are defensive unmodifiable copies.
|
All snapshot lists and maps are defensive unmodifiable copies.
|
||||||
|
|
||||||
- [ ] **Step 4: Run focused and full tests**
|
- [x] **Step 4: Run focused and full tests**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=SegmentAndSnapshotTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=SegmentAndSnapshotTest test`
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml test`
|
Run: `mvn -f javaTest/pom.xml test`
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
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 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
|
||||||
@@ -132,7 +132,7 @@ git commit -m "feat: validate shadow segment snapshots"
|
|||||||
- Produces: `WaitForGraph.wouldCreateCycle(waiter,holders): boolean`
|
- Produces: `WaitForGraph.wouldCreateCycle(waiter,holders): boolean`
|
||||||
- Produces: `RollingDispatchPolicy.decide(List<ShadowCandidate>, ResourceLedger, EffectiveTrafficMap): List<ShadowDecision>`
|
- Produces: `RollingDispatchPolicy.decide(List<ShadowCandidate>, ResourceLedger, EffectiveTrafficMap): List<ShadowDecision>`
|
||||||
|
|
||||||
- [ ] **Step 1: Write failing deterministic decision tests**
|
- [x] **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.
|
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.
|
||||||
|
|
||||||
@@ -143,21 +143,21 @@ assertEquals(DecisionType.HOLD, cycleDecision.getType());
|
|||||||
assertEquals("WAIT_CYCLE", cycleDecision.getReasonCode());
|
assertEquals("WAIT_CYCLE", cycleDecision.getReasonCode());
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Run focused test and verify RED**
|
- [x] **Step 2: Run focused test and verify RED**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=RollingDispatchPolicyTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=RollingDispatchPolicyTest test`
|
||||||
|
|
||||||
- [ ] **Step 3: Implement deterministic rolling policy**
|
- [x] **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.
|
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**
|
- [x] **Step 4: Run focused and full tests**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=RollingDispatchPolicyTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=RollingDispatchPolicyTest test`
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml test`
|
Run: `mvn -f javaTest/pom.xml test`
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add javaTest/src/main/java/com/ft546/wcs/shadow/decision javaTest/src/test/java/com/ft546/wcs/shadow/RollingDispatchPolicyTest.java
|
git add javaTest/src/main/java/com/ft546/wcs/shadow/decision javaTest/src/test/java/com/ft546/wcs/shadow/RollingDispatchPolicyTest.java
|
||||||
@@ -175,25 +175,25 @@ git commit -m "feat: decide shadow traffic safely"
|
|||||||
**Interfaces:**
|
**Interfaces:**
|
||||||
- Produces: `FeedbackReconciler.reconcile(TrafficSegment, ExecutionFeedback): FeedbackResult`
|
- Produces: `FeedbackReconciler.reconcile(TrafficSegment, ExecutionFeedback): FeedbackResult`
|
||||||
|
|
||||||
- [ ] **Step 1: Write failing feedback tests**
|
- [x] **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.
|
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**
|
- [x] **Step 2: Run focused test and verify RED**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=FeedbackReconcilerTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=FeedbackReconcilerTest test`
|
||||||
|
|
||||||
- [ ] **Step 3: Implement matching and release rules**
|
- [x] **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.
|
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**
|
- [x] **Step 4: Run focused and full tests**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=FeedbackReconcilerTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=FeedbackReconcilerTest test`
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml test`
|
Run: `mvn -f javaTest/pom.xml test`
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add javaTest/src/main/java/com/ft546/wcs/shadow/feedback javaTest/src/test/java/com/ft546/wcs/shadow/FeedbackReconcilerTest.java
|
git add javaTest/src/main/java/com/ft546/wcs/shadow/feedback javaTest/src/test/java/com/ft546/wcs/shadow/FeedbackReconcilerTest.java
|
||||||
@@ -218,25 +218,25 @@ git commit -m "feat: reconcile feedback fail closed"
|
|||||||
- Produces: `DecisionReplayService.read(InputStream): DecisionEvent`
|
- Produces: `DecisionReplayService.read(InputStream): DecisionEvent`
|
||||||
- Produces: `DecisionReplayService.replay(DecisionEvent): List<ShadowDecision>`
|
- Produces: `DecisionReplayService.replay(DecisionEvent): List<ShadowDecision>`
|
||||||
|
|
||||||
- [ ] **Step 1: Write failing guard and replay tests**
|
- [x] **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.
|
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**
|
- [x] **Step 2: Run focused tests and verify RED**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=ShadowCoordinatorReplayTest,DemoScenarioTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=ShadowCoordinatorReplayTest,DemoScenarioTest test`
|
||||||
|
|
||||||
- [ ] **Step 3: Implement coordinator, guard, event hash, and replay**
|
- [x] **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.
|
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**
|
- [x] **Step 4: Run focused tests and executable demo**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=ShadowCoordinatorReplayTest,DemoScenarioTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=ShadowCoordinatorReplayTest,DemoScenarioTest test`
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml exec:java`
|
Run: `mvn -f javaTest/pom.xml exec:java`
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
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 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
|
||||||
@@ -253,19 +253,19 @@ git commit -m "feat: replay guarded shadow decisions"
|
|||||||
- Consumes: `RollingDispatchPolicy`, `ResourceLedger`, `FeedbackReconciler`
|
- Consumes: `RollingDispatchPolicy`, `ResourceLedger`, `FeedbackReconciler`
|
||||||
- Produces: repeatable invariant regression output including seed, map version, and input summary.
|
- Produces: repeatable invariant regression output including seed, map version, and input summary.
|
||||||
|
|
||||||
- [ ] **Step 1: Write fixed-seed invariant tests**
|
- [x] **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.
|
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**
|
- [x] **Step 2: Run property test**
|
||||||
|
|
||||||
Run: `mvn -f javaTest/pom.xml -Dtest=ShadowInvariantPropertyTest test`
|
Run: `mvn -f javaTest/pom.xml -Dtest=ShadowInvariantPropertyTest test`
|
||||||
|
|
||||||
- [ ] **Step 3: Update README**
|
- [x] **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.
|
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**
|
- [x] **Step 4: Run final verification**
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
|
|
||||||
@@ -276,10 +276,11 @@ 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-*`.
|
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**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add javaTest/src/test/java/com/ft546/wcs/shadow/ShadowInvariantPropertyTest.java javaTest/README.md
|
git add javaTest/src/test/java/com/ft546/wcs/shadow/ShadowInvariantPropertyTest.java javaTest/README.md
|
||||||
git commit -m "test: verify shadow traffic invariants"
|
git commit -m "test: verify shadow traffic invariants"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user