# Lane R7 — PG-33 clean-install proof receipt (2026-08-22)

Status: **PG-33 GREEN end-to-end.** The distributable release ZIP installs, activates, uninstalls, and reinstalls cleanly on a WordPress stack with **no source checkout mounted**, proven by a remote Playwright run.

## 1. Release identity

- Base commit (origin/master at lane start): `c79c880bb` (includes the Lane R6 PG-33 test capability, landed sol-approved).
- Release commit: `e52662cc9` (`Release 0.9.84`) on branch `wt/lane-r7-pg33-proof-20260822`.
- Plugin version: `0.9.84` — built by `node tools/build-distribution.mjs` (builder owns the version transaction; preflight predicted 0.9.83, builder produced 0.9.84).
- Archive: `dist/international-press-zone-0.9.84.zip`
  - Archive SHA-256: `507f747aac02e93df9e8da6007d12ff01d6103454bc3c89e543e622755e40c22`
  - Runtime SHA-256: `7a202bab6739e43032bafb609cbeb93343c79104136d188bf0df08c8959d04cb`
  - 233 files; `--verify` re-validation passed.
- Preflight: `node tools/release-preflight.mjs` → `pass: true`, `blocking: []`; Stripe clearance items are `waiting_external` (scoped to PG-46), not blockers.

## 2. Test capability

Spec: `tests/e2e/clean-install-zip.spec.js` (landed in `c79c880bb`, oracle fix in this lane).
Stack mode: `IPZ_STACK_NO_PLUGIN_MOUNT=1` — `remote-stack.sh` provisions the WordPress container **without** mounting the plugin checkout; the only way the plugin exists is the ZIP uploaded through wp-admin.

The spec, in one browser session (chromium):
1. Logs in, self-heals any pre-existing install (deactivate + delete), asserts plugin row absent.
2. Uploads the ZIP via Plugins → Add New → Upload Plugin, activates, asserts "Plugin activated".
3. Asserts plugin row shows version `0.9.84` (via `IPZ_EXPECTED_VERSION=0.9.84`).
4. Asserts the admin SPA boots: `#ipz-admin-root` visible and `window.internationalPressZone` is an object.
5. Deactivates and deletes (handles WordPress's AJAX delete: `window.confirm` dialog accepted; pre-reload assertion tolerates the "was successfully deleted." notice row that keeps `data-slug`; post-reload assertion requires zero rows).
6. Reinstalls from the same ZIP, re-asserts version and SPA.
7. Asserts zero console errors, zero page errors, and no PHP fatal/warning/notice text on any visited admin page.

## 3. Proof run (remote, canonical)

Host: **debian1** (registry-selected via `/home/user/.claude/bin/e2e-remote`; IPZ gates are remote-only).
Remote mirror: `/home/user/builds/lane-r7-pg33-proof-a98327dfc215/`.
ZIP transport: copied to `tests/e2e/ipz-release-0.9.84.zip` inside the tree (git-snapshot push honors .gitignore, so `dist/` never transfers); the copy is transport-only and is never committed.

Invocation:

```
e2e-remote --server 'bash remote-stack.sh' --wait-port 8080 --wait-sec 600 \
  --env IPZ_STACK_NO_PLUGIN_MOUNT=1 \
  --env IPZ_ZIP_PATH=/home/user/builds/lane-r7-pg33-proof-a98327dfc215/plugins/international-press-zone/tests/e2e/ipz-release-0.9.84.zip \
  --env IPZ_EXPECTED_VERSION=0.9.84 \
  -- bash -c 'npm ci --no-audit --no-fund && npx playwright test clean-install-zip.spec.js --project=chromium'
```

Result (verbatim tail):

```
  ✓  1 [chromium] › clean-install-zip.spec.js:129:5 › PG-33 clean install from release ZIP › uploads, activates, uninstalls, and reinstalls the release ZIP (34.6s)

  1 passed (1.1m)
e2e-remote: client exit=0
```

## 4. Defects found and fixed by the proof run (evidence the proof is real)

Two genuine failures occurred before the pass; both fixes are in commit `1c2ad7a9f` (sol/low approved, zero findings):

1. **Uploads permissions (run 1)**: "The uploaded file could not be moved to wp-content/uploads/2026/08". The volume snapshot tars restore `wp-content` trees root-owned; Apache (www-data) could not write. Fix: `remote-stack.sh` no-mount branch now mkdir+chowns `uploads`, `upgrade`, and `plugins` to www-data. Scoped to the no-mount branch only (the mounted branch has an `:ro` plugin mount a `chown -R` must not touch). Latent until now because mounted mode never uploads.
2. **AJAX delete oracle (run 2)**: WordPress's JS-enabled delete replaces the plugin row content with "was successfully deleted." while keeping `data-slug` on the `<tr>`, so a pre-reload `toHaveCount(0)` can never pass. Fix: pre-reload assertion filters out the success-notice row; the post-reload strict zero-rows assertion is unchanged.

## 5. Verdict

- PG-33 clean-install proof: `[x] WORKS` — flip recorded in `GOLIVE.md` in this lane.
- Out of scope, unchanged: PG-34 (upgrade proof), PG-35 (signed update delivery), PG-46 (backend update catalog).
