# KBX FE Interaction Closure Hardening v56

## 1. Executive judgement

v55 closed major recovery-workbench gaps, but the remaining risk was no longer template count. It was interaction closure: keyboard focus disappearing after DOM replacement, overlays returning users to nowhere, HTTP 200 being treated as all-success for bulk work, browser-persisted WMS retry commands crossing operator sessions, and runtime feedback metadata reporting an old app version.

The v56 rule is simple: a user action is not complete until the UI preserves context, reports the authoritative outcome, and leaves the operator at a deterministic next action.

## 2. Changes

### Overlay focus lifecycle
- KbxDialog 1.1.0 and KbxDrawer 1.1.0 capture the invoking element on open and restore it after the overlay has actually hidden.
- Restoration is fail-safe: disconnected or disabled targets are ignored.
- KbxDialog supports `restoreFocus=false` for components that own a richer focus contract.
- KbxLookupDialog uses that opt-out because KbxLookup intentionally advances to the next form field after a successful selection; generic restore must not override that behavior.

### T08 Excel Import focus continuity
- KbxExcelImport 1.3.0 gives all six stages a programmatic focus landing.
- When server status replaces one stage DOM with another, focus moves to the new stage heading instead of falling back to `body`.
- Error-row first/next focus remains independent from stage focus.
- The static HTML/JavaScript reference mirrors the same behavior and avoids stealing focus during repeated progress rerenders.

### T06 authoritative bulk receipt
- The real Claim endpoint already returns `ClaimedCount` and `SkippedCount`, but FE typed it as `unknown` and discarded the result.
- v56 consumes the real response and renders a persistent inline receipt: requested / claimed / skipped.
- Partial processing offers `내 업무 보기` and `최신 상태 조회`; a generic success toast is not considered sufficient.
- Demo API now matches the production response shape.

### WMS shared-PDA retry isolation
- v1 stored unacknowledged scan commands in one unscoped localStorage key.
- This is unsafe on shared PDAs because a later operator/session could inherit an old retry queue.
- v56 uses a hashed tenant/user UI scope for authenticated persistent storage; anonymous/default contexts are session-only.
- The old unscoped v1 queue is explicitly retired and never replayed.
- Parsed browser data is shape-validated and queue length is bounded before replay.
- Idempotency key reuse and sequential replay remain unchanged.

### Runtime provenance correction
- `App.vue` still reported `v51-fe-presentation-workbench` while the source had advanced through v55.
- v56 corrects runtime `app-version` to `v56-fe-interaction-closure-hardening` so suggestions, telemetry, and operational reproduction do not record a stale build identity.

### Static FE truth hardening
- Static T07 previously simulated reconciliation by directly setting `actual = expected` and `difference = 0` in client memory.
- That contradicted the real v55 Reconcile policy.
- v56 changes the static reference to register a reprocessing request while explicitly preserving OMS/WMS source truth.

### E2E readiness repair
- The OMS Import Playwright scenario referenced an XLSX fixture that did not exist in the repository.
- v56 uses an in-memory browser file for the Demo API flow, removing an untracked binary prerequisite.
- Demo Import now provides a complete required-field mapping so the Golden Flow can actually proceed to validation.
- Keyboard regression now explicitly asserts F2 Lookup -> Esc -> invoking customer-code field focus restoration.

## 3. QA criticism

The previous project direction had several mature contracts but some tests were ceremonial: a Golden Flow could exist in source while depending on a missing binary fixture or a Demo API response shape different from the real endpoint. That creates false confidence. A QA gate must prove that the test can execute, not merely that a spec file exists.

Similarly, overlay accessibility cannot stop at `Esc closes`. In an ERP screen, closing a lookup or detail surface without deterministic focus restoration breaks the operator's keyboard production line. Focus is part of transactional UX, not cosmetic accessibility.

WMS local persistence must be treated as operational data. Idempotency protects the server from duplication, but it does not make an unscoped browser queue safe across operators. Storage isolation and idempotency solve different failure modes.

## 4. What was deliberately not added

- No new low-code/runtime metadata engine.
- No new backend command merely to support the UI changes.
- No optimistic domain-state mutation.
- No broad redesign of Home after v54 stabilization.
- No claim that Playwright/Vite/Vitest passed in this container.

## 5. Verification

Full `node scripts/validate-kbx.mjs`: PASS.

Current governance snapshot:
- 161 design tokens
- 20 screens
- 86 components
- 34 core APIs
- 309 TS/Vue script units
- T01~T09 recipe verification 9/9
- Design Debt 116 <= 131
- Design-Code Parity PASS
- Release Governance major PASS

See `docs/evidence/v56-validate-kbx-full.log` and `docs/evidence/v56-fe-interaction-closure-validation.txt`.

## 6. Next P0

The next stage should stop adding structural contracts and execute runtime evidence in a dependency-complete environment:

1. OMS-ORD-001 Drawer open/close and row-focus restore at 1440x900 and 1280x720.
2. OMS-ORD-002 keyboard-only transaction from customer F2 through grid entry, validation failure, correction and F8 save.
3. OMS-ORD-003 six-stage Import with partial completion and failed-row retry.
4. COMMON-OPS-001 multi-select bulk claim with a true skipped subset and recovery.
5. COMMON-REC-001 evidence Drawer, exception handoff, and proof that source values never mutate client-side.
6. WMS-PICK-001 at 390x844: duplicate wedge scan, response-loss retry, identity-scope change, stale queue rejection, offline recovery and server-confirmed scan truth.

The release gate should only be promoted from contract PASS to field PASS after those flows are captured with browser traces/screenshots and repeatable fixtures.
