# Translation tab pagination and cache — plan

Audience: AI coding agents first.

**Status:** DONE

**Outcome:** ACF/Fields, Posts, Themes, Plugins, and CPT Translation tabs return at most 20 rows per page from server-side pagination and normally paint from a WordPress-local database snapshot before expensive source work runs.

**Task ID:** 15

**Source request:** On 2026-08-12, owner reported long Translation-tab queries and required 20 items per page, WordPress-side cache-first loading, and cache-busting when relevant data changes.

**Acceptance criteria:**
- Every requested tab requests and reports exactly 20 items per page.
- Pagination reduces source/database work; handlers MUST NOT assemble an entire eligible collection merely to slice one page.
- Cache identity includes site, user, granted permissions, locale, route, normalized page/query filters, plugin version, schema version, and invalidation generations.
- A valid hit bypasses source handler. A stale hit returns immediately and schedules at most one deferred refresh. Source failure retains last valid snapshot.
- Successful relevant mutations/lifecycle events invalidate only affected groups; failures do not invalidate.
- ACF response/UI behavior remains compatible with separate ACF remodeling lane; this task changes only pagination/cache contracts needed for 20-item pages.
- Focused PHP and admin tests prove page bounds, totals, key separation, hit/stale query suppression, refresh deduplication, and invalidation.
- Full clean project gates pass; release lands on `origin/master`, deploys to dev1, and installed version/archive/assets match.

**Preserved WIP/ref/path:** Work only in `/home/user/Projects/Press.zone/wordpress/wp-content/.worktrees/paginate-translation-tabs` on `wt/paginate-translation-tabs`, based on fresh `origin/master` at `9ce007c4e`. Preserve all unrelated worktrees and shared-checkout WIP. Another session owns ACF visual and interaction remodeling.

**Constraints:**
- No subagents.
- Use existing `DataStore`, `DataRegion`, `AdminDataPolicy`, `RestResponseCache`, and WordPress transient-backed `ObjectCache` seams.
- Never persist authentication, nonces, licensing, payments, migrations, active jobs, or live progress.
- No browser tests against dev1. Browser verification, if required, runs only against authorized local infrastructure through `e2e-remote`.
- No force push, `--no-verify`, raw stash pop, or shared-main mutation.

**Execution steps:**
1. Map each tab to client store, REST route, source query, response envelope, cache policy, and mutation/lifecycle hooks.
2. Add failing focused tests for fixed page size, source-side pagination, cache bypass/stale refresh, normalized query identity, and precise invalidation.
3. Set requested clients and normal list endpoints to 20; move pagination into source/database/scanner queries where currently post-sliced.
4. Correct cache policy and invalidation so cached snapshots serve before source handlers and affected first pages can refresh outside navigation.
5. Run focused tests, static analysis, formatting, admin tests/build, and authorized local browser verification; resolve every signal.
6. Commit, land through project delivery controller, build next patch release, deploy to dev1, and verify installed identity and packaged assets.

**Current receipt:** Fixed 20-row source pagination is implemented for ACF field groups and content/string result rows. Themes/Plugins keep their complete source selector because limiting that selector would hide sources rather than reduce scanner work; their selected-source string rows paginate at 20. Broad-capability content requests use SQL count plus `LIMIT 20 OFFSET`; restricted users retain per-object authorization before slicing. ACF graph construction occurs after slicing group definitions. Cache policy keys ACF pages by `page` and `per_page`; existing cache hit/stale, deduplication, and invalidation suites remain green. Verification: ACF standalone contract passed; focused PHP cache suites passed 131 tests/721 assertions; PHPStan passed; focused admin suites passed 49 tests; complete admin suite passed 570 tests; production admin build completed cleanly.

**Final receipt:** Implementation commit `9234115b6` and release commit `1e8c9a677` are published on `origin/master`. Release archive `international-press-zone-0.9.47.zip` contains 181 runtime files and has runtime SHA-256 `7c0724395b0eca5a17dacc8c297219ebd9108175c2650e80e81f929dc3479eac`. The authenticated deployment replaced active 0.9.46 without deactivation; dev1 reports International Press Zone 0.9.47 active, and every packaged admin manifest/CSS/JS asset was verified byte-for-byte after installation.

**Next executable action:** None.

**Resume receipt:** Owner resumed full end-to-end execution. Task #15 is active in the preserved worktree.

**Latest receipt:** Remote fleet connectivity is online, but its seat audit is unhealthy on all three hosts. Despite that doctor failure, the normal remote-only test dispatcher succeeded after dependencies were installed: REST cache 63 tests/251 assertions and focused admin pagination 32 tests passed. Cache invalidation tests passed (35/181 and 14/25). The localization policy test exposed nine fixture/contract failures after a proposed tag change; that change was reverted rather than weakening the frozen contract. PHP syntax checks pass.
