# FT546 shadow phase and evidence repair The user approved repairing the five findings in the 2026-09-08 field assessment. Execute in the existing `optimize/wcs` worktree. Subagents inspect/review only; the main agent implements and verifies. ## Constraints and design - Preserve Java 8, Maven 3.6.0, offline dependencies, the formal Admin/PLC/WMS runtime, existing evidence and SQL permissions. No live migration, deletion, threshold increase or process operation. - Read queue `issued` and `execution_status` from the existing source views. Only explicit pending `0/1` rows may produce new predictions; executing, completed, unknown and already-arrived phases produce observation evidence. Preserve an existing vehicle binding with a shadow-only assignment adapter. Do not relax busy-vehicle checks. - Reconstruct legacy PLC endpoints using the actual sending rules, including lift endpoint rewriting and stale path/phase rejection. Observation rows are separate from algorithm differences. - Store new input JSON losslessly as a versioned gzip envelope; share the first stored input within a save batch through a bounded cycle reference. Preserve original logical hashes. Keep old raw JSON readable. All input rows/references remain in existing tables, in the existing transaction. A loopback input export endpoint returns original JSON with its verified hash, so readers do not need to understand physical storage. - Configure explicitly approved safe wait/yield site IDs; validate topology membership and safe-exit constraints. Empty configuration remains protected and produces an explicit diagnostic. Never infer physical safety from ordinary passability. - Publish an embedded repair build ID and a computed digest of nonsecret effective runtime settings independently of operator-supplied artifact/config hashes. Record the required IDEA field correction in the upgrade notes; do not rewrite historical runs. ## Execution checklist - [x] Baseline `mvn -o -pl ruoyi-wcs-shadow -am test` passes; keep the baseline log outside the worktree. - [x] Add failing lifecycle and legacy projection tests, including already-issued, completed-at-destination, pending bound vehicle and lift `tsj` cases. Add fields to `ShadowQueueFact`/`SqlServerShadowFactReader`, a shadow eligibility classifier/assignment adapter, and observation support in evidence collection/comparison. Preserve old fixture hashes when new fields are absent; absent lifecycle is observation-only for dispatch. - [x] Add failing storage round-trip, tamper, inflation-limit, reference, rollback and old-format tests. Implement `ShadowInputPayloadCodec`, repository input resolution and a bounded loopback input endpoint. Budget physical inserted payload while enforcing logical input bounds. - [x] Add configured-safe-point and invalid-point tests. Wire the settings into `ShadowDispatchSnapshotAssembler` and expose blocked-resource/safe-point diagnostics without enabling unconfigured avoidance. - [x] Add independent runtime build/config identity tests and wire identity into the status/heartbeat. Document source-only deployment fields and physical input export format. - [x] Run focused tests after each change, then the full reactor and historical/new captured-input replay. Validate real field inputs remain immutable and incomplete old lifecycle cannot authorize dispatch. - [x] Run independent read-only review of phase safety and evidence compatibility. Resolve findings, update the runbook and confirm no formal runtime source changes. - Delivery after this plan snapshot: commit/push the scoped shadow repair under the existing authorization for `optimize/wcs`; record the exact revision in the handoff. Do not deploy remotely. Implementation decisions: `BaseSRgvThread` passes the live vehicle site to the sender, so bound phase predictions now start there directly. Cross-floor and two-stage handoffs remain observation-only pending state-machine evidence. Reviewer suggestion to reject all lift-entry paths was not adopted: the formal sender explicitly rewrites the endpoint after path construction. Final review identified IPv4-mapped loopback compatibility; a failing regression reproduced it and numeric `InetAddress.isLoopbackAddress` parsing fixes it without DNS or forwarded-header trust. Private field replay: 25 rows / 17 unique raw inputs preserve their exact JSON and input hashes. New gzip root payloads total 604,048 nvarchar bytes versus 3,294,254 raw bytes (18.34%). This is input payload only, not total SQL allocation. The earlier 300-row archive is no longer at its attachment path; current verification uses the available 2026-09-08 audit exports plus explicit pending lifecycle fixtures.