# SortableList lifecycle contract

- **Outcome:** The canonical `SortableList` class preserves its constructor API, caller behavior, drag/touch/keyboard accessibility behavior, and rendered-node identity while adding safe idempotent lifecycle convergence.
- **Status:** IDLE
- **Task ID:** D5-SORTABLELIST-01
- **Source request:** Owner requested Delivery 5 SortableList lifecycle convergence from current `origin/master`, working directly without delegation, external models, or skills. Read landed lifecycle components and the Delivery 5 contract first; add `mount()`, `update(next)`, and `destroy()` only where appropriate; test API compatibility, repeated lifecycle calls, drag/listener cleanup, update behavior, remount, and keyboard semantics. Run focused tests, full admin suite, lint, production build, inventory/gate, and full factory gate with dependencies installed. Commit locally and do not land. Independent review then found four release blockers: preserve grabbed ARIA/class/focus across an active keyboard Arrow movement rerender; reset drag/touch state, ghost, placeholder, and listeners before an update-driven rerender; retain item-node identity for no-op/unchanged updates; and correct the receipt to claim only verified behavior. Final review found two further blockers: handle `touchcancel` through the same cleanup path as touch end with regression coverage for ghost, placeholder, class, and state cleanup; and correct the receipt because the reviewed repair is already committed.
- **Acceptance criteria:** Existing constructor API and callers remain compatible. The same container/root/list item nodes remain stable for lifecycle calls that do not require content reconciliation, including `update({})` and supplied values equal to current state. `mount()` and `destroy()` are idempotent; destroy removes active per-item event listeners and transient drag/touch/keyboard artifacts; remount restores interactions exactly once. An active keyboard move retains the grabbed class, `aria-grabbed`, selected index, and focus after its required rerender. An update-driven rerender clears active drag/touch state, ghost, placeholder, and listeners. `update(next)` applies changed supported public state without replacing the container. Focused coverage proves these cases and all required gates pass with dependencies installed.
- **Preserved WIP/ref/path:** Clean isolated worktree `/home/user/Projects/Press.zone/wordpress/wp-content/.claude/worktrees/agent-aa8f875a5eca709b3` at `3edde4f654d956dee8082993f6f1f39b2922c418`, matching fetched `origin/master`; no pre-existing changes.
- **Constraints:** Change only `admin/src/components/SortableList.js`, focused lifecycle coverage, and truthful plan/inventory records. Do not alter public APIs, unrelated components/pages, generated assets, caller behavior, or land the commit.
- **Execution steps:** Study landed lifecycle sources/tests; implement minimal idempotent lifecycle ownership; add focused regression coverage; run every required gate; commit locally; record exact outcomes.
- **Current receipt:** The local-only touch-cancel repair is committed. `touchcancel` now uses the same `_resetInteractionState()` cleanup path as touch end. Regression coverage proves it removes the dragging class, drag/touch state, ghost, and placeholder. Focused lifecycle coverage passes (7/7); full admin suite passes (51 files/676 tests); lint, production build, inventory/gate, and complete factory gate pass with installed locked dependencies. Inventory remains 123 modules, 54 components, 16 pages, zero unclassified modules, zero direction violations, and two baseline duplicate IDs.
- **Next executable action:** None within this local-only slice; landing remains excluded.
