Measure navigation history and cache corroboration cycle

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9
This commit is contained in:
tegwick 2026-09-27 00:11:21 +02:00
parent f3697c1447
commit d32774da51
20 changed files with 2917 additions and 24 deletions

View file

@ -350,6 +350,8 @@ research/evaluations/language-pilot-01/summary.json
research/evolution/EvolutionReport.md
research/evolution/README.md
research/evolution/context.json
research/evolution/cycles/2026-09-27-navigation-effort.json
research/evolution/cycles/2026-09-27-navigation.md
research/evolution/ledger.json
research/evolution/profiles.json
research/evolution/snapshots/baseline-2026-09-26.json
@ -395,6 +397,12 @@ research/experiments/matrix-recovery/package-lock.json
research/experiments/matrix-recovery/package.json
research/experiments/matrix-recovery/provenance.json
research/experiments/matrix-recovery/result.json
research/experiments/navigation-history/README.md
research/experiments/navigation-history/experiment.mjs
research/experiments/navigation-history/initial-partial.json
research/experiments/navigation-history/package-lock.json
research/experiments/navigation-history/package.json
research/experiments/navigation-history/result.json
research/plan/OpenQuestions.md
research/plan/ResearchProgram.md
research/plan/ResearchProtocol.md
@ -414,6 +422,7 @@ research/reviews/LocalFirstAdmissionScreen.json
research/reviews/LocalFirstEvidenceExpansion.md
research/reviews/MatrixRecoveryExperiment.md
research/reviews/NavigationCoverage.md
research/reviews/NavigationHistoryExperiment.md
research/reviews/NavigationRenderingEvidence.md
research/reviews/NestedDismissalIsolation.md
research/reviews/NestedOwnershipRouting.md

View file

@ -41,3 +41,12 @@ Proposed connections: [URL-addressable State](URLAddressableState.md) supports s
view selection; [Mutation Outcome Tracking](MutationOutcomeTracking.md) matters when
an enhanced write becomes uncertain. Neither is a universal dependency.
[VC-03](../walkthroughs/VC03-ContentPublication.md) explores a read-only core.
## Prospective runtime corroboration — 2026-09-27
Native links and GET filtering remain usable with JavaScript disabled or htmx
loading failed. An enhanced 503 keeps the old URL/view, and an explicitly provided
native recovery link navigates successfully. This does not establish automatic fallback,
late-script safety, accessible focus/announcements or offline availability.
See [NH01–NH06](../reviews/NavigationHistoryExperiment.md). One authored application
with a real package, not independent deployed recurrence. Hypothesis retained.

View file

@ -38,3 +38,12 @@ Application State seed; no canonical identity or admitted relations.
Proposed connection: [Progressive Enhancement](ProgressiveEnhancement.md) can preserve
native navigation while adding faster transitions; it is optional, not required by
addressability. [VC-03](../walkthroughs/VC03-ContentPublication.md) is a synthetic trace.
## Prospective runtime corroboration — 2026-09-27
Direct filtered entry, reload, snapshot restoration and explicit history-miss recovery
preserve selection in a pinned htmx fixture. Omitting representation Vary reproduces
a fragment served as a full document in Chromium and Firefox; correct selection
keeps representations distinct, without promising cache retention or freshness.
See [NH01–NH06](../reviews/NavigationHistoryExperiment.md). One authored application
with a real package, not independent deployed recurrence. Hypothesis retained.

View file

@ -164,3 +164,12 @@ SRC-0036 follow-up: [activation conflicts and update reload](../reviews/Activati
adds an authored conditional-write server and reload policy with sessionStorage.
Three HTTP cases plus nine cases per browser, 21/21 expected observations; negative
controls included. Same synthetic evidence family, not an independently deployed use.
## Prospective navigation runtime — 2026-09-27
SRC-0038: [navigation/history fixture](../experiments/navigation-history/README.md),
htmx 2.0.11 and Playwright 1.63.0 with locked packages and hashed inputs/browser
binaries. Authored HTTP application; 18 browser cases plus explicit HTTP validator
sequence repeated twice. [NH01–NH06 review](../reviews/NavigationHistoryExperiment.md),
preregistered prospective corroboration. This is one implementation family, not
an independent production deployment. Initial launch failure receipt preserved.

View file

@ -1,6 +1,6 @@
# Language evolution report
Generated by `make evolution-report`; curated assessment date: 2026-09-26.
Generated by `make evolution-report`; curated assessment date: 2026-09-27.
This is an evidence profile, not a completion percentage. Evidence presence does not establish full-contract recurrence or production fitness.
@ -14,7 +14,7 @@ The baseline profiles are author-model assessments by Codex; they do not confer
| --- | ---: |
| documentary | 17 |
| static-code | 5 |
| runtime | 6 |
| runtime | 8 |
Categories overlap. Runtime includes authored fixtures and negative controls. Family labels group related evidence; they are not counts of independent applications.
@ -22,7 +22,7 @@ Independent human profile reviews: 0/17. Full-contract independent-use counts un
## Change since baseline
Baseline baseline-2026-09-26; source revision `f273a190f0e08b8cfe0bb7260d0e7d889f1c090a`. Added: 0; removed: 0; shared candidates with changed content: 0; changed evidence/review assessments: 0; maturity transitions: 0.
Baseline baseline-2026-09-26; source revision `f273a190f0e08b8cfe0bb7260d0e7d889f1c090a`. Added: 0; removed: 0; shared candidates with changed content: 2; changed evidence/review assessments: 2; maturity transitions: 0.
The shared cohort is compared separately from additions. Changed text or evidence counts are not learning gains.
@ -47,25 +47,31 @@ One frozen development pilot with submitted model review; six matched briefs. Eq
## Learning and effort
Selected retrospective outcomes, not a complete historical census. All entered 2026-09-26; historical effort unmeasured. Prospective cycles begin after this baseline.
Ten selected retrospective outcomes (not a historical census), followed by prospectively registered bounded cycles. Retrospective effort remains unknown.
| Outcome | Entries (not independent discoveries) |
| --- | ---: |
| corroboration | 0 |
| corroboration | 1 |
| inconclusive | 0 |
| merge | 0 |
| rejection | 0 |
| revision | 10 |
Cycles with recorded research effort: 0/10. Unknown effort is neither zero nor estimated from commits, tokens or assertion counts.
Cycles with recorded research effort: 1/11. Unknown effort is neither zero nor estimated from commits, tokens or assertion counts.
No prospective comparison windows yet. Learning rate and diminishing returns: **not measurable from this baseline**.
### Stream B / B-navigation-mechanism-v1
| Cycle | Outcome | Research minutes | Consequential outcome/hour |
| --- | --- | ---: | ---: |
| LEARN-0011 | corroboration | 6.177 | 0.00 |
One bounded question counts at most one consequential outcome. Corroboration and inconclusive work remain visible separately. Fewer than three comparable cycles: no trend assessment.
## Coherence and maintainability
Profile hashes and local references passed validation when this report was generated. That checks traceability, not source truth or external URL freshness.
Profiles with unknown last substantive review date: 17. Assessment dates record this metadata review, not a new substantive validation. No age-based freshness claim is available for those profiles.
Profiles with unknown last substantive review date: 15. Assessment dates record this metadata review, not a new substantive validation. No age-based freshness claim is available for those profiles.
Coherence metrics (ambiguous selections, unjustified relations and overlap resolved): not measured. Conflict Copy / Explicit Reconciliation overlap remains an explicit open question.
@ -207,8 +213,9 @@ Make a navigable state reconstructible from its URL.
| --- | --- | --- | --- |
| documentary | htmx | History behavior and history-cache misses. | [NavigationRenderingEvidence](../../research/reviews/NavigationRenderingEvidence.md) |
| documentary | Web platform | pushState changes history, not server dereferenceability. | [NavigationRenderingEvidence](../../research/reviews/NavigationRenderingEvidence.md) |
| runtime | htmx in authored public-catalog fixture | NH01–NH06: native/enhanced routes, history hit/miss, actual browser cache ordering and missing-Vary negative control; explicit Node validator checks separate. | [NavigationHistoryExperiment](../../research/reviews/NavigationHistoryExperiment.md) |
Open limits: Direct load, history miss and full/fragment cache runtime checks pending.
Open limits: Independent deployed full-contract recurrence remains unverified. Keyboard/focus/announcements, late-script activation, interrupted transport, invalid/deleted routes, offline availability and real intermediary behavior remain open.
Superseded by: none recorded.
@ -222,8 +229,9 @@ Keep essential actions usable when enhancement is unavailable.
| --- | --- | --- | --- |
| documentary | htmx | Boosted links and forms. | [NavigationRenderingEvidence](../../research/reviews/NavigationRenderingEvidence.md) |
| documentary | SvelteKit | Form actions and rendering/page options. | [NavigationRenderingEvidence](../../research/reviews/NavigationRenderingEvidence.md) |
| runtime | htmx in authored public-catalog fixture | NH01–NH06: native/enhanced routes, history hit/miss, actual browser cache ordering and missing-Vary negative control; explicit Node validator checks separate. | [NavigationHistoryExperiment](../../research/reviews/NavigationHistoryExperiment.md) |
Open limits: No executed no-script workflow or deployed independent recurrence study.
Open limits: Independent deployed full-contract recurrence remains unverified. Keyboard/focus/announcements, late-script activation, interrupted transport, invalid/deleted routes, offline availability and real intermediary behavior remain open.
Superseded by: none recorded.
@ -473,3 +481,17 @@ Evidence: [ActivationConflictsAndReload](../../research/reviews/ActivationConfli
Remaining uncertainty: One-process atomicity; no native unload, crash or real remote-outcome coverage.
Supersedes: none recorded.
### LEARN-0011 — Can a public route preserve selection and complete-document availability across native/enhanced entry, history and HTTP caching?
2026-09-27 · stream B · prospective · corroboration
Before: Native href/GET contracts plus representation-aware routing and cache selection should satisfy this narrow obligation; documentary support lacked runtime checks.
Conclusion: Corroborated in pinned htmx fixture: native and history paths work; missing Vary reproduces fragment-as-document reuse in both browsers. Existing obligations stand; no new pattern or promotion.
Evidence: [NavigationHistoryExperiment](../../research/reviews/NavigationHistoryExperiment.md), [result](../../research/experiments/navigation-history/result.json), [2026-09-27-navigation-effort](../../research/evolution/cycles/2026-09-27-navigation-effort.json).
Remaining uncertainty: One authored application, no independent recurrence or usefulness gain. Accessibility, delayed scripts, interrupted transport, real intermediaries and offline availability remain open.
Supersedes: none recorded.

View file

@ -0,0 +1,45 @@
{
"start_utc": "2026-09-26T22:02:55Z",
"start_monotonic": 198212.69757878,
"execution_seconds": 61.257515474018874,
"method": "Single-agent continuous active session; subtract timed experiment and verification subprocess durations. Includes planning, implementation and analysis; excludes final commit/sync after cutoff. No overlap.",
"start_utc_note": "UTC label is initial orientation clock reading; monotonic measurement began after orientation as preregistered.",
"executions": [
{
"command": [
"node",
"research/experiments/navigation-history/experiment.mjs"
],
"seconds": 12.89531968801748,
"exit_code": 1
},
{
"command": [
"node",
"research/experiments/navigation-history/experiment.mjs"
],
"seconds": 34.61645083199255,
"exit_code": 0
},
{
"command": [
"make",
"evolution-check",
"evolution-test",
"schema-test",
"bench-test"
],
"seconds": 13.745744954008842,
"exit_code": 0
}
],
"status": "complete",
"end_utc": "2026-09-26T22:11:04.416742+00:00",
"measured_start_utc_approx": "2026-09-26T22:03:52.518569+00:00",
"elapsed_seconds": 431.898,
"research_minutes": 6.177,
"execution_minutes": 1.021,
"precision": "Monotonic subprocess durations; minute fields rounded to 0.001, not a claim of human effort precision.",
"excluded": "Orientation before timer start and administration/final receipt refresh after this cutoff. Checkpoint inspection during experiment assigned to execution only.",
"budget_review": "Within 45 active research minutes and 10 execution minutes; no scope extension."
}

View file

@ -1,6 +1,6 @@
{
"schema_version": 1,
"coverage": "Selected retrospective outcomes, not a complete historical census. All entered 2026-09-26; historical effort unmeasured. Prospective cycles begin after this baseline.",
"coverage": "Ten selected retrospective outcomes (not a historical census), followed by prospectively registered bounded cycles. Retrospective effort remains unknown.",
"events": [
{
"id": "LEARN-0001",
@ -336,6 +336,43 @@
"cost_usd": null
},
"supersedes": []
},
{
"id": "LEARN-0011",
"date": "2026-09-27",
"recording": "prospective",
"stream": "B",
"comparison_group": "B-navigation-mechanism-v1",
"protocol_ref": "research/evolution/cycles/2026-09-27-navigation.md",
"question": "Can a public route preserve selection and complete-document availability across native/enhanced entry, history and HTTP caching?",
"previous_belief": "Native href/GET contracts plus representation-aware routing and cache selection should satisfy this narrow obligation; documentary support lacked runtime checks.",
"conclusion": "Corroborated in pinned htmx fixture: native and history paths work; missing Vary reproduces fragment-as-document reuse in both browsers. Existing obligations stand; no new pattern or promotion.",
"disposition": "corroboration",
"affected_patterns": [
"CAND-0009",
"CAND-0010"
],
"evidence": [
"research/reviews/NavigationHistoryExperiment.md",
"research/experiments/navigation-history/result.json",
"research/evolution/cycles/2026-09-27-navigation-effort.json"
],
"remaining_uncertainty": [
"One authored application, no independent recurrence or usefulness gain.",
"Accessibility, delayed scripts, interrupted transport, real intermediaries and offline availability remain open."
],
"reviewer": {
"name": "Codex",
"role": "author-model",
"independent_human": false
},
"effort": {
"research_minutes": 6.177,
"execution_minutes": 1.021,
"reported_tokens": null,
"cost_usd": null
},
"supersedes": []
}
]
}

View file

@ -1,6 +1,6 @@
{
"schema_version": 1,
"assessed_at": "2026-09-26",
"assessed_at": "2026-09-27",
"profiles": [
{
"id": "CAND-0001",
@ -317,7 +317,7 @@
"id": "CAND-0009",
"path": "research/candidates/URLAddressableState.md",
"title": "URL-addressable State",
"sha256": "45132f34aa762b453c36c9bc6b418ab7f9ce17097365995b2792fd173f6aa11e",
"sha256": "3edc087c5b4b0a332dd9097334022cdb138437413b933f271e5cf96096cc63be",
"status": "draft",
"maturity": "hypothesis",
"decision": "Make a navigable state reconstructible from its URL.",
@ -333,18 +333,25 @@
"family": "Web platform",
"ref": "research/reviews/NavigationRenderingEvidence.md",
"scope": "pushState changes history, not server dereferenceability."
},
{
"kind": "runtime",
"family": "htmx in authored public-catalog fixture",
"ref": "research/reviews/NavigationHistoryExperiment.md",
"scope": "NH01–NH06: native/enhanced routes, history hit/miss, actual browser cache ordering and missing-Vary negative control; explicit Node validator checks separate."
}
],
"independent_full_contract_uses": null,
"review": {
"assessed_at": "2026-09-26",
"assessed_at": "2026-09-27",
"reviewer": "Codex",
"role": "author-model",
"independent_human": false,
"last_substantive_review_date": null
"last_substantive_review_date": "2026-09-27"
},
"gaps": [
"Direct load, history miss and full/fragment cache runtime checks pending."
"Independent deployed full-contract recurrence remains unverified.",
"Keyboard/focus/announcements, late-script activation, interrupted transport, invalid/deleted routes, offline availability and real intermediary behavior remain open."
],
"superseded_by": []
},
@ -352,7 +359,7 @@
"id": "CAND-0010",
"path": "research/candidates/ProgressiveEnhancement.md",
"title": "Progressive Enhancement",
"sha256": "e8bfc9997336b62f67081434528dc3d3dd280c349156da7620bc76f2197f6414",
"sha256": "e9ca2b046cb69fff16379e22e1a9d0d61d2a5801ff92bbfc1b56ae3e3be16c7c",
"status": "draft",
"maturity": "hypothesis",
"decision": "Keep essential actions usable when enhancement is unavailable.",
@ -368,18 +375,25 @@
"family": "SvelteKit",
"ref": "research/reviews/NavigationRenderingEvidence.md",
"scope": "Form actions and rendering/page options."
},
{
"kind": "runtime",
"family": "htmx in authored public-catalog fixture",
"ref": "research/reviews/NavigationHistoryExperiment.md",
"scope": "NH01–NH06: native/enhanced routes, history hit/miss, actual browser cache ordering and missing-Vary negative control; explicit Node validator checks separate."
}
],
"independent_full_contract_uses": null,
"review": {
"assessed_at": "2026-09-26",
"assessed_at": "2026-09-27",
"reviewer": "Codex",
"role": "author-model",
"independent_human": false,
"last_substantive_review_date": null
"last_substantive_review_date": "2026-09-27"
},
"gaps": [
"No executed no-script workflow or deployed independent recurrence study."
"Independent deployed full-contract recurrence remains unverified.",
"Keyboard/focus/announcements, late-script activation, interrupted transport, invalid/deleted routes, offline availability and real intermediary behavior remain open."
],
"superseded_by": []
},

View file

@ -0,0 +1,40 @@
# Navigation, history and representation-cache experiment
First prospective cycle: [preregistration](../../evolution/cycles/2026-09-27-navigation.md)
at commit `f3697c1`, before implementation/execution. [Review](../../reviews/NavigationHistoryExperiment.md).
Pinned htmx 2.0.11 and Playwright 1.63.0, authored public read-only HTTP fixture.
[Result](result.json) includes input hashes, exact browser versions/binary hashes,
request traces and final DOM/event observations. No real application/CDN or model call.
```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
```
Firefox profile access required execution outside the workspace sandbox. Chromium
was an explicit preinstalled binary override, not claimed to be Playwright's bundled
revision. Default output `/tmp/fep-navigation-result.json`; `FEP_RESULT_PATH` overrides
it. The runner writes checkpoints to that output and a complete receipt on completion.
Choose a new output per run; committed receipts are never default outputs.
[Initial partial receipt](initial-partial.json) retains ten passing Chromium rows;
launch then failed because Firefox was not in Playwright's default cache. Setting the
existing browser-cache path fixed execution, without changing runner or criteria.
The full run repeated Chromium and completed Firefox: 20/20 registered checks, not
30 independent observations. N10 repeats explicit Node HTTP checks in each browser
group; those two rows are not evidence of browser-specific automatic revalidation.
N09 records the negative control, including non-reproduction if that ever occurs.
N01–N06 cover direct/native/enhanced/history/recovery paths; N07–N09 use actual browser
HTTP cache with no request interception. N08's final full fetch reaches the server
again in both browsers: correctness does not imply simultaneous retention of both
variants or optimal cache hit rate. Both N09 runs reuse the fragment without another
request. The server varies on both request selectors and computes ETags from response
bytes. htmx history requests explicitly disable HX-Request; the server separately
supports the history-restore header overriding fragment selection.
History eviction uses htmx 2.0.11's sessionStorage key, an experimental control tied
to the pinned implementation. No assertion of identical content freshness across
history, general offline availability, accessibility, script-late races, writes,
real intermediary correctness or independent full-pattern recurrence follows.

View file

@ -0,0 +1,114 @@
import {chromium, firefox} from 'playwright';
import {createServer} from 'node:http';
import {once} from 'node:events';
import {readFile, writeFile} from 'node:fs/promises';
import {createHash} from 'node:crypto';
import assert from 'node:assert/strict';
const dir=new URL('.',import.meta.url);
const htmx=await readFile(new URL('node_modules/htmx.org/dist/htmx.js',dir));
let requests=[];
const observer=`window.probe=[];for(const name of ['htmx:afterSettle','htmx:historyRestore','htmx:responseError'])document.addEventListener(name,e=>window.probe.push({name,url:location.href,cacheMiss:e.detail.cacheMiss}));`;
const server=createServer((req,res)=>{
const url=new URL(req.url,'http://localhost');
const hx=req.headers['hx-request']==='true', restore=req.headers['hx-history-restore-request']==='true';
let status=200,body='',representation='asset';
res.setHeader('Cache-Control','no-store');
if(url.pathname==='/htmx.js'){
status=url.searchParams.has('fail')?503:200;body=status===200?htmx:'blocked enhancement';res.setHeader('Content-Type','application/javascript');
}else if(url.pathname==='/observe.js'){body=observer;res.setHeader('Content-Type','application/javascript');}
else if(['/articles','/cache-good','/cache-bad'].includes(url.pathname)){
const topic=url.searchParams.get('topic')==='beta'?'beta':'alpha';
const fail=url.searchParams.has('scriptfail')?'&scriptfail=1':'';
const main=`<main id="content" hx-history-elt><h1>${topic}</h1><p id="article">Public article ${topic}</p><a id="next" href="${url.pathname}?topic=${topic==='alpha'?'beta':'alpha'}${fail}" hx-boost="true" hx-target="#content" hx-select="#content" hx-swap="outerHTML">Other topic</a><form action="${url.pathname}" method="get"><label>Topic <select name="topic"><option>alpha</option><option>beta</option></select></label><button>Filter</button></form><a id="broken" href="/articles?topic=beta&enhancedfail=1" hx-boost="true" hx-target="#content" hx-select="#content" hx-swap="outerHTML">Injected enhanced failure</a><a id="recover" href="/articles?topic=beta&enhancedfail=1">Native recovery</a></main>`;
representation=hx&&!restore?'fragment':'full';
const full=`<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Public catalog</title><meta name="htmx-config" content='{"historyRestoreAsHxRequest":false}'><script src="/observe.js"></script><script src="/htmx.js${fail?'?fail=1':''}" defer></script></head><body><header id="shell">Catalog shell</header>${main}</body></html>`;
body=representation==='full'?full:main;
if(hx&&url.searchParams.has('enhancedfail')){status=503;body='Injected enhancement outage';}
res.setHeader('Content-Type','text/html; charset=utf-8');
if(url.pathname.startsWith('/cache-')){
res.setHeader('Cache-Control','public, max-age=3600');
const etag='"'+createHash('sha256').update(body).digest('hex')+'"';res.setHeader('ETag',etag);
if(url.pathname==='/cache-good')res.setHeader('Vary','HX-Request, HX-History-Restore-Request');
if(req.headers['if-none-match']===etag){status=304;body='';}
}
}
else{status=404;body='Not found';}
requests.push({path:req.url,hx,restore,ifNoneMatch:req.headers['if-none-match']||null,status,representation,vary:res.getHeader('Vary')||null,etag:res.getHeader('ETag')||null});
res.writeHead(status);res.end(body);
});
server.listen(0,'127.0.0.1');await once(server,'listening');
const base=`http://127.0.0.1:${server.address().port}`;
const results=[], browsers={};
const output=process.env.FEP_RESULT_PATH||'/tmp/fep-navigation-result.json';
try{
for(const [engine,launcher] of [['chromium',chromium],['firefox',firefox]]){
const executablePath=engine==='chromium'?process.env.FEP_CHROMIUM_PATH:undefined;
const browser=await launcher.launch({headless:true,...(executablePath?{executablePath}:{})});
const binary=executablePath||launcher.executablePath();
browsers[engine]={version:browser.version(),executable:binary,sha256:createHash('sha256').update(await readFile(binary)).digest('hex')};
try{
async function scenario(id,run,javaScriptEnabled=true){
requests=[];const context=await browser.newContext({javaScriptEnabled});const page=await context.newPage();page.setDefaultTimeout(4000);
const result={id,engine,status:'pass'};
try{result.observation=await run(page,context);}catch(e){result.status='fail';result.error=e.message;}
result.requests=[...requests];result.url=page.url();result.body=await page.locator('body').innerText().catch(()=>null);
result.events=javaScriptEnabled?await page.evaluate(()=>window.probe||[]).catch(()=>[]):[];
results.push(result);await context.close();
await writeFile(output,JSON.stringify({status:'incomplete',results},null,2)+'\n');
}
async function selected(p,topic){await p.locator('h1').filter({hasText:topic}).waitFor();assert.equal(new URL(p.url()).searchParams.get('topic'),topic);}
async function enhanced(p){await p.waitForFunction(()=>window.htmx?.version==='2.0.11');}
async function next(p,topic){await p.locator('#next').click();await selected(p,topic);await p.waitForFunction(()=>window.probe.some(e=>e.name==='htmx:afterSettle'));}
await scenario('N01-no-script-native',async p=>{
await p.goto(base+'/articles?topic=alpha');await selected(p,'alpha');assert.equal(await p.locator('#shell').count(),1);
await p.locator('#next').click();await selected(p,'beta');await p.locator('select').selectOption('alpha');await p.getByRole('button',{name:'Filter'}).click();await selected(p,'alpha');
assert(requests.filter(r=>r.path.startsWith('/articles')).every(r=>!r.hx&&r.representation==='full'));return {directLinkAndGetForm:true,fullShell:true};
},false);
await scenario('N02-enhance-reload-direct',async(p,c)=>{
await p.goto(base+'/articles?topic=alpha');await enhanced(p);await next(p,'beta');assert(requests.some(r=>r.hx&&r.representation==='fragment'));
await p.reload();await selected(p,'beta');assert.equal(await p.locator('#shell').count(),1);
const fresh=await c.newPage();await fresh.goto(base+'/articles?topic=beta');assert.equal(await fresh.locator('#shell').count(),1);await fresh.close();return {pushReloadAndFreshEntry:true};
});
await scenario('N03-history-hit',async p=>{
await p.goto(base+'/articles?topic=alpha');await enhanced(p);await next(p,'beta');const before=requests.length;
await p.goBack();await selected(p,'alpha');await p.waitForFunction(()=>window.probe.some(e=>e.name==='htmx:historyRestore'));
await p.goForward();await selected(p,'beta');
assert(!requests.slice(before).some(r=>r.path.startsWith('/articles')));return {backForward:true,additionalArticleRequests:0};
});
await scenario('N04-history-miss',async p=>{
await p.goto(base+'/articles?topic=alpha');await enhanced(p);await next(p,'beta');await p.evaluate(()=>sessionStorage.removeItem('htmx-history-cache'));
await p.goBack();await selected(p,'alpha');assert(requests.some(r=>r.restore&&r.representation==='full'&&!r.hx));return {evictedSnapshotFetchedFull:true};
});
await scenario('N05-enhancement-failure',async p=>{
await p.goto(base+'/articles?topic=alpha');await enhanced(p);await p.locator('#broken').click();await p.waitForFunction(()=>window.probe.some(e=>e.name==='htmx:responseError'));await selected(p,'alpha');
assert(requests.some(r=>r.hx&&r.status===503));await p.locator('#recover').click();await selected(p,'beta');assert.equal(await p.locator('#shell').count(),1);return {oldViewAndUrlRetained:true,explicitNativeRecovery:true};
});
await scenario('N06-script-failure',async p=>{
await p.goto(base+'/articles?topic=alpha&scriptfail=1');assert(requests.some(r=>r.path==='/htmx.js?fail=1'&&r.status===503));assert.equal(await p.evaluate(()=>typeof window.htmx),'undefined');
await p.locator('#next').click();await selected(p,'beta');await p.locator('select').selectOption('alpha');await p.getByRole('button',{name:'Filter'}).click();await selected(p,'alpha');return {nativeLinkAndFormDespiteScript503:true};
});
async function cachedFetch(p,path,hx=false){return p.evaluate(async({path,hx})=>{const r=await fetch(path,{headers:hx?{'HX-Request':'true'}:{}});return {status:r.status,text:await r.text(),etag:r.headers.get('etag')};},{path,hx});}
await scenario('N07-fragment-before-document',async p=>{
await p.goto(base+'/articles?topic=alpha');const path='/cache-good?topic=beta';const frag=await cachedFetch(p,path,true);assert(!frag.text.includes('id="shell"'));
await p.goto(base+path);assert.equal(await p.locator('#shell').count(),1);await selected(p,'beta');return {fragmentThenFull:true};
});
await scenario('N08-document-before-fragment',async p=>{
const path='/cache-good?topic=alpha';await p.goto(base+path);const frag=await cachedFetch(p,path,true);assert(!frag.text.includes('id="shell"'));assert(frag.text.includes('<main'));
const full=await cachedFetch(p,path);assert(full.text.includes('id="shell"'));return {fullThenFragmentThenFull:true};
});
await scenario('N09-missing-vary-negative',async p=>{
await p.goto(base+'/articles?topic=alpha');const path='/cache-bad?topic=beta';await cachedFetch(p,path,true);const before=requests.length;await p.goto(base+path);
return {fragmentServedAsDocument:await p.locator('#shell').count()===0,additionalRequests:requests.slice(before),negativeControl:true};
});
await scenario('N10-conditional-representations',async()=>{
const path=base+'/cache-good?topic=beta';const fragment=await fetch(path,{headers:{'HX-Request':'true'}});const etag=fragment.headers.get('etag');await fragment.text();
const same=await fetch(path,{headers:{'HX-Request':'true','If-None-Match':etag}});assert.equal(same.status,304);
const full=await fetch(path,{headers:{'If-None-Match':etag}});assert.equal(full.status,200);assert((await full.text()).includes('id="shell"'));assert.notEqual(full.headers.get('etag'),etag);
const restore=await fetch(path,{headers:{'HX-Request':'true','HX-History-Restore-Request':'true'}});assert((await restore.text()).includes('id="shell"'));return {transport:'explicit Node HTTP requests; duplicated per browser group, not independent browser evidence',sameRepresentation:304,crossRepresentation:200,restoreFull:true};
});
}finally{await browser.close();}
}
}finally{await new Promise(resolve=>server.close(resolve));}
const files={};for(const f of ['experiment.mjs','package.json','package-lock.json','node_modules/htmx.org/dist/htmx.js'])files[f]=createHash('sha256').update(await readFile(new URL(f,dir))).digest('hex');
const receipt={date:new Date().toISOString(),node:process.version,kind:'authored-http-fixture-with-pinned-htmx',browsers,files,results,passed:results.filter(r=>r.status==='pass').length,total:results.length};
await writeFile(output,JSON.stringify(receipt,null,2)+'\n');console.log(JSON.stringify({output,passed:receipt.passed,total:receipt.total,failures:results.filter(r=>r.status==='fail')},null,2));if(receipt.passed!==receipt.total)process.exitCode=1;

View file

@ -0,0 +1,768 @@
{
"status": "incomplete",
"results": [
{
"id": "N01-no-script-native",
"engine": "chromium",
"status": "pass",
"observation": {
"directLinkAndGetForm": true,
"fullShell": true
},
"requests": [
{
"path": "/articles?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/favicon.ico",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 404,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=beta",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
}
],
"url": "http://127.0.0.1:39749/articles?topic=alpha",
"body": "Catalog shell\nalpha\n\nPublic article alpha\n\nOther topic\nTopic \nalpha\nbeta\nFilter\nInjected enhanced failureNative recovery",
"events": []
},
{
"id": "N02-enhance-reload-direct",
"engine": "chromium",
"status": "pass",
"observation": {
"pushReloadAndFreshEntry": true
},
"requests": [
{
"path": "/articles?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=beta",
"hx": true,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "fragment",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=beta",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=beta",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
}
],
"url": "http://127.0.0.1:39749/articles?topic=beta",
"body": "Catalog shell\nbeta\n\nPublic article beta\n\nOther topic\nTopic \nalpha\nbeta\nFilter\nInjected enhanced failureNative recovery",
"events": []
},
{
"id": "N03-history-hit",
"engine": "chromium",
"status": "pass",
"observation": {
"backForward": true,
"additionalArticleRequests": 0
},
"requests": [
{
"path": "/articles?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=beta",
"hx": true,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "fragment",
"vary": null,
"etag": null
}
],
"url": "http://127.0.0.1:39749/articles?topic=beta",
"body": "Catalog shell\nbeta\n\nPublic article beta\n\nOther topic\nTopic \nalpha\nbeta\nFilter\nInjected enhanced failureNative recovery",
"events": [
{
"name": "htmx:afterSettle",
"url": "http://127.0.0.1:39749/articles?topic=beta"
},
{
"name": "htmx:afterSettle",
"url": "http://127.0.0.1:39749/articles?topic=alpha"
},
{
"name": "htmx:historyRestore",
"url": "http://127.0.0.1:39749/articles?topic=alpha"
},
{
"name": "htmx:afterSettle",
"url": "http://127.0.0.1:39749/articles?topic=beta"
},
{
"name": "htmx:historyRestore",
"url": "http://127.0.0.1:39749/articles?topic=beta"
}
]
},
{
"id": "N04-history-miss",
"engine": "chromium",
"status": "pass",
"observation": {
"evictedSnapshotFetchedFull": true
},
"requests": [
{
"path": "/articles?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=beta",
"hx": true,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "fragment",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=alpha",
"hx": false,
"restore": true,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
}
],
"url": "http://127.0.0.1:39749/articles?topic=alpha",
"body": "Catalog shell\nalpha\n\nPublic article alpha\n\nOther topic\nTopic \nalpha\nbeta\nFilter\nInjected enhanced failureNative recovery",
"events": [
{
"name": "htmx:afterSettle",
"url": "http://127.0.0.1:39749/articles?topic=beta"
},
{
"name": "htmx:afterSettle",
"url": "http://127.0.0.1:39749/articles?topic=alpha"
},
{
"name": "htmx:historyRestore",
"url": "http://127.0.0.1:39749/articles?topic=alpha",
"cacheMiss": true
}
]
},
{
"id": "N05-enhancement-failure",
"engine": "chromium",
"status": "pass",
"observation": {
"oldViewAndUrlRetained": true,
"explicitNativeRecovery": true
},
"requests": [
{
"path": "/articles?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=beta&enhancedfail=1",
"hx": true,
"restore": false,
"ifNoneMatch": null,
"status": 503,
"representation": "fragment",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=beta&enhancedfail=1",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
}
],
"url": "http://127.0.0.1:39749/articles?topic=beta&enhancedfail=1",
"body": "Catalog shell\nbeta\n\nPublic article beta\n\nOther topic\nTopic \nalpha\nbeta\nFilter\nInjected enhanced failureNative recovery",
"events": []
},
{
"id": "N06-script-failure",
"engine": "chromium",
"status": "pass",
"observation": {
"nativeLinkAndFormDespiteScript503": true
},
"requests": [
{
"path": "/articles?topic=alpha&scriptfail=1",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js?fail=1",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 503,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=beta&scriptfail=1",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js?fail=1",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 503,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/articles?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
}
],
"url": "http://127.0.0.1:39749/articles?topic=alpha",
"body": "Catalog shell\nalpha\n\nPublic article alpha\n\nOther topic\nTopic \nalpha\nbeta\nFilter\nInjected enhanced failureNative recovery",
"events": []
},
{
"id": "N07-fragment-before-document",
"engine": "chromium",
"status": "pass",
"observation": {
"fragmentThenFull": true
},
"requests": [
{
"path": "/articles?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/cache-good?topic=beta",
"hx": true,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "fragment",
"vary": "HX-Request, HX-History-Restore-Request",
"etag": "\"d4a2e4af8c3671d399ddcbbc92984556a75f795817fba6404ea84e1805892663\""
},
{
"path": "/cache-good?topic=beta",
"hx": false,
"restore": false,
"ifNoneMatch": "\"d4a2e4af8c3671d399ddcbbc92984556a75f795817fba6404ea84e1805892663\"",
"status": 200,
"representation": "full",
"vary": "HX-Request, HX-History-Restore-Request",
"etag": "\"843d827eaa297ed04d5424a03a78a7049356060ac71f73bc7e1b85d3b5691c41\""
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
}
],
"url": "http://127.0.0.1:39749/cache-good?topic=beta",
"body": "Catalog shell\nbeta\n\nPublic article beta\n\nOther topic\nTopic \nalpha\nbeta\nFilter\nInjected enhanced failureNative recovery",
"events": []
},
{
"id": "N08-document-before-fragment",
"engine": "chromium",
"status": "pass",
"observation": {
"fullThenFragmentThenFull": true
},
"requests": [
{
"path": "/cache-good?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": "HX-Request, HX-History-Restore-Request",
"etag": "\"3a9bd4c1596afe87253606468ccd0909f3748af4a479926917695e13f45b15c3\""
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/cache-good?topic=alpha",
"hx": true,
"restore": false,
"ifNoneMatch": "\"3a9bd4c1596afe87253606468ccd0909f3748af4a479926917695e13f45b15c3\"",
"status": 200,
"representation": "fragment",
"vary": "HX-Request, HX-History-Restore-Request",
"etag": "\"af6404a0e852c5f75ab2abf25f61de82db30f85e21abeb19055a6b5caf854229\""
},
{
"path": "/cache-good?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": "\"af6404a0e852c5f75ab2abf25f61de82db30f85e21abeb19055a6b5caf854229\"",
"status": 200,
"representation": "full",
"vary": "HX-Request, HX-History-Restore-Request",
"etag": "\"3a9bd4c1596afe87253606468ccd0909f3748af4a479926917695e13f45b15c3\""
}
],
"url": "http://127.0.0.1:39749/cache-good?topic=alpha",
"body": "Catalog shell\nalpha\n\nPublic article alpha\n\nOther topic\nTopic \nalpha\nbeta\nFilter\nInjected enhanced failureNative recovery",
"events": []
},
{
"id": "N09-missing-vary-negative",
"engine": "chromium",
"status": "pass",
"observation": {
"fragmentServedAsDocument": true,
"additionalRequests": [],
"negativeControl": true
},
"requests": [
{
"path": "/articles?topic=alpha",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": null,
"etag": null
},
{
"path": "/observe.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/htmx.js",
"hx": false,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "asset",
"vary": null,
"etag": null
},
{
"path": "/cache-bad?topic=beta",
"hx": true,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "fragment",
"vary": null,
"etag": "\"69c19e9840aa688ca34f4768e33ab28e0b994aeb5191251db7c0ab9a36b2699b\""
}
],
"url": "http://127.0.0.1:39749/cache-bad?topic=beta",
"body": "beta\n\nPublic article beta\n\nOther topic\nTopic \nalpha\nbeta\nFilter\nInjected enhanced failureNative recovery",
"events": []
},
{
"id": "N10-conditional-representations",
"engine": "chromium",
"status": "pass",
"observation": {
"transport": "explicit Node HTTP requests; duplicated per browser group, not independent browser evidence",
"sameRepresentation": 304,
"crossRepresentation": 200,
"restoreFull": true
},
"requests": [
{
"path": "/cache-good?topic=beta",
"hx": true,
"restore": false,
"ifNoneMatch": null,
"status": 200,
"representation": "fragment",
"vary": "HX-Request, HX-History-Restore-Request",
"etag": "\"d4a2e4af8c3671d399ddcbbc92984556a75f795817fba6404ea84e1805892663\""
},
{
"path": "/cache-good?topic=beta",
"hx": true,
"restore": false,
"ifNoneMatch": "\"d4a2e4af8c3671d399ddcbbc92984556a75f795817fba6404ea84e1805892663\"",
"status": 304,
"representation": "fragment",
"vary": "HX-Request, HX-History-Restore-Request",
"etag": "\"d4a2e4af8c3671d399ddcbbc92984556a75f795817fba6404ea84e1805892663\""
},
{
"path": "/cache-good?topic=beta",
"hx": false,
"restore": false,
"ifNoneMatch": "\"d4a2e4af8c3671d399ddcbbc92984556a75f795817fba6404ea84e1805892663\"",
"status": 200,
"representation": "full",
"vary": "HX-Request, HX-History-Restore-Request",
"etag": "\"843d827eaa297ed04d5424a03a78a7049356060ac71f73bc7e1b85d3b5691c41\""
},
{
"path": "/cache-good?topic=beta",
"hx": true,
"restore": true,
"ifNoneMatch": null,
"status": 200,
"representation": "full",
"vary": "HX-Request, HX-History-Restore-Request",
"etag": "\"843d827eaa297ed04d5424a03a78a7049356060ac71f73bc7e1b85d3b5691c41\""
}
],
"url": "about:blank",
"body": "",
"events": []
}
]
}

View file

@ -0,0 +1,47 @@
{
"name": "fep-navigation-history",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "fep-navigation-history",
"dependencies": {
"htmx.org": "2.0.11",
"playwright": "1.63.0"
}
},
"node_modules/htmx.org": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-2.0.11.tgz",
"integrity": "sha512-Thx/WtpeOQqSrqBCw/A1cwGJGg4UrVa3+sW0GmrM3p4gJgO89ecH4qtbnyzDDWFvBTqjnIMCgELTNt636dtamA==",
"license": "0BSD"
},
"node_modules/playwright": {
"version": "1.63.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz",
"integrity": "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==",
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.63.0"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=20"
}
},
"node_modules/playwright-core": {
"version": "1.63.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.63.0.tgz",
"integrity": "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==",
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=20"
}
}
}
}

View file

@ -0,0 +1 @@
{"name":"fep-navigation-history","private":true,"type":"module","scripts":{"test":"node experiment.mjs"},"dependencies":{"htmx.org":"2.0.11","playwright":"1.63.0"}}

File diff suppressed because it is too large Load diff

View file

@ -25,3 +25,11 @@ Stream E follow-up: [feature/deployment contrast](FeatureDeploymentBoundaries.md
adds pinned example code and release workflow definitions; operational independence
remains unverified. VC-06 now has a provisional synthetic draft; VC-04/05 and VC-07–10
remain planned. One new developed seed brings the current corpus to seventeen hypotheses.
## Prospective navigation evidence — 2026-09-27
[First measured cycle](NavigationHistoryExperiment.md) adds pinned htmx runtime
corroboration to VC-03, URL-addressable State and Progressive Enhancement. Direct/
native/enhanced/history and representation-cache subset exercised in two browsers;
missing-Vary negative control reproduced. VC-03 stays provisional and offline/
accessibility work remains open. No maturity or M1/M2 promotion.

View file

@ -0,0 +1,75 @@
# First prospective navigation cycle — 2026-09-27
Author/reviewer: Codex, author-model; no independent human validation. Stream B,
LEARN-0011. [Registered protocol](../evolution/cycles/2026-09-27-navigation.md) committed
as `f3697c1` before implementation/execution. [Runner and reproduction](../experiments/navigation-history/README.md),
[complete receipt](../experiments/navigation-history/result.json),
[partial first run](../experiments/navigation-history/initial-partial.json).
## Evidence and observations
Real htmx 2.0.11 in an authored public-catalog server; Playwright 1.63.0, Chromium
151.0.7922.34 and Firefox 155.0. Dependencies locked, inputs and browser binaries
hashed in the complete receipt. Existing [htmx history/cache documentation](https://htmx.org/docs/)
was consulted for mechanism context (accessed local date 2026-09-27, living revision
unknown); execution is evidence only for the pinned package and declared server policy.
| Claim | Registered checks | Observation in both browsers |
| --- | --- | --- |
| NH01 | N01/N02 | Direct filtered entry, native link/GET form, enhanced navigation, reload and fresh direct entry preserve selection; document entries include the shell |
| NH02 | N03/N04 | Snapshot back/forward makes no additional article request; evicting the pinned sessionStorage history cache causes a history-restore request and full response |
| NH03 | N05/N06 | Enhanced 503 leaves the old committed URL/content; explicit native recovery works. A failed htmx script load leaves native link/form usable |
| NH04 | N07/N08 | Correct Vary selection returns full versus fragment content in both population orders; N08's final full fetch recontacts the server, not proof that both variants stay cached |
| NH05 | N09 | Without Vary, the browser reuses the cached fragment as a full document, loses the shell, and sends no additional request |
| NH06 | N10 | Explicit Node requests receive 304 for a matching representation validator and 200/full body for the other representation; a history-restore selector returns full content |
20/20 registered rows met expectations, including the intentionally broken N09.
There are 18 browser cases and the same explicit HTTP sequence repeated twice; do
not describe N10 as browser automatic revalidation. Snapshot hits restore selected
views, not a tested guarantee of current publisher bytes. HTTP cache and htmx history
storage are different mechanisms. Vary names both HX-Request and
HX-History-Restore-Request because both influence the fixture's representation.
The fixture's historyRestoreAsHxRequest=false is explicit, not a claim about defaults.
The first run completed ten Chromium rows, then failed to locate Firefox in its
default installation path. Its incomplete receipt is preserved. The second run used
the existing `/tmp/fep-playwright-browsers` installation and unrestricted temporary
profile access. No source/criteria changes between runs; repetition is not new learning.
No unexpected assertion failure was discarded. Initial launch error: executable absent
at `/home/worsch/.cache/ms-playwright/firefox-1543/firefox/firefox`.
## Learning disposition: corroboration
Before: documentary evidence and synthetic reasoning predicted native contracts,
history recovery and representation-aware caching were necessary for coherent routes.
After: one pinned library plus our server policy supplies bounded runtime support,
including a concrete fragment-as-document counterexample when cache selection is broken.
The existing obligations stand; no new pattern or consequential conceptual revision is
claimed. Updating evidence text is not automatically a new discovery. This is one
question/outcome, not twenty discoveries, and not independent deployed recurrence.
CAND-0009 and CAND-0010 remain draft/hypothesis. VC-03 remains provisional: its tested
read-only navigation subset is stronger, while keyboard/focus/announcements, delayed
script activation, interrupted transport, invalid/deleted routes, numerical delivery
budgets and offline availability remain open. Native recovery was explicitly offered
by the fixture; no automatic fallback or full accessibility claim follows. No real
CDN/intermediary, private cache policy or publisher-freshness guarantee was tested.
## Measurement and next decision
[Effort receipt](../evolution/cycles/2026-09-27-navigation-effort.json) records the
monotonic measured window and subtracted execution intervals. Active time includes
registration, fixture development, source inspection, analysis and recording. The
initial orientation is excluded; subprocess execution includes the failed launch and
full rerun. Administrative commit/snapshot/sync time after cutoff is unmeasured overhead.
This is single-agent elapsed effort, not human labor or model compute time. Token/cost
telemetry is unknown. Brief checkpoint inspection during execution is assigned wholly
to execution, never counted twice. Clock start UTC label was read during orientation;
monotonic start after orientation is the duration authority.
No diminishing-returns claim follows from one corroborating cycle. WP-0006 T03 keeps
comparison-window review and review-date reconciliation open. WP-0003 T01 next owns
bounded keyboard/focus/error-feedback checks if we continue this navigation stream;
use a new comparison group if the accessibility question/protocol is materially different.
WP-0003 T02 still owns the independent walkthrough review and offline branch. M1/M2,
independent human review and language usefulness remain unresolved.

View file

@ -98,3 +98,13 @@ representation-cache checks. Test interrupted enhancement separately from entire
absent scripts. Establish a measurable content-delivery budget before performance
claims. Keep offline cache research bounded; do not add another draft merely to
make the diagram complete. Independent decision-usefulness review remains open.
## Prospective runtime subset — 2026-09-27
[Navigation/history experiment](../reviews/NavigationHistoryExperiment.md) NH01–NH06
corroborates direct/native/enhanced navigation, snapshot hit/miss recovery and full/
fragment cache selection in an authored htmx fixture. Both browsers reproduce shell
loss under missing Vary. Validator checks use explicit Node requests. This strengthens
the read-only trace; the case remains provisional. Keyboard/focus/announcements, late
scripts, interrupted transport, invalid/deleted routes and the offline branch remain
open. No performance, independent-human or decision-usefulness gate is completed.

View file

@ -43,11 +43,12 @@ def test_rejects_misleading_or_untraceable_records(data, mutation, match):
def test_unknown_effort_and_retrospective_sample_cannot_create_a_trend(data):
data['ledger']['events'] = [e for e in data['ledger']['events'] if e['recording'] == 'retrospective']
for entry in data['ledger']['events']:
entry['effort']['research_minutes'] = None
report = evolution.render(data)
assert 'Learning rate and diminishing returns: **not measurable' in report
assert '0/10' in report
assert f"0/{len(data['ledger']['events'])}" in report
assert 'historical only' in report
assert 'no revised numeric count' in report
assert 'Consequential outcome/hour' not in report

View file

@ -8,7 +8,7 @@ status: active
owner: codex
topic_slug: canon
created: "2026-09-24"
updated: "2026-09-26"
updated: "2026-09-27"
state_hub_workstream_id: "13c123f1-a470-560e-ab8e-b270c387930a"
---
@ -185,3 +185,19 @@ real backend outcome or retention authorization claim. These remain T01 limits f
any production recommendation. Next breadth task: pending VC-03 navigation/history/
full-versus-fragment cache evidence. Seventeen hypotheses; T02/T03 and M1/M2 gates
unchanged. No model inference or production actions.
## First prospective cycle completed — 2026-09-27
LEARN-0011 preregistered at f3697c1; htmx 2.0.11 navigation/history/cache experiment
meets 20/20 registered checks (18 browser rows and repeated explicit HTTP checks).
Both browsers reproduce missing-Vary fragment-as-document failure. Outcome is
corroboration, not a new discovery. Active/execution effort recorded in
research/evolution/cycles/2026-09-27-navigation-effort.json; one cycle cannot show a trend.
Candidate profiles/report updated; hypothesis status and provisional VC-03 retained.
WP-0003 T01 retains keyboard/focus/error-feedback and delayed/interrupted enhancement
questions; T02 retains independent walkthrough review and offline-reading branch.
WP-0006 T03 remains progress for comparable-window review and remaining substantive
review-date reconciliation. Choose a new comparison group for materially different
questions. M1/M2 and independent-human validation remain open. See
research/reviews/NavigationHistoryExperiment.md.

View file

@ -8,7 +8,7 @@ status: active
owner: codex
topic_slug: canon
created: "2026-09-26"
updated: "2026-09-26"
updated: "2026-09-27"
state_hub_workstream_id: "528d24c1-c2c4-5914-a065-992b0dd877c8"
---
@ -49,7 +49,7 @@ experiment receipts. Intent/protocol/program now describe continuous learning.
```task
id: FEP-WP-0006-T03
status: todo
status: progress
priority: medium
state_hub_task_id: "2c5c4bae-a0a9-54bf-ac86-49b2803fdd8c"
```
@ -64,3 +64,19 @@ then and no automatic plateau declaration. Preserve independent confirmation val
Reconcile substantive-review dates from original artifacts; baseline assessment dates
must not fabricate freshness. Future usefulness work retains stable development anchors
and preregisters fresh tasks under WP-0004; it does not alter the consumed pilot.
## First prospective cycle completed — 2026-09-27
LEARN-0011 preregistered at f3697c1; htmx 2.0.11 navigation/history/cache experiment
meets 20/20 registered checks (18 browser rows and repeated explicit HTTP checks).
Both browsers reproduce missing-Vary fragment-as-document failure. Outcome is
corroboration, not a new discovery. Active/execution effort recorded in
research/evolution/cycles/2026-09-27-navigation-effort.json; one cycle cannot show a trend.
Candidate profiles/report updated; hypothesis status and provisional VC-03 retained.
WP-0003 T01 retains keyboard/focus/error-feedback and delayed/interrupted enhancement
questions; T02 retains independent walkthrough review and offline-reading branch.
WP-0006 T03 remains progress for comparable-window review and remaining substantive
review-date reconciliation. Choose a new comparison group for materially different
questions. M1/M2 and independent-human validation remain open. See
research/reviews/NavigationHistoryExperiment.md.