frontend-patterns/research/experiments/feature-release/README.md
tegwick f273a190f0 Test activation conflicts and draft-preserving application reload
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9
2026-09-26 23:30:15 +02:00

77 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Feature publication, activation and rollback experiment
Executed 2026-09-26. Seven scenarios in Chromium 151.0.7922.34 and Firefox 155.0;
14/14 assertions met. [Review](../../reviews/FeatureReleaseExperiment.md),
[results](result.json), [provenance](provenance.json).
This is an authored synthetic host using real browser-native modules/import maps,
not execution of the earlier FSD/single-spa examples or a production release system.
The host API is fixed at 1. Reports R1/R2 support 1, R3 declares 2; Account A1 stays
unchanged. Each new HTML document receives the current map. Published assets and
activation bindings are separate in-memory controls in the test server.
## Reproduce
From this directory:
```bash
npm ci --ignore-scripts --cache /tmp/fep-npm-cache
PLAYWRIGHT_BROWSERS_PATH=/tmp/fep-playwright-browsers node node_modules/playwright/cli.js install firefox
PLAYWRIGHT_BROWSERS_PATH=/tmp/fep-playwright-browsers FEP_CHROMIUM_PATH=/path/to/chrome npm test
```
Playwright 1.63.0 is locked. Recorded runs used the same browser binaries identified
by hashes in provenance.json, with an explicit Chromium executable override. Firefox
required execution outside the workspace sandbox to access its temporary profile.
No external network is used during cases. Loopback server/browser cleanup is automatic.
Outputs default to `/tmp/fep-release-result.json` and an incomplete checkpoint at
`/tmp/fep-release-checkpoint.json`; `FEP_RESULT_PATH` overrides the final destination.
Any failed assertion produces nonzero exit. Receipts are not overwritten automatically.
## Cases and limits
| Case | Observed result in both browsers |
| --- | --- |
| X01 Publish R2 without changing binding | Fresh page still uses R1; no R2 request |
| X02 Activate compatible R2 | Fresh page R2; old loaded and old lazy pages R1; Account A1 unchanged |
| X03 Activate incompatible R3 | Host rejects mount, Account works; R3 module has already evaluated |
| X04 Point binding to missing artifact | Reports error, Account navigation still usable |
| X05 Roll binding back R2 → R1 | Fresh page R1; running page R2; explicit reload gets R1 |
| X06 Retire R1 after activating R2 | Old loaded page retains R1; old lazy page fails; new page uses R2 |
| X07 Fail shared startup module | Both navigation buttons remain disabled; feature loading never starts |
Negative controls intentionally pass when the specified failure is observed. All
responses disable HTTP caching, so this is not a CDN/cache invalidation test. Existing
pages retain their document maps; dynamic map mutation/hot replacement is not tested.
Only the host's deliberately tiny API-version contract is checked; module evaluation
can already have side effects before that check. No backend writes, authentication,
API migrations, atomic/concurrent map updates, accessibility audit or safe reload of
unsaved work is modeled. The startup outage reflects this fixture's chosen dependency,
not an assertion that every independently released frontend must fail that way.
## Activation conflicts and safe update reload
[Review](../../reviews/ActivationConflictsAndReload.md) and
[receipt](conflicts-reload-results.json): three deterministic stale-writer HTTP cases
and nine reload scenarios in each browser, 21/21 expected observations.
```bash
PLAYWRIGHT_BROWSERS_PATH=/tmp/fep-playwright-browsers FEP_CHROMIUM_PATH=/path/to/chrome node conflicts-reload.mjs
```
Uses the same pinned dependencies/browsers as the original release experiment.
Default output `/tmp/fep-conflicts-reload.json`; `FEP_RESULT_PATH` overrides it.
Incomplete browser progress goes to `/tmp/fep-conflicts-reload-checkpoint.json`.
The earlier host, runner and receipts remain unchanged. The new reload-host.js is
an authored policy using sessionStorage, explicit user choices and schema checks.
C01 and R01 deliberately reproduce data loss from unsafe choices. C02 refetches and
reapplies a disjoint intent; C03 rejects a conflicting stale rollback. R02–R09 exercise
update deferral, preservation, storage refusal, incompatible schema, explicit discard,
unknown-outcome gating, edits during preflight and activation after preflight.
Activation comparison/replacement is atomic only within this single-process model;
its revision header and 409 response are not a full HTTP precondition implementation.
Storage refusal is injected. Preservation assumes retention is authorized and protects
only the tested same-tab reload. Native reload/tab close, crashes, real backend
outcome recovery, multiple tabs and automatic schema migration remain out of scope.