# Multilingual Site Entry and Layout — request

Audience: AI coding agents first.

## Status

**ACTIVE — Owner requested completion of all remaining slices. Slice 1 plus dormant navigation, synced-pattern resolution, and Site Content resource handling are DONE; segmented backend translation is the current slice.**

### All-slices continuation (2026-08-14)

- Task ID: `MULTILINGUAL-ALL-SLICES`.
- Source requests: “complete all slices”; latest execution directive: owner-invoked Ask Codex `gpt-5.6-terra/medium` to implement, with main-agent review and merge.
- Current receipt: dormant Site Content identity, request contexts, catalog, repository, codec, block-template resolver, navigation resolver, synced-pattern resolver, and Site Content resource handler are published. Navigation commit `45ee7ef347747ab0ac1cd5e3ba18387f0edec2b0`, synced-pattern commit `2079fefa27fa80fb7e7a00ed01d5680b7538bdec`, and Site Content handler implementation `097a5f64b078078896f88de326278d2101263094` retain no activation seams. Exact current mapping rejects standalone post-handler and controller recovery: post finalization still requires authenticated job/raw callback context, while preserved controller queueing creates inert pending jobs and uses obsolete non-token mutations. Segmented backend translation is the smallest independent prerequisite.
- Remaining gaps: Page grouping/layout metadata and fidelity; segmented backend/capability; post-resource handler plus two-resource dispatch and Site Content controller; admin Site Content UX; runtime/E2E activation and final delivery.
- Constraints: reuse published work; smallest dependency-correct units; default-OFF server flags for incomplete user-facing behavior; every gate MUST run remotely on registry-authorized `debian1`/`debian2`/`debian3` through canonical `/ipz-e2e`; NEVER run gates in local environment; no dev1/dev3 tests.
- Next executable action: implement bounded backward-compatible segmented backend translation and explicit capability metadata. See `2026-08-15-segmented-site-content-backend.md`.

### Slice 1 status

**DONE — Slice 1 is present on `origin/master`, verified against the exact remote tree, and remains separate from Slice 2. No deployment was required for this code-only Slice.**

### Receipt (2026-08-13, Slice 1)

Revived from carrier `refs/wip-snapshot/current-20260811/wt-multilingual-site-entry-and-layout` (`09d3de3ac`; backup `e9a2c64f6`), ported method-by-method onto current master. Slice 1 scope:

- New: `includes/Frontend/LocaleBootstrap.php`, `LocaleContextCoordinator.php`, `LanguageRequestContext.php`, `SpecialPageResolver.php`, `EffectiveTemplateResolver.php`, `LocalizedURLResolver.php`.
- Wiring: `international-press-zone.php` (`LocaleBootstrap::register()` before `plugins_loaded` 10), `includes/Core/Plugin.php` (resolvers, option filters, redirects, permalink/canonical/sitemap/robots/hreflang seams), `includes/Core/LanguageManager.php` (`clearCurrentLanguage()` — the audited semantic seam), `includes/Frontend/ContentFilter.php`, `URLManager.php`, `LanguageSwitcher.php`, `includes/Compatibility/YoastSEOIntegration.php`.
- Tests: new `tests/Unit/Frontend/{SpecialPageResolver,EffectiveTemplateResolver,LocaleContextCoordinator,LocalizedURLResolver}Test.php`, `tests/Unit/Core/PluginSeoRoutingTest.php`; extended `PluginRewriteRulesTest`, `ContentFilterTest`, `URLManagerTest`; all registered in `phpunit.xml.dist`. Suite: 65 tests green.
- Gate diagnosis (2026-08-14): repository pre-commit uses `php tools/phpcs-baseline.php check` only for staged PHP under `includes/` and `international-press-zone.php`. It correctly reported 3,383 violations beyond unchanged baseline across 12 Slice 1 production files; no unchanged file contributed. Earlier 12,653-file run incorrectly included tests outside PHPCS scope. `phpcbf` reduced production surplus to 697; remaining violations require Slice 1 remediation, primarily variable/property naming (459), method naming (51), and required docblocks (140). No baseline growth or suppression accepted. `composer test` passes: 65 tests, 239 assertions. Next: finish production and test-file remediation; restage; run focused tests, `composer test`, changed-file PHPCS, PHPStan, and actual pre-commit; then commit Slice 1.
- PHPCS declaration slice receipt (2026-08-14): declaration and formatting remediation reduced the exact occurrence-baseline surplus to 253 across Slice 1 production files. Focused PHPStan identifies 16 inconsistent property references in `SpecialPageResolver.php` and `LocalizedURLResolver.php`; direct focused PHPUnit exposed order-dependent test bootstrap because `ABSPATH` and WordPress function stubs are supplied by individual test files. The worktree guard correction landed on Overdeck `origin/main`; installed Ask Codex description is owner-only, installed guard bytes include registered `.claude/worktrees` validation, and a real plan edit in this worktree now succeeds. Main agent performs all remaining implementation and review directly; no subagents or Ask Codex. Next: add deterministic shared PHPUnit bootstrap, repair inconsistent renamed symbols and WordPress option keys, then drive focused tests, occurrence-baseline PHPCS, PHPStan, full tests, and pre-commit clean before landing to `origin/master`.

### Reconciliation deltas vs carrier (master diverged; master behavior kept)

- Master replaced the carrier-base `parse_request normalize_language_root_request` with a `request`-filter `filter_language_root_request` + `pre_option_page_on_front` and query var `presszone_international_language_root`. Slice 1 keeps master's routing shape; resolver-based front-page resolution replaces the `ContentManager::getTranslatedPostId` block inside it; legacy path retained only when the resolver is not yet constructed. `LocaleBootstrap::finalize` runs on a new `parse_request` `PHP_INT_MAX` hook.
- Master's `URLManager` already handles the WordPress installation path (`get_home_path()`); kept. Carrier's remaining URLManager seams ported: live `getURLMode()` (no cached mode), REQUEST_URI/HTTP_HOST/`lang` input hardening.
- Carrier bug fixed during port: `option_page_on_front`/`option_page_for_posts` filters recursed (filter → resolver → `get_option` → same filter). `Plugin::$resolvingSpecialPageOption` reentry guard added; both filters return the canonical ID while a resolution is in flight.
- `Plugin::filterDetermineLocale` removed (hook superseded by `LocaleBootstrap` `determine_locale` priority 1; method had no remaining callers).
- HARD-REJECTED from carrier (fake-green / foreign lanes): `admin/dist/**`, `admin/package-lock.json`, all `package.json`, `composer.json`/`composer.lock`, carrier `phpcs-baseline.json`/`phpstan-baseline.neon`, repo-wide phpcs Yoda/error_log sweep, DB partitioning lane, multisite/site-content schema changes in the main plugin file (Slice 2 scope).

### Final Slice 1 receipt (2026-08-14)

- Direct main-agent review completed without subagents or Ask Codex. Scope is limited to Slice 1 routing, locale, URL/SEO integration, focused tests, and the PHPStan baseline entries made obsolete by this implementation.
- Reviewer corrected one mechanical acronym split: `get_special_page_redirect_u_r_l()` is now `get_special_page_redirect_url()`.
- Final gate receipt after the naming correction: PHPUnit `OK (65 tests, 239 assertions)` with no deprecations; direct PHPStan `[OK] No errors`; occurrence-baseline PHPCS exited 0 with no output; staged `git diff --check` exited 0. The Composer PHPStan wrapper hit Composer's fixed 300-second process timeout at 50%; the same configured PHPStan command completed cleanly when run directly without that wrapper timeout.
- Current-master integration preserved the 0.9.51 credential retirement/connect boot changes and current Site Content request-context hardening, adapting Slice 1 consumers to its immutable getter API. The official WordPress parser test now discovers the WordPress root by walking parents instead of assuming checkout depth, so it works in mandatory worktrees.
- Merged-tree gate receipt: PHPUnit `OK (101 tests, 361 assertions)` with no warnings or deprecations; PHPStan `[OK] No errors`; occurrence-baseline PHPCS and `git diff --check` exited 0.
- Delivery controller landed candidate `8291b81c1d3088ff5f9025e2cf22556be073dba0` through remote receipt `81befd7ae`; exact remote verification found `LocaleBootstrap.php`, `get_special_page_redirect_url()`, and the hardened `LanguageRequestContext::effective_language()` API on `origin/master`.

### Next executable action

No Slice 1 action remains. Do not start Slice 2 from this plan receipt.

**Goal:** Ship automatic language-specific homepage/posts-page behavior, clear Page-role/layout UX, and structurally safe Site Editor translation through templates, template parts, navigation, and synced patterns.

**Canonical design:** `docs/specs/2026-08-09-multilingual-site-entry-and-layout-design.md`. Every invariant, failure rule, release gate, and non-goal in that spec is mandatory. This request pins implementation seams and acceptance; never weaken the design to reuse generic post translation.

## Context

Current gaps:

- `international-press-zone.php:126` starts full plugin on `plugins_loaded` priority 10; locale bootstrap required before that point does not exist.
- `includes/Core/Plugin.php::filter_language_root_request()` sends a language root to canonical `page_on_front`, not its target-language translation.
- `includes/Frontend/ContentFilter.php::filterPosts()` filters language after routing and cannot substitute special-page identity.
- `includes/API/PostsController.php::getPosts()` lacks homepage/posts-page/effective-layout metadata and canonical-group pagination.
- `includes/Translation/PostTypeRegistry.php::PROTECTED_TYPES` correctly excludes Site Editor entities. Preserve this exclusion.
- `includes/Translation/TranslationBridge.php::create_translation()` omits Page-template and hierarchy fidelity.
- `admin/src/pages/translations.js` defaults to Theme strings and has no Site Content route.
- backend structured translation handles posts, not stable segmented Site Content resources.

Target deployed WordPress is dev1. Local WordPress content is assistant fixture data and MUST NOT support claims about dev1 configuration.

## Files

### Plugin bootstrap, routing, URLs, SEO

- Modify `international-press-zone.php` — register minimal locale bootstrap before full priority-10 initialization.
- Create `includes/Frontend/LocaleBootstrap.php` — immediate hook registration only; lazy fail-closed context bootstrap.
- Create `includes/Frontend/LocaleContextCoordinator.php` — requested/effective language, locale switching, restoration, request cleanup.
- Create `includes/Frontend/LanguageRequestContext.php` — immutable request context value.
- Create `includes/Frontend/SpecialPageResolver.php` — canonical Reading-role detection and translated-role resolution.
- Create `includes/Frontend/EffectiveTemplateResolver.php` — native `front-page`/`home`/Page hierarchy reporting.
- Create `includes/Frontend/LocalizedURLResolver.php` — one canonical URL source for links, redirects, switcher, SEO, and sitemap.
- Modify `includes/Core/Plugin.php` — consume bootstrap context; replace source-ID root normalization; register exact lifecycle/SEO seams.
- Modify `includes/Frontend/ContentFilter.php` — use effective language and preserve exact-root front-page fallback.
- Modify `includes/Frontend/URLManager.php` — delegate special-role URL generation.
- Modify `includes/Frontend/LanguageSwitcher.php` — root-to-root links and unavailable-target behavior.
- Modify `includes/Compatibility/YoastSEOIntegration.php` — documented ownership filters only; no rendered-HTML scraping.

### Page API and translation fidelity

- Modify `includes/API/PostsController.php` — role/effective-layout/source-group fields; query-level canonical grouping before filters/pagination.
- Modify `includes/Translation/TranslationBridge.php` — copy safe Page layout semantics and map translated parent when available.
- Modify `includes/Translation/PostTypeRegistry.php` only if needed to document/route protection; NEVER remove Site Editor protected types.
- Modify `includes/Core/Plugin.php` — register new REST controller and invalidation hooks.

### Site Content plugin domain

- Create `includes/SiteContent/SiteEntityIdentity.php` — typed internal identity; raw key never exposed as route segment.
- Create `includes/SiteContent/SiteContentCatalog.php` — official WordPress template/entity enumeration and opaque catalog IDs.
- Create `includes/SiteContent/BlockSegmentCodec.php` — block extraction, stable identity/reconciliation, field-specific validation, current-source apply.
- Create `includes/SiteContent/SiteContentRepository.php` — translation rows, monotonic revisions, compare-and-swap, theme/source lifecycle.
- Create `includes/SiteContent/BlockTemplateTranslationAdapter.php` — `wp_template`/`wp_template_part` runtime hooks.
- Create `includes/SiteContent/NavigationTranslationAdapter.php` — `wp_navigation` labels/link mapping through navigation seams.
- Create `includes/SiteContent/SyncedPatternTranslationAdapter.php` — persisted synced `wp_block` overlays through pattern seams.
- Create `includes/API/SiteContentController.php` — catalog/detail/queue/review/delete routes with capability/object/size/idempotency/revision enforcement.
- Create `includes/Translation/TranslationResourceHandler.php` — exactly the spec contract.
- Create `includes/Translation/PostTranslationResourceHandler.php` — existing post finalization behind handler without behavior regression.
- Create `includes/Translation/SiteContentTranslationResourceHandler.php` — segmented payload/finalization for Site Content records.
- Modify `includes/Translation/JobSender.php`, `includes/Translation/JobReceiver.php`, `includes/Translation/TranslationFinalizer.php`, and `includes/Translation/TranslationService.php` — dispatch through exactly two resource handlers; preserve existing post contracts.
- Modify `includes/Core/Database.php` — additive Site Content table plus idempotency columns/indexes and versioned multisite-safe schema creation.
- Modify existing migration/maintenance files under `includes/Migrations/` and `includes/Database/` that own schema version, new-site creation, bounded cleanup, and cache invalidation; do not create a second migration framework.

### Admin UI

- Modify `admin/src/pages/translations.js` — order `Pages`, `Posts`, `Custom Types`, `Site Content`, `Theme Text`, `Plugin Text`; default Pages; preserve legacy hashes.
- Modify `admin/src/pages/content-translate.js` — site-entry cards, role/effective-layout badges, canonical source rows, role/layout/source-language filters, editor guidance.
- Create `admin/src/pages/site-content.js` — Templates, Headers & Footers, Navigation, Patterns subtabs and translation/review states.
- Modify `admin/src/main.js` — Site Content route and capability-aware loading.
- Modify `admin/src/styles/pages/_translations.scss` — responsive, RTL, dark-mode, focus, status, and card styles; no inline CSS.
- Modify existing admin API/i18n utilities only where required by the new routes; preserve centralized escaping and request handling.
- Commit rebuilt `admin/dist/` artifacts and manifest produced by the existing build.

### Backend segmented contract

- Modify `press-zone-backend/api/src/types/index.ts` — backward-compatible segmented request/response types.
- Modify `press-zone-backend/api/src/utils/structuredFields.ts` — validate exact IDs, bounds, and protected placeholders without permitting provider-owned structure.
- Modify `press-zone-backend/api/src/services/geminiClient.ts` — translate segment text/context only; exact-ID response.
- Modify `press-zone-backend/api/src/services/translationService.ts` — detect/validate segmented resources while preserving title/excerpt/content behavior.
- Modify `press-zone-backend/api/src/worker.ts` — queued segmented handling, idempotent completion, exact response contract.
- Modify backend capability/health metadata route used by plugin negotiation — advertise segmented Site Content only after deployment supports it.

### Tests

- Create `tests/Unit/Frontend/SpecialPageResolverTest.php`.
- Create `tests/Unit/Frontend/EffectiveTemplateResolverTest.php`.
- Create `tests/Unit/Frontend/LocaleContextCoordinatorTest.php`.
- Create `tests/Unit/Frontend/LocalizedURLResolverTest.php`.
- Extend `tests/Unit/Core/PluginRewriteRulesTest.php`, `tests/Unit/Frontend/ContentFilterTest.php`, and `tests/Unit/Frontend/URLManagerTest.php`.
- Create `tests/Unit/SiteContent/BlockSegmentCodecTest.php`.
- Create `tests/Unit/SiteContent/SiteContentRepositoryTest.php`.
- Create `tests/Unit/SiteContent/RuntimeAdaptersTest.php`.
- Create `tests/Unit/API/SiteContentControllerTest.php`.
- Add focused Page grouping/fidelity tests under `tests/Unit/API/` and `tests/Unit/Translation/`.
- Create `tests/e2e/multilingual-site-entry.spec.js`.
- Create `tests/e2e/site-content-translation.spec.js`.
- Add backend unit/integration tests beside existing `structuredFields`, `geminiClient`, `translationService`, and worker tests under `press-zone-backend/api/src/__tests__/`.

## Contract

### Locale bootstrap

```text
LocaleBootstrap::register(): void
LocaleContextCoordinator::bootstrap(): LanguageRequestContext
LocaleContextCoordinator::finalizeForParsedRequest(array $queryVars): LanguageRequestContext
LocaleContextCoordinator::restore(): void
```

- `LocaleBootstrap::register()` is called directly from main plugin file after constants/autoload and before `add_action(...mpz_init, 10)`.
- It immediately registers `determine_locale` priority 1, `plugins_loaded` priority 0, and `shutdown` `PHP_INT_MAX`.
- `determine_locale` lazily initializes context if called before `plugins_loaded` 0.
- Missing schema, requirements, language data, option data, or valid URL marker returns canonical locale without initializing/upgrading full plugin.
- Full `Core\Plugin` init at priority 10 consumes the context.
- Explicit public fallback switches through WordPress locale APIs; shutdown/test/worker finalization restores prior locale and clears request state.

### Special pages and effective templates

```text
SpecialPageResolver::getOverview(): SpecialPageOverview
SpecialPageResolver::getRole(int $postId): null|'front_page'|'posts_page'
SpecialPageResolver::resolveForLanguage(string $role, string $languageCode): SpecialPageResolution
EffectiveTemplateResolver::forRole(string $role, ?int $resolvedPostId): EffectiveTemplateResolution
```

- Canonical source IDs come only from captured `show_on_front`, `page_on_front`, and active `page_for_posts`.
- Static front-page target resolves by translation relationship and published visibility.
- Missing/unpublished front target uses whole-document source fallback only at exact language root: source locale/text direction/localization/query filtering, source canonical, `noindex,follow`, no false alternate/sitemap.
- Published posts-page target uses translated slug and native `is_home()` semantics.
- Missing/unpublished posts-page target has no URL, fallback, switcher target, alternate, or sitemap entry; guessed source slug follows normal routing.
- `front-page` controls site front; `home` controls posts index. Cards report effective hierarchy, not `_wp_page_template` alone.
- Stored Reading options never change.

Hook priorities and context exclusions MUST match canonical design exactly.

### URLs and SEO

```text
LocalizedURLResolver::forRole(string $role, string $languageCode): URLResolution
LocalizedURLResolver::forContent(int $postId, string $languageCode): URLResolution
```

One service feeds page/permalink filters, role redirects, language switcher, canonicals, `hreflang`, `x-default`, robots, and WordPress sitemap. Normalize before redirect; preserve safe pagination/query state; never loop. Never redirect preview/feed/embed/REST/admin/cron/CLI. Yoast integration replaces only outputs owned through documented filters.

### Page API response

Existing Page list rows gain:

```json
{
  "canonical_source_id": 123,
  "source_language": "en",
  "site_roles": ["front_page"],
  "assigned_layout": {"id": "template-id", "label": "Default layout"},
  "effective_layout": {"id": "front-page", "label": "Front Page", "origin": "theme"}
}
```

Group translation relationships before search/role/layout/source filters and pagination. Totals describe canonical source rows. Unlinked Pages remain rows.

Translated Page creation preserves `_wp_page_template`, menu order, safe publication attributes, featured-image reference, existing ACF policy, and translated parent when available. It never copies identity/lock/revision/cache/language-link metadata blindly.

### Site catalog and routes

```text
SiteContentCatalog::list(SiteContentQuery $query): SiteContentPage
SiteContentCatalog::get(SiteEntityIdentity $identity): ?SiteEntity
```

Catalog uses official WordPress APIs. Public `catalog_id` is a stable URL-safe digest resolved against current catalog; zero/multiple matches fail. Raw `theme//slug` never enters route path or filesystem lookup.

Routes:

- `GET /site/overview`
- `GET /site-content`
- `GET /site-content/{type}/{catalog_id}`
- `POST /site-content/{type}/{catalog_id}/translations`
- `PUT /site-content/{type}/{catalog_id}/translations/{language}`
- `DELETE /site-content/{type}/{catalog_id}/translations/{language}`

WordPress handles cookie `X-WP-Nonce`; route callbacks enforce capability and object authorization. Validate configured active language, source/target inequality, request bytes, segment count, segment length, total characters, and opaque ID.

POST requires idempotency key. Persist actor/scope/fingerprint/job/response/expiry for 24 hours through terminal status. Same key+fingerprint returns original response without new charge; same key+different fingerprint returns 409. PUT/DELETE require source and translation revisions; stale compare-and-swap returns 409.

### Segmented resource

```json
{
  "resource_type": "site_content",
  "source_language": "en",
  "target_language": "he",
  "segments": [{"id": "opaque-id", "text": "Source text", "context": "core/heading"}]
}
```

Response contains each input ID exactly once and no unknown IDs. Existing post structured-field payloads remain unchanged.

`BlockSegmentCodec` separates `segment_id` from source hash; reconciles revisions by tree/sequence matching; duplicate/ambiguous matches require review. Providers cannot alter URLs, IDs, block names, attributes, placeholders, markup, order, or nesting unless field schema explicitly permits value markup. Runtime starts from current source structure; translated segments are authority; compiled serialization is disposable cache.

### Storage

Site translation row contains numeric ID, entity type/key, source/target languages, source SHA-256, monotonic `translation_revision`, translated segments, disposable compiled cache, status/error/audit timestamps, and unique entity+key+target key.

Every mutation atomically compares source and translation revisions and increments translation revision. Theme/source changes reconcile compatible segments; changed/ambiguous segments show current source and `needs_update`. Theme switch makes old rows inactive; multisite schema/data remain per blog.

### Runtime adapters

- Block template adapter handles only `wp_template` and `wp_template_part` official retrieval hooks.
- Navigation adapter handles `wp_navigation` retrieval/render hooks and internal translated-link mapping.
- Synced pattern adapter handles persisted synced `wp_block`; unsynced/non-persisted patterns belong to containing content.
- Public frontend or explicit plugin preview only. Source Site Editor, generic REST, admin, cron, CLI, management AJAX, and global canonical caches never receive translated variants.

### Admin literals

Top tabs, in order: `Pages`, `Posts`, `Custom Types`, `Site Content`, `Theme Text`, `Plugin Text`.

Site Content subtabs: `Templates`, `Headers & Footers`, `Navigation`, `Patterns`.

Required status/guidance strings:

- `Latest posts (automatic)`
- `Homepage`
- `Posts page`
- `Blog index: editor content is not displayed`
- `Effective layout`
- `Missing homepage translation`
- `Homepage translation is not published`
- `Missing`, `Translating`, `Ready`, `Needs update`, `Failed`

Classic themes retain visible Site Content tab with explanatory disabled state. No fake template rows.

## Behavior

- Release 1 ships homepage/posts-page routing, SEO, and Pages UX with no segmented-backend dependency.
- Release 2 ships Templates and Headers & Footers only after backend metadata advertises segmented capability.
- Release 3 ships Navigation and Patterns only after their runtime adapters pass release gates.
- Keep releases capability-gated and independently deployable; never expose a later release before its named gate.
- Support WordPress 6.0 baseline. Use block attribute `role=content` on WordPress 6.7+ and tested core-schema extraction on WordPress 6.0–6.6.
- Default-language changes atomically reclassify canonical source ownership, invalidate URLs/SEO/catalog caches, and preserve recoverable translation history.
- Uninstall follows existing retention policy: retain translation data unless explicit destructive uninstall is enabled; remove new tables/idempotency records only through that existing destructive path.
- Every failure keeps current source structure live and never exposes stale compiled markup.
- Every cache has invalidation for Reading settings, links, post status/deletion, URL mode, default language, entity/source revision, theme switch, plugin update, and translation mutation.
- Admin interactions satisfy keyboard, live-region, focus restoration, RTL, dark mode, narrow width, reduced motion, and text-plus-icon status requirements.
- Do not add inline CSS.

## Out of scope

- Per-language theme selection.
- Per-language layout/design forks.
- PHP template source translation.
- Dynamic query-result translation as template text.
- Replacement of WordPress Reading settings.
- Unrelated licensing/workflow/admin redesign.
- Removing Site Editor types from `PostTypeRegistry::PROTECTED_TYPES`.
- Using local WordPress data as evidence for dev1.

## Acceptance

### Plugin PHP

Run from `plugins/international-press-zone`:

```bash
composer test
composer phpcs
composer phpstan
```

Expected: all commands exit 0 with no warnings. Tests prove every PHP/unit/integration case listed in canonical design, including bootstrap order, pre-`plugins_loaded` lazy locale, front-page/home hierarchy, source fallback document locale, missing posts-page no-fallback, query-level grouping pagination, redirect loops, REST limits/auth/idempotency/concurrency, block ambiguity, runtime context isolation, theme switch, and multisite new-site schema.

### Admin

Run from `plugins/international-press-zone/admin`:

```bash
npm run lint:js
npm run build
```

Expected: exit 0 with no warnings; committed `admin/dist/` matches source and manifest.

### Backend

Run from `press-zone-backend/api`:

```bash
npm test -- --runInBand
npm run build
```

Expected: exit 0 with no warnings; segmented tests prove exact IDs, limits, placeholder preservation, malformed provider rejection, terminal idempotency replay, retries, and old post payload compatibility.

### Browser

Run Playwright only through `~/.claude/bin/e2e-remote`; never launch workstation browsers. Execute focused `tests/e2e/multilingual-site-entry.spec.js` and `tests/e2e/site-content-translation.spec.js` against authorized dev1 after deployment.

Expected:

- Pages identifies real dev1 homepage without title guessing.
- latest-posts mode states no homepage Page exists.
- cards show correct effective `front-page`/`home` layout.
- target language root renders published translated homepage.
- translated homepage slug redirects once to language root.
- missing homepage uses whole-document source fallback contract.
- missing posts target exposes no false URL/fallback.
- Site Content translation changes text without block-structure changes.
- source template changes produce `Needs update` with current structure.
- screenshots pass desktop/narrow, LTR/RTL, light/dark checks.

### Distribution and dev1

From `plugins/international-press-zone`:

```bash
node tools/build-distribution.mjs
node tools/deploy-dev1.mjs <generated-international-press-zone-version.zip>
```

Expected: archive verification passes; deploy script reports installed active expected version and byte-matching deployed admin assets. Use generated archive path emitted by build; never invent filename.

Deploy backend segmented capability before enabling Site Content queue UI. Verify backend health/capability metadata after deployment. On dev1, read actual Reading configuration, translate one safe homepage and one safe Site Content fixture, verify URLs/SEO/cache/RTL, and remove only fixtures created by this run.

### Receipt (2026-08-14, Slice 1 PHPCS declaration pass)

Status: IDLE. Task ID: `SLICE1-PHPCS-URL-SEO`.

Source request: remediate PHPCS declaration-by-declaration only in `includes/Frontend/URLManager.php`, `includes/Frontend/LanguageSwitcher.php`, `includes/Compatibility/YoastSEOIntegration.php`, and `tests/Unit/Frontend/URLManagerTest.php`; preserve staged WIP and behavior; sanitize input; do not reset, stash, clean, mass-format, baseline, suppress, commit, or deploy.

Acceptance: direct PHPCS passes all four scoped files; focused `vendor/bin/phpunit tests/Unit/Frontend/URLManagerTest.php` passes; staged WIP remains staged; no out-of-scope file changes except this receipt.

Preserved WIP: all four scoped files and `docs/plans/INDEX.md` were staged before this pass. They now show `MM`; staged content was not changed. No reset, stash, clean, suppression, commit, or deployment ran.

Current receipt:

- Loaded `.claude/agents/expert.md` and `wordpress-php-integration`.
- Renamed scoped declarations, properties, locals, internal calls, and focused test references to PHPCS snake_case forms. Dependency APIs were not globally renamed.
- Replaced discouraged `parse_url()` calls in `URLManager` with `wp_parse_url()`.
- Changed `lang` query handling to unslash before sanitization.
- `git diff --check` passes.
- Focused PHPUnit remains red with the same 11 behavioral errors present at baseline (`Tests: 12, Assertions: 1, Errors: 11`); the fixture also needs a `wp_parse_url()` stub after the parser change.
- Production PHPCS is improved but still red. Remaining findings are member `@var` docs, comment punctuation, direct-input sniff handling, output escaping in the exception message, and residual declaration references. The test fixture additionally has global/curly namespace and stub-prefix/docblock findings.

Blocker investigation limit: one focused remediation pass plus two direct gate cycles. Limit reached; no unsafe mass-format or suppression used.

Next executable action: continue surgically from current unstaged delta. Finish production PHPCS messages first; add the faithful `wp_parse_url()` test stub; restructure or prefix test stubs without changing behavior; run direct four-file PHPCS and focused PHPUnit. Do not start Slice 2.
