Skip to content

E2E evidence: file:// verification can pass while the shipped page is broken #332

Description

@Data-Wise

E2E evidence: file:// verification can pass while the shipped page is broken

What happened

e2e-before-pr.md requires a live exercise that can fail, with a quoted
transcript. I satisfied that rule and still nearly shipped a dead page.

Building a two-pane week browser for a Quarto course site, I verified the
interaction in Chrome against the rendered output:

file:///…/_site/materials.html
→ {"jsAttr":"on","activePanels":["week-1"],"visiblePanelCount":1,
   "railCurrent":"1Introduction to Regression","railTabbable":1}

Rail click, arrow keys, boundary, and cold deep-link all passed. Real
transcript, real failure modes, rule satisfied.

Then I served the same directory over HTTP:

http://localhost:8899/materials.html#week-12
→ {"dataJs":null,"activePanels":[],"visibleCount":16,"scrollY":5089}

Every panel visible, no active state, the entire control dead.

Cause: Quarto's own script rewrites in-page hrefs to absolute URLs at runtime
(adding data-original-href). A [href^="#week-"] selector matches under
file:// and matches nothing once served over HTTP — which is every real
visit. The fix was to select on a.hash, which survives the rewrite.

A second file://-only artifact in the same session: Quarto's external-link
JS marked every internal link as external and appended an icon, because the
file:// origin is null so every link reads as cross-origin. Over HTTP:
zero. I nearly "fixed" a bug that did not exist.

Why it matters for craft

e2e-before-pr.md is precise about the transcript and about the E2E being
able to fail, but says nothing about the environment the exercise runs in.
For a rendered-artifact change its table says:

| Rendered artifact (tutorial, export) | Render-gate: build it, grep the output for known content |

Grepping built output would not have caught this — the HTML was correct. Only
the runtime behavior differed, and only over a real origin.

Suggestion

Add an environment clause to the rendered-artifact / web-surface row: when the
artifact is a web page with any client-side behavior, the E2E must run over
http(s), not file://. One line, e.g.:

Serve the built output (python3 -m http.server) and exercise it there —
file:// has a null origin and different URL resolution, so scripts that
rewrite or compare URLs behave differently than they will in production.

Optionally note the inverse failure too: file://-only artifacts can
manufacture phantom bugs (the external-link icons above), so a finding seen
only under file:// should be re-checked over HTTP before it is acted on.

Scope

Docs-only change to ~/.claude/rules/e2e-before-pr.md (or craft's copy if it
is vendored). No code. Happy to send the PR if you want it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions