Files
rust_browser/_bmad-output/planning-artifacts/epics.md
Zachary D. Rowitsch 0863153acd Implement parent-child margin collapsing (CSS 2.1 §8.3.1)
Add parent-first-child top and parent-last-child bottom margin collapsing
using a two-level approach (Level A shifts child inside parent, Level B
adjusts grandparent for effective collapsed margin). Fix pre-existing bug
in shift_subtree_x that incorrectly skipped absolute/fixed children.
Extract shared MARGIN_EPSILON constant, add 9 unit tests and 4 golden
tests (209-212), promote 31 WPT tests to pass. Includes code review
fixes: pub(crate) visibility for is_root_element, known-limitation docs,
and inline-content shift test coverage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 18:41:50 -04:00

78 KiB

stepsCompleted, status, completedAt, inputDocuments, scopeExclusions
stepsCompleted status completedAt inputDocuments scopeExclusions
step-01-validate-prerequisites
step-02-design-epics
step-03-create-stories
step-04-final-validation
complete 2026-03-12
_bmad-output/planning-artifacts/prd.md
_bmad-output/planning-artifacts/architecture.md
P3 (Phase 3 / Daily Driver) requirements excluded: FR32, FR37, FR40, FR43, FR44, FR45, FR46

rust_browser - Epic Breakdown

Overview

This document provides the complete epic and story breakdown for rust_browser, decomposing the requirements from the PRD, UX Design if it exists, and Architecture requirements into implementable stories.

Requirements Inventory

Functional Requirements

FR1: The browser parses HTML documents and constructs a DOM tree from arbitrary web content. Acceptance: all WPT tree-construction tests pass. FR2: The browser parses CSS stylesheets (inline, embedded, and external) and computes styles for all DOM nodes. Acceptance: computed style output matches WPT expectations for supported properties. FR3: The browser performs layout computation for block, inline, flexbox, table, and positioned elements. Acceptance: golden test output matches expected layout trees for each layout mode. FR4: The browser generates a display list from the layout tree and rasterizes it to pixels. Acceptance: golden test pixel output matches expected display list dumps. FR5a: The browser selects the correct font based on CSS font-family, font-weight, and font-style declarations. Acceptance: golden tests with multiple font stacks render the expected glyphs. FR5b: The browser performs line breaking per UAX#14 and renders text with correct line-height, font-size, and baseline alignment. Acceptance: golden tests with multi-line text match expected output. FR6: The browser renders images in PNG, JPEG, GIF, WebP, and SVG formats as both inline content and CSS background-image. Acceptance: golden tests with each format produce correct visual output. FR7a: The browser renders CSS backgrounds (color, image, repeat, position, attachment) and borders (all border-style values including double, groove, ridge, inset, outset). Acceptance: WPT background/border tests pass. FR7b: The browser renders box-shadow, CSS gradients (linear-gradient, radial-gradient), and opacity. Acceptance: golden tests for each effect match expected output. FR8: [P2] The browser renders CSS generated content (::before, ::after) with content property values including strings, attr(), and counter(). Acceptance: WPT generated-content tests pass. FR9: The browser performs CSS selector matching with full specificity calculation and cascade resolution per CSS 2.1 sections 6 and 6.4. Acceptance: WPT cascade/specificity tests pass. FR10: [P2] The browser resolves CSS inheritance, initial values, and inherit/initial/unset keywords for all CSS 2.1 properties. Acceptance: WPT inheritance tests pass for each supported property. FR11: The browser parses and executes JavaScript programs. Acceptance: Test262 pass rate reaches 95%+ against the full tc39/test262 suite (50,000+ tests). FR12: The browser executes scripts from inline <script> elements and external script resources, including deferred and asynchronous loading. Acceptance: WPT script-loading tests pass for each loading mode. FR13: The browser exposes DOM manipulation APIs to JavaScript: getElementById, querySelector, querySelectorAll, createElement, appendChild, removeChild, insertBefore, replaceChild, classList, and style property access. Acceptance: WPT DOM manipulation tests pass for each listed API. FR14: The browser dispatches events to JavaScript listeners with capture, target, and bubble phases per the DOM Events specification. Acceptance: WPT event dispatch tests pass including stopPropagation and preventDefault. FR15: The browser executes microtasks (Promise.then), macrotasks (setTimeout, setInterval), and requestAnimationFrame callbacks in spec-defined order. Acceptance: event loop ordering tests produce correct execution sequences. FR16: The browser exposes these Web APIs to JavaScript: console (log/warn/error), JSON (parse/stringify), fetch, localStorage, sessionStorage, and all DOM/event APIs listed in FR13-FR14. Acceptance: each API has at least one integration test verifying correct behavior. FR17: The browser catches JavaScript runtime errors (TypeError, ReferenceError, SyntaxError) without crashing and reports them to console.error. Acceptance: a test script with each error type runs without process termination and produces console output. FR18: The user enters a URL in the address bar and the browser navigates to it. Acceptance: URL entry triggers resource fetch and page render within the performance bounds defined in NFR1. FR19: The browser loads resources over HTTP, HTTPS, file://, and data: URI schemes. Acceptance: integration tests verify successful resource loading for each scheme. FR20a: The browser follows HTTP 301, 302, 303, 307, and 308 redirects up to a maximum of 20 hops. Acceptance: redirect chain tests verify correct final destination and hop limit enforcement. FR20b: The browser displays HTTP error responses (4xx, 5xx) to the user with the status code and a descriptive message. Acceptance: error page tests verify status code display for 404 and 500 responses. FR21: [P1 -- done] The browser manages cookies per RFC 6265: domain scoping, path matching, Secure/HttpOnly flags, and Max-Age/Expires expiry. Acceptance: cookie integration tests verify correct set/send behavior for each attribute. FR22: [P1 -- done] The browser caches HTTP responses using ETag and Last-Modified headers, sends conditional requests (If-None-Match, If-Modified-Since), and honors Cache-Control directives (max-age, no-cache, no-store). Acceptance: caching integration tests verify 304 responses and cache hit/miss behavior. FR23: [P1 -- done] The browser maintains cookie-based session state across navigations within a browsing session: cookies set on page A are sent with requests to the same domain on page B. Acceptance: a multi-navigation test verifies session cookie persistence across 3+ page loads. FR24: The user navigates forward and backward through browsing history. Acceptance: history navigation tests verify correct page restoration for 3+ history entries. FR25: The browser resolves relative URLs against the document base URL (including if present). Acceptance: URL resolution tests cover relative paths, query strings, fragments, and base element override. FR26: The user interacts with form controls: text inputs, buttons, checkboxes, radio buttons, select menus, and textareas. Acceptance: integration tests verify user input produces correct form control state for each control type. FR27: The browser submits forms via GET and POST with application/x-www-form-urlencoded encoding. [P2] multipart/form-data encoding for file uploads. Acceptance: form submission tests verify correct request body encoding for each method and encoding type. FR28: [P2] The browser performs client-side form validation for required, pattern, min, max, minlength, maxlength, and type-based constraints (email, url, number). Acceptance: validation tests verify correct constraint enforcement and user-visible error indication for each constraint type. FR29: The user interacts with the page via click, keyboard input, and scroll. Acceptance: input event tests verify correct event dispatch and default behavior for each input type. FR30: The browser manages focus state and supports keyboard navigation (Tab/Shift+Tab) between focusable elements in document order. Acceptance: focus management tests verify correct tab order across form controls, links, and elements with tabindex. FR31: The user views and edits the current URL in an address bar that updates on navigation. Acceptance: address bar reflects the current page URL after each navigation. FR32: [P3] The user opens new tabs, switches between tabs, and closes tabs. Each tab maintains independent navigation history, DOM state, and scroll position. Acceptance: multi-tab tests verify independent state across 3+ tabs. FR33: The user scrolls page content vertically and horizontally when content exceeds the viewport. Acceptance: scroll tests verify content accessibility for pages taller and wider than the viewport. FR34: The browser displays a loading indicator during page load and clears it on completion or failure. Acceptance: loading state tests verify indicator visibility during fetch and removal after load/error events. FR35: The user reloads the current page (re-fetches all resources) and stops a loading navigation (cancels pending fetches). Acceptance: reload/stop tests verify correct behavior for each action. FR36: The browser renders a chrome UI containing the address bar, navigation buttons (back/forward/reload/stop), and a tab bar (Phase 3). Acceptance: chrome UI renders correctly at window widths from 800px to 2560px. FR37: [P3] The browser blocks tracker and advertisement requests by matching URLs against a bundled blocklist (e.g., EasyList format). Acceptance: blocking tests verify that requests matching 10+ known tracker patterns are prevented, and non-matching requests proceed normally. FR38: The browser enforces same-origin policy: JavaScript on origin A cannot read DOM content, cookies, or network responses from origin B (where A and B differ in scheme, host, or port). Acceptance: cross-origin access tests verify blocked read access for each resource type. FR39: The browser blocks top-level navigation to javascript: URIs and data: URIs. Sub-resource loading of data: URIs is permitted. Acceptance: navigation blocking tests verify blocked and permitted cases. FR40: [P3] The browser persists cookies and session data to disk and restores them on application restart. Acceptance: restart persistence tests verify cookie availability after process termination and relaunch. FR41: [P1 -- done] The browser serves previously cached HTTP responses when the origin server is unreachable, subject to Cache-Control freshness rules. Acceptance: offline tests verify cached page display when network requests fail. FR42: [P2] The browser provides localStorage (persistent, 5MB per origin) and sessionStorage (per-tab, cleared on tab close) to JavaScript. Acceptance: Web Storage tests verify getItem/setItem/removeItem/clear behavior, storage limits, and cross-origin isolation. FR43: [P3] The browser discovers and uses OS-installed fonts on macOS (Core Text) and Linux (fontconfig), falling back to bundled Noto Sans. Acceptance: font discovery tests verify at least 3 system fonts are available beyond the bundled set on each supported platform. FR44: [P3] The user copies selected text to the system clipboard and pastes text from the clipboard into form inputs. Acceptance: clipboard tests verify round-trip copy/paste of plain text content. FR45: [P3] The browser presents native file dialogs for file upload () and download (Content-Disposition: attachment). Acceptance: file dialog tests verify dialog presentation and correct file data transfer. FR46: [P3] The browser registers as the default URL handler on macOS and Linux so that clicking links in other applications opens rust_browser. Acceptance: URL handler registration tests verify correct launch from an external link on each platform. FR47: [P2] The browser passes 90%+ of CSS 2.1 Web Platform Tests as measured by the WPT harness in CI. FR48: [P2] The browser passes 95%+ of the full tc39/test262 ECMAScript conformance suite (50,000+ tests) as measured by the Test262 harness. FR49: [P2] The browser passes 90%+ of HTML5 Web Platform Tests as measured by the WPT harness in CI. FR50: The browser handles malformed HTML, CSS, and JavaScript input without crashing. Acceptance: fuzz tests and malformed-input test suites covering each parser run without panics.

NonFunctional Requirements

NFR1: Page load and first paint for a content-heavy site (CNN, Hacker News) completes within 3 seconds on an M1 MacBook or equivalent. Measured by timing from navigation start to first paint event in debug logs. NFR2: Scrolling maintains 30+ frames per second on pages with up to 500 DOM elements. Measured by frame timing instrumentation in the render loop. NFR3: No single JavaScript task blocks the rendering thread for more than 100ms. Measured by task duration logging in the event loop. NFR4: The browser starts up and displays the address bar ready for URL input within 2 seconds from process launch. Measured by startup timing instrumentation. NFR5: Resident memory usage does not grow by more than 50MB after navigating to 20 different pages and returning to the first. Measured by RSS sampling before and after the navigation sequence. NFR6: All parsers (HTML, CSS, JavaScript) handle malformed and adversarial input without panics or undefined behavior. Verified by fuzz test suites covering each parser with 10,000+ random inputs without crashes. NFR7: The unsafe keyword is forbidden in all crates except the two designated platform-integration crates. Verified by an automated CI check that scans source files and fails the build on violations. NFR8: JavaScript on origin A cannot read DOM content, cookies, or fetch responses from origin B (different scheme, host, or port). Verified by cross-origin integration tests covering each resource type. NFR9: Top-level navigation to javascript: and data: URIs is blocked; sub-resource data: URIs are permitted. Verified by navigation tests for each URI scheme. NFR10: The browser binary contains zero telemetry, analytics, or tracking code. Verified by code audit: no outbound network requests are made except those explicitly initiated by page content or user navigation. NFR11: The browser does not crash on any valid or malformed web content. Parser, layout, and render failures produce user-visible error messages instead of panics. Verified by running the full WPT and Test262 suites plus malformed-input tests without process termination. NFR12: The CI gate passes on every merged change, covering formatting, linting, all test suites, safety policy, and metrics. Verified by CI pass/fail status on every merge. NFR13: Every bug fix includes at least one regression test that reproduces the bug and verifies the fix. Verified by code review policy. NFR14: Conformance test suites (golden tests, WPT, Test262) run on every CI build. Any test that previously passed and now fails blocks the merge. Verified by CI harness exit codes. NFR15: The browser displays a user-visible error page (not a blank screen or hang) within 10 seconds of a network failure (timeout, DNS error, connection refused). Verified by network failure integration tests with simulated failures. NFR16: No crate in a lower architectural layer depends on a crate in a higher layer. Verified by an automated dependency check in CI that parses Cargo.toml files and fails on violations. NFR17: Each crate has a single documented responsibility. No crate's public API surface exceeds 50 exported items. Verified by periodic API surface audit. NFR18: No source file exceeds 1,000 lines. Verified by an automated file-size check in CI. NFR19: New external dependencies require documented rationale and workspace-level version pinning. Verified by code review policy. NFR20: Implementation of non-obvious spec behavior includes a comment citing the relevant spec section (e.g., CSS 2.1 section 8.3.1). Verified by code review policy. NFR21: The total crate count does not exceed 30 and total source file count does not exceed 500. Verified by periodic metrics collection in CI.

Additional Requirements

From Architecture document:

  • Brownfield project -- no starter template needed; all new work extends existing 22-crate, 4-layer architecture
  • Cookie jar module in net with domain scoping and swappable backing store interface for later storage-backed persistence
  • HTTP cache -- in-memory first, disk persistence later via storage crate
  • Storage crate serves as general-purpose persistence layer for all disk-persisted data (cookies, cache, localStorage, sessionStorage)
  • CSS property implementation order enforced: parse (css/) → computed style (style/) → layout effect (layout/) → paint effect (display_list/) → golden test → checklist update → CI
  • HTML element implementation order enforced: parse (html/) → DOM (dom/) → UA styling (style/) → layout (layout/) → paint (display_list/) → runtime behavior (web_api/) → golden test → checklist update → CI
  • JS feature implementation order enforced: tokenization (js_parser/) → AST (js_parser/) → execution (js_vm/) → unit tests → Test262 manifest → feature matrix update → CI
  • Bytecode IR introduction deferred until generators/async-await become priority -- AST walker sufficient for current spec compliance work
  • Compositor thread as first concurrency step -- consuming immutable display lists for async rasterization
  • JS yield mechanism via cooperative yielding with statement counter (existing max_statements in VmConfig)
  • Web API crate scaling -- module-per-domain initially, extract to web_api_<domain> crates when complexity warrants (~10-15 files)
  • System font discovery through platform/ OS-specific trait, fonts crate provides FontProvider facade
  • Clipboard & file dialogs wrapped in platform/ behind traits, consumed by app_browser
  • Single-process model now; multi-process architecture designed when tabs are implemented
  • Tab state isolation -- fully isolated per tab (own DOM, JS engine, styles, layout); cookie jar shared semantically
  • Error handling -- thiserror-derived specific error types in parsers, SharedResult in engine crates, domain conversions at bridge boundaries
  • Spec citations required for non-obvious behavior (CSS 2.1 §X.Y.Z, HTML §X.Y.Z, ECMAScript §X.Y.Z)
  • Dependency addition protocol -- check std first, pin in workspace, document rationale, pass deny.toml

FR Coverage Map

FR1: Epic 2 - HTML parsing and DOM tree construction FR2: Epic 1 - CSS parsing and style computation FR3: Epic 1 - Layout computation (block, inline, flex, table, positioned) FR4: Epic 1 - Display list generation and rasterization FR5a: Epic 1 - Font selection (font-family, font-weight, font-style) FR5b: Epic 1 - Line breaking and text rendering FR6: Epic 2 - Image rendering (PNG, JPEG, GIF, WebP, SVG) FR7a: Epic 1 - CSS backgrounds and borders FR7b: Epic 1 - Box-shadow, gradients, opacity FR8: Epic 1 - CSS generated content (::before, ::after) FR9: Epic 1 - Selector matching and cascade resolution FR10: Epic 1 - CSS inheritance and initial/inherit/unset keywords FR11: Epic 3 - JavaScript parsing and execution FR12: Epic 2 - Script loading (inline, external, async, defer) FR13: Epic 2 (DOM infrastructure) + Epic 3 (JS bindings) - DOM manipulation APIs FR14: Epic 3 - Event dispatch (capture, target, bubble phases) FR15: Epic 3 - Microtasks, macrotasks, requestAnimationFrame FR16: Epic 3 - Web API exposure (console, JSON, fetch, storage APIs) FR17: Epic 3 - JavaScript error handling without crashing FR18: Epic 5 - URL navigation FR19: Epic 5 - Resource loading (HTTP, HTTPS, file://, data:) FR20a: Epic 5 - HTTP redirect following FR20b: Epic 5 - HTTP error response display FR21: Epic 5 - Cookie management (P1 -- done, maintained) FR22: Epic 5 - HTTP caching (P1 -- done, maintained) FR23: Epic 5 - Session state persistence (P1 -- done, maintained) FR24: Epic 5 - Forward/backward history navigation FR25: Epic 2 - Base URL resolution () FR26: Epic 4 - Form control interaction FR27: Epic 4 - Form submission (GET/POST, multipart/form-data) FR28: Epic 4 - Client-side form validation FR29: Epic 4 - Click, keyboard, scroll interaction FR30: Epic 4 - Focus management and keyboard navigation FR31: Epic 5 - Address bar display and editing FR33: Epic 5 - Vertical and horizontal scrolling FR34: Epic 5 - Loading indicator FR35: Epic 5 - Reload and stop navigation FR36: Epic 5 - Chrome UI rendering FR38: Epic 6 - Same-origin policy enforcement FR39: Epic 6 - javascript:/data: URI navigation blocking FR41: Epic 5 - Offline cached response serving (P1 -- done, maintained) FR42: Epic 6 - localStorage and sessionStorage FR47: Epic 1 - CSS 2.1 WPT 90%+ pass rate FR48: Epic 3 - Test262 95%+ pass rate FR49: Epic 2 - HTML5 WPT 90%+ pass rate FR50: Epic 6 - Malformed input handling without crashes

Epic List

Epic 1: Visual Fidelity -- CSS 2.1 Complete

Web pages render with full CSS 2.1 visual fidelity. Margin collapsing, stacking contexts, positioning, generated content, tables, backgrounds, borders, text, and overflow all work correctly. Sites like CNN and Hacker News look right. FRs covered: FR2, FR3, FR4, FR5a, FR5b, FR7a, FR7b, FR8, FR9, FR10, FR47

Epic 1: Visual Fidelity -- CSS 2.1 Complete

Web pages render with full CSS 2.1 visual fidelity. Margin collapsing, stacking contexts, positioning, generated content, tables, backgrounds, borders, text, and overflow all work correctly. Sites like CNN and Hacker News look right.

FRs covered: FR2, FR3, FR4, FR5a, FR5b, FR7a, FR7b, FR8, FR9, FR10 Exit criterion: FR47 -- CSS 2.1 WPT 90%+ pass rate

Story 1.1: Margin Collapsing Completeness

As a web user, I want pages to render with correct vertical spacing between elements, So that text, headings, and content blocks have proper visual separation matching other browsers.

Acceptance Criteria:

Given two adjacent block-level siblings with bottom and top margins When the page is rendered Then the margins collapse to the larger of the two values per CSS 2.1 §8.3.1

Given a parent element with no border, padding, or clearance and a first/last child with margin When the page is rendered Then the child's margin collapses through the parent per CSS 2.1 §8.3.1

Given an empty block with top and bottom margins and no border, padding, or height When the page is rendered Then the top and bottom margins collapse into a single margin

Given an element with clearance set When the page is rendered Then margin collapsing is prevented at the clearance boundary

And golden tests cover each collapsing case, docs/CSS2.1_Implementation_Checklist.md is updated, and just ci passes.

Story 1.2: Stacking Contexts & Z-Index

As a web user, I want overlapping elements to render in the correct front-to-back order, So that menus, modals, and layered content display correctly.

Acceptance Criteria:

Given an element with position: relative/absolute/fixed and a z-index value other than auto When the page is rendered Then a new stacking context is created per CSS 2.1 §9.9.1

Given elements within the same stacking context When the page is rendered Then painting order follows CSS 2.1 §E.2: backgrounds/borders → negative z-index → block flow → floats → inline flow → z-index 0/auto → positive z-index

Given nested stacking contexts When the page is rendered Then child stacking contexts are painted atomically within their parent's z-order position

And golden tests cover overlapping positioned elements with various z-index values, checklist is updated, and just ci passes.

Story 1.3: Positioning Completeness

As a web user, I want fixed-position headers, tooltips, and absolutely positioned elements to appear in the correct location, So that page layouts with positioned elements render correctly.

Acceptance Criteria:

Given an element with position: fixed When the page is scrolled Then the element remains fixed relative to the viewport

Given a positioned element with top, right, bottom, left set to auto When the page is rendered Then auto values resolve per CSS 2.1 §10.6.4 and §10.3.7 based on the element's static position

Given a positioned element with clip: rect(...) When the page is rendered Then the element's visible area is clipped to the specified rectangle per CSS 2.1 §11.1.2

Given an absolutely positioned element within a relatively positioned container When the page is rendered Then the element is positioned relative to its containing block's padding edge

And golden tests cover fixed positioning, auto resolution, and clip, checklist is updated, and just ci passes.

Story 1.4: Generated Content

As a web user, I want CSS-generated content (bullets, quotes, labels) to render correctly, So that pages using ::before and ::after pseudo-elements display as intended.

Acceptance Criteria:

Given a CSS rule with ::before or ::after and a content property with a string value When the page is rendered Then the string content is inserted as an inline box before/after the element's content per CSS 2.1 §12.1

Given a content value using attr() When the page is rendered Then the attribute value from the HTML element is inserted as generated content

Given a content value using counter() with counter-reset and counter-increment When the page is rendered Then the counter value is computed and displayed per CSS 2.1 §12.4

Given generated content with styling (color, font-size, display) When the page is rendered Then the pseudo-element is styled independently from its originating element

And golden tests cover string content, attr(), counter(), checklist is updated, and just ci passes.

Story 1.5: Table Layout Completeness

As a web user, I want HTML tables to render with correct cell sizing, borders, and captions, So that tabular data displays correctly on real websites.

Acceptance Criteria:

Given a table with border-collapse: collapse When the page is rendered Then adjacent cell borders are merged using the conflict resolution rules per CSS 2.1 §17.6.2

Given a table with border-collapse: separate and border-spacing When the page is rendered Then cells are separated by the specified spacing

Given a table with caption-side: top or caption-side: bottom When the page is rendered Then the caption is placed above or below the table box respectively

Given a table with empty-cells: hide and cells containing no content When the page is rendered Then borders and backgrounds of empty cells are not drawn

Given a table with cells spanning rows/columns and percentage/fixed widths When the page is rendered Then the table layout algorithm distributes space correctly per CSS 2.1 §17.5

And golden tests cover each table feature, checklist is updated, and just ci passes.

Story 1.6: Lists & Counters

As a web user, I want ordered and unordered lists to render with correct markers and numbering, So that list content displays properly on real websites.

Acceptance Criteria:

Given a list element with list-style-position: inside or outside When the page is rendered Then the marker is positioned inside or outside the list item's content area per CSS 2.1 §12.5.1

Given a list with list-style-image pointing to a valid URL When the page is rendered Then the specified image is used as the list marker

Given elements with counter-reset and counter-increment properties When the page is rendered Then counters are created, incremented, and scoped correctly per CSS 2.1 §12.4

Given nested lists with automatic counter numbering When the page is rendered Then each nesting level maintains its own counter scope

And golden tests cover list marker positioning, custom images, and nested counters, checklist is updated, and just ci passes.

Story 1.7: Backgrounds

As a web user, I want page and element backgrounds to render correctly with images, patterns, and positioning, So that visually rich websites display as intended.

Acceptance Criteria:

Given an element with the full background shorthand property When the page is rendered Then all background sub-properties (color, image, repeat, attachment, position) are parsed and applied correctly per CSS 2.1 §14.2.1

Given an element with background-image: url(...) and background-repeat When the page is rendered Then the image is tiled according to the repeat value (repeat, repeat-x, repeat-y, no-repeat)

Given an element with background-attachment: fixed When the page is scrolled Then the background image remains fixed relative to the viewport

Given an element with background-position using keyword, percentage, or length values When the page is rendered Then the background image is positioned correctly within the element's padding box

And golden tests cover each background property combination, checklist is updated, and just ci passes.

Story 1.8: Borders & Outline

As a web user, I want all CSS border styles and outlines to render correctly, So that element borders display with the correct visual appearance.

Acceptance Criteria:

Given an element with border-style set to double When the page is rendered Then two parallel lines with a gap between them are drawn per CSS 2.1 §8.5.3

Given an element with border-style set to groove, ridge, inset, or outset When the page is rendered Then the 3D border effect is rendered with appropriate light/dark color variations

Given an element with outline properties (outline-style, outline-width, outline-color) When the page is rendered Then the outline is drawn outside the border edge without affecting layout per CSS 2.1 §18.4

Given an element with outline-offset When the page is rendered Then the outline is offset from the border edge by the specified amount

And golden tests cover each border style and outline, checklist is updated, and just ci passes.

Story 1.9: Text Properties

As a web user, I want text to render with correct indentation, decoration, spacing, and directionality, So that text-heavy pages display properly across languages and styles.

Acceptance Criteria:

Given an element with text-indent When the page is rendered Then the first line of the block is indented by the specified amount per CSS 2.1 §16.1

Given an element with text-decoration: underline | overline | line-through (including inherited/accumulated values) When the page is rendered Then the decorations are drawn correctly and propagate to inline descendants per CSS 2.1 §16.3

Given an element with word-spacing or letter-spacing When the page is rendered Then additional spacing is applied between words or characters respectively

Given an element with direction: rtl and unicode-bidi When the page is rendered Then text is laid out right-to-left with correct bidi reordering per CSS 2.1 §9.10

And golden tests cover each text property, checklist is updated, and just ci passes.

Story 1.10: Font Properties

As a web user, I want font styles to render correctly including shorthand declarations and variant styles, So that typography on web pages matches the designer's intent.

Acceptance Criteria:

Given an element with the font shorthand property When the page is rendered Then all font sub-properties (style, variant, weight, size, line-height, family) are parsed and applied correctly per CSS 2.1 §15.8

Given an element with font-variant: small-caps When the page is rendered Then lowercase characters are rendered as small capital letters

Given a CSS value using ex units When the page is rendered Then the unit resolves to the x-height of the element's font per CSS 2.1 §4.3.2

Given font metrics from the bundled font set When computing line-height and baseline alignment Then the correct ascent, descent, and x-height values are used for layout calculations

And golden tests cover font shorthand, small-caps, and ex units, checklist is updated, and just ci passes.

Story 1.11: Overflow

As a web user, I want content that exceeds its container to be clipped or scrollable as specified, So that pages with constrained containers display correctly.

Acceptance Criteria:

Given an element with overflow: hidden and content exceeding its bounds When the page is rendered Then overflowing content is clipped at the element's padding edge

Given an element with overflow: scroll When the page is rendered Then a scrolling mechanism is provided regardless of whether content overflows

Given an element with overflow: auto and content exceeding its bounds When the page is rendered Then a scrolling mechanism is provided only when content overflows

Given an element with overflow clipping and positioned children When the page is rendered Then clipping is applied correctly to the element's content and descendants per CSS 2.1 §11.1.1

And golden tests cover each overflow value, checklist is updated, and just ci passes.

Story 1.12: Media Rules

As a web user, I want stylesheets imported via @import and conditional @media rules to apply correctly, So that pages load external stylesheets and respond to media types.

Acceptance Criteria:

Given a stylesheet with @import url("other.css") When the page is rendered Then the imported stylesheet's rules are fetched and applied with correct cascade order per CSS 2.1 §6.3

Given a stylesheet with @import url("print.css") print When rendering for screen media type Then the imported stylesheet is not applied

Given a @media screen { ... } block When rendering for screen media type Then the rules inside the block are applied

Given a @media print { ... } block When rendering for screen media type Then the rules inside the block are not applied

And golden tests cover @import and @media rules, checklist is updated, and just ci passes.

Story 1.13: CSS Inheritance Completeness

As a web user, I want CSS property values to correctly inherit, reset, and cascade, So that styling behaves predictably across nested elements.

Acceptance Criteria:

Given an element with a property set to inherit When the page is rendered Then the element uses its parent's computed value for that property per CSS 2.1 §6.2.1

Given an element with a property set to initial When the page is rendered Then the element uses the property's initial value per its specification

Given an element with a property set to unset When the page is rendered Then the property behaves as inherit if it's an inherited property, or initial if it's not

Given all CSS 2.1 properties When checking inheritance behavior Then each property correctly defaults to inherited or non-inherited per its CSS 2.1 specification

And golden tests cover inherit/initial/unset for both inherited and non-inherited properties, checklist is updated, and just ci passes.


Epic 2: Document Completeness -- HTML5 Full Support

All HTML5 elements and document features work correctly. Full tokenizer state machine, tree builder insertion modes, DOM core APIs (DocumentFragment, insertBefore, replaceChild, live collections, querySelector/querySelectorAll), document lifecycle events, script loading modes, and base URL resolution.

FRs covered: FR1, FR6, FR12, FR13 (DOM infrastructure), FR25 Exit criterion: FR49 -- HTML5 WPT 90%+ pass rate

Story 2.1: HTML5 Tokenizer Completeness

As a web user, I want all HTML content to be parsed correctly regardless of markup patterns, So that pages render properly even with unusual or complex HTML.

Acceptance Criteria:

Given HTML content using all tokenizer states (data, RCDATA, RAWTEXT, script data, PLAINTEXT, etc.) When the HTML is parsed Then each state transition produces the correct tokens per WHATWG HTML §13.2.5

Given HTML with character references (named, numeric, hexadecimal) in various contexts When the HTML is parsed Then character references are resolved correctly per their context (attribute vs. content)

Given HTML with CDATA sections, processing instructions, and bogus comments When the HTML is parsed Then each construct is tokenized according to the spec without errors

Given malformed HTML with unclosed tags, missing quotes, and invalid characters When the HTML is parsed Then the tokenizer recovers gracefully without panics per the spec's error handling rules

And golden tests cover edge-case tokenizer states, docs/HTML5_Implementation_Checklist.md is updated, and just ci passes.

Story 2.2: Tree Builder Insertion Modes

As a web user, I want the browser to construct the correct DOM tree from any HTML document, So that page structure matches what other browsers produce.

Acceptance Criteria:

Given HTML content triggering each tree builder insertion mode (initial, before html, before head, in head, in body, in table, in select, after body, etc.) When the HTML is parsed Then elements are inserted into the correct location in the DOM tree per WHATWG HTML §13.2.6

Given HTML with implicit element creation (e.g., <td> without <table>, text before <html>) When the HTML is parsed Then missing elements are created automatically per the spec's implied open/close rules

Given HTML with misnested block/inline elements (e.g., <p><div></div></p>) When the HTML is parsed Then the tree builder splits and restructures elements per the spec

Given HTML with elements that change insertion mode (tables, select, template, etc.) When the HTML is parsed Then the correct insertion mode is activated and deactivated at the right boundaries

And WPT tree-construction tests pass for all covered insertion modes, checklist is updated, and just ci passes.

Story 2.3: Adoption Agency & Foster Parenting

As a web user, I want misnested formatting tags and misplaced table content to render correctly, So that real-world pages with imperfect HTML display as expected.

Acceptance Criteria:

Given HTML with misnested formatting elements (e.g., <b>text<i>more</b>rest</i>) When the HTML is parsed Then the adoption agency algorithm restructures the DOM tree so formatting is correctly applied per WHATWG HTML §13.2.6.4.7

Given the adoption agency algorithm running on deeply nested formatting (8+ levels) When the HTML is parsed Then the algorithm respects the iteration and nesting limits defined in the spec

Given HTML with non-table content directly inside <table>, <tbody>, <tr> elements When the HTML is parsed Then the content is foster-parented to the correct location before the table per WHATWG HTML §13.2.6.1

Given a combination of foster parenting and adoption agency in the same document When the HTML is parsed Then both algorithms interact correctly producing the spec-defined DOM tree

And WPT tree-construction tests covering adoption agency and foster parenting pass, checklist is updated, and just ci passes.

Story 2.4: DOM Tree Mutation APIs

As a web developer using JavaScript, I want to create, insert, replace, and move DOM nodes programmatically, So that dynamic web pages can modify their structure at runtime.

Acceptance Criteria:

Given JavaScript calling document.createDocumentFragment() When nodes are appended to the fragment and the fragment is inserted into the DOM Then all child nodes transfer to the insertion point and the fragment becomes empty per DOM §4.5

Given JavaScript calling parentNode.insertBefore(newNode, referenceNode) When the operation completes Then the new node is inserted before the reference node, or appended if reference is null

Given JavaScript calling parentNode.replaceChild(newChild, oldChild) When the operation completes Then the old child is removed and the new child takes its place in the DOM tree

Given a node being inserted that already exists elsewhere in the DOM When the insertion API is called Then the node is moved (removed from its current parent and inserted at the new location)

And integration tests verify each mutation API, docs/DOM_Implementation_Checklist.md is updated, and just ci passes.

Story 2.5: DOM Query APIs & Live Collections

As a web developer using JavaScript, I want to query the DOM by CSS selectors and access live element collections, So that scripts can efficiently find and track elements in the document.

Acceptance Criteria:

Given JavaScript calling document.querySelector(selector) with a valid CSS selector When the query executes Then the first matching element is returned, or null if no match exists

Given JavaScript calling document.querySelectorAll(selector) When the query executes Then a static NodeList of all matching elements is returned in document order

Given JavaScript calling document.getElementsByTagName(name) or document.getElementsByClassName(name) When the DOM is subsequently modified (elements added/removed) Then the returned HTMLCollection reflects the changes automatically (live collection)

Given complex CSS selectors (combinators, pseudo-classes like :first-child, :nth-child, attribute selectors) When used with querySelector/querySelectorAll Then the selectors match correctly using the existing selector matching engine

And integration tests verify query APIs and live collection behavior, DOM checklist is updated, and just ci passes.

Story 2.6: Script Loading -- async/defer

As a web user, I want pages to load faster by running scripts asynchronously or after parsing, So that script-heavy pages don't block rendering unnecessarily.

Acceptance Criteria:

Given a <script defer src="..."> element When the HTML is parsed Then the script is fetched in parallel with parsing and executed after the document is fully parsed, in document order per WHATWG HTML §4.12.1

Given a <script async src="..."> element When the HTML is parsed Then the script is fetched in parallel and executed as soon as it's available, regardless of document order

Given multiple <script defer> elements in a document When all scripts have loaded and the document is parsed Then they execute in the order they appear in the document

Given a <script> with both async and defer attributes When the HTML is parsed Then the async attribute takes precedence per the spec

And integration tests verify each loading mode's execution timing and ordering, checklist is updated, and just ci passes.

Story 2.7: Document Lifecycle

As a web developer using JavaScript, I want document lifecycle events to fire at the correct times, So that scripts can initialize at the right point in page loading.

Acceptance Criteria:

Given a page with a DOMContentLoaded event listener When the HTML has been fully parsed (but stylesheets/images may still be loading) Then the DOMContentLoaded event fires on the document

Given a page with a load event listener on the window When all resources (images, stylesheets, scripts) have finished loading Then the load event fires

Given JavaScript reading document.readyState When the document is in different loading phases Then it returns "loading" during parsing, "interactive" after parsing (before load), and "complete" after all resources load

Given a readystatechange event listener When document.readyState changes Then the event fires for each transition

And integration tests verify event timing and readyState transitions, checklist is updated, and just ci passes.

Story 2.8: iframe Support

As a web user, I want embedded content in iframes to load and render, So that pages using iframes for embedded documents display correctly.

Acceptance Criteria:

Given an <iframe src="..."> element in a page When the page is rendered Then the iframe's source document is fetched, parsed, and rendered within the iframe's content area

Given an iframe with width and height attributes or CSS sizing When the page is rendered Then the iframe's content area matches the specified dimensions

Given an iframe document with its own stylesheets and scripts When the iframe is rendered Then styles and scripts are scoped to the iframe's document and do not affect the parent

Given an iframe with srcdoc attribute When the page is rendered Then the inline HTML content is parsed and rendered as the iframe's document

And golden tests cover iframe rendering, checklist is updated, and just ci passes.

Story 2.9: Base URL Resolution & Image Rendering Completeness

As a web user, I want all relative URLs to resolve correctly and all image formats to render, So that pages with relative links and various image types display properly.

Acceptance Criteria:

Given a document with <base href="https://example.com/path/"> When relative URLs are resolved (in links, images, scripts, stylesheets) Then the base URL is used instead of the document's URL per WHATWG HTML §4.2.3

Given multiple <base> elements in a document When URLs are resolved Then only the first <base> with an href attribute is used

Given images in PNG, JPEG, GIF, WebP, and SVG formats referenced as <img> or CSS background-image When the page is rendered Then each format decodes and renders correctly at the specified dimensions

Given an <img> with width/height attributes and/or CSS sizing When the image is rendered Then the image scales to the specified dimensions while the intrinsic aspect ratio is used for auto dimensions

And golden tests cover base URL resolution and each image format, checklists are updated, and just ci passes.


Epic 3: Interactive Web -- JavaScript Engine Maturity

JS-heavy websites function. Generators, async/await, ES modules, complete built-in coverage, and 95%+ Test262 conformance. DOM manipulation via JS bindings, full event dispatch, microtask/macrotask scheduling, Web API exposure, and robust error handling.

FRs covered: FR11, FR13 (JS bindings), FR14, FR15, FR16, FR17 Exit criterion: FR48 -- Test262 95%+ pass rate

Story 3.1: Bytecode IR Introduction

As a browser developer, I want the JavaScript engine to execute via a bytecode interpreter instead of an AST walker, So that suspension semantics (generators, async/await) can be cleanly implemented and execution performance improves.

Acceptance Criteria:

Given the existing JavaScript test suite (vendored Test262 + unit tests) When execution is switched from AST walker to bytecode interpreter Then all previously passing tests continue to pass with identical results

Given a JavaScript program When it is executed Then the js_parser produces an AST, a bytecode compiler emits bytecode instructions, and the bytecode interpreter executes them

Given the bytecode instruction set When reviewed against the ECMAScript spec Then it supports all currently implemented language features (variables, functions, closures, control flow, try/catch, classes, etc.)

Given the bytecode interpreter's execution model When a suspension point is needed (for future generators/async-await) Then the interpreter's frame/stack design supports saving and restoring execution state

And docs/js_feature_matrix.md is updated to note the bytecode transition, and just ci passes.

Story 3.2: Generators & Iterator Protocol

As a web developer using JavaScript, I want generator functions and the iterator protocol to work, So that lazy sequences, custom iterables, and for...of loops function correctly.

Acceptance Criteria:

Given a generator function declared with function* When called Then it returns a generator object without executing the body

Given a generator object When next() is called Then execution resumes from the last yield point and returns {value, done} per ECMAScript §27.5

Given a generator with yield* delegating to another iterable When iterated Then values from the inner iterable are yielded one at a time

Given an object implementing the iterator protocol (Symbol.iterator, next()) When used with for...of, spread syntax, or destructuring Then the iteration protocol is followed correctly

Given a generator with return() or throw() called on it When the method is invoked Then the generator completes or throws at the current suspension point

And Test262 generator/iterator tests are promoted in the manifest, feature matrix is updated, and just ci passes.

Story 3.3: async/await

As a web developer using JavaScript, I want async functions and await expressions to work, So that asynchronous code can be written in a readable, sequential style.

Acceptance Criteria:

Given a function declared with async function When called Then it returns a Promise that resolves with the function's return value

Given an await expression inside an async function When the awaited value is a Promise Then execution suspends until the Promise settles, then resumes with the resolved value or throws the rejection

Given an await expression with a non-Promise value When executed Then the value is wrapped in a resolved Promise and execution continues

Given a try/catch block inside an async function with an awaited rejected Promise When the Promise rejects Then the rejection is caught by the catch block

Given multiple async functions with interleaved awaits When executed Then microtask scheduling follows the correct order per ECMAScript §27.7

And Test262 async/await tests are promoted in the manifest, feature matrix is updated, and just ci passes.

Story 3.4: ES Modules

As a web developer using JavaScript, I want import/export statements and <script type="module"> to work, So that modular JavaScript code loads and executes correctly.

Acceptance Criteria:

Given a <script type="module" src="..."> element When the page is loaded Then the module is fetched, parsed, and executed in strict mode with deferred timing per WHATWG HTML §4.12.1

Given a module with import { foo } from './other.js' When the module is executed Then the binding is resolved from the target module's exports per ECMAScript §16.2

Given a module with export default and named export declarations When imported by another module Then the exported bindings are available to the importing module

Given circular module dependencies (A imports B, B imports A) When the modules are loaded Then the module registry handles the cycle without deadlock, with uninitialized bindings where appropriate per ECMAScript §16.2.1.5.2

Given a module imported by multiple other modules When the page is loaded Then the module is fetched and evaluated exactly once (singleton semantics)

And Test262 module tests are promoted, feature matrix is updated, and just ci passes.

Story 3.5: Built-in Completeness -- Array/String/Object

As a web developer using JavaScript, I want all standard Array, String, and Object methods to be available, So that common JavaScript patterns and library code work correctly.

Acceptance Criteria:

Given Array methods (flat, flatMap, findIndex, findLast, findLastIndex, from, of, at, toReversed, toSorted, toSpliced, with, etc.) When called on arrays Then each method behaves per its ECMAScript specification

Given String methods (replaceAll, matchAll, trimStart, trimEnd, padStart, padEnd, startsWith, endsWith, at, etc.) When called on strings Then each method behaves per its ECMAScript specification

Given Object methods (fromEntries, hasOwn, entries, keys, values, assign, getOwnPropertyDescriptors, etc.) When called Then each method behaves per its ECMAScript specification

Given methods that accept callback functions (map, filter, reduce, sort, etc.) When the callback throws an error Then the error propagates correctly without corrupting internal state

And Test262 tests for each built-in are promoted in the manifest, feature matrix is updated, and just ci passes.

Story 3.6: Built-in Completeness -- Date/RegExp/Map/Set

As a web developer using JavaScript, I want Date, RegExp, Map, Set, WeakMap, and WeakSet to work completely, So that date handling, pattern matching, and collection types function correctly.

Acceptance Criteria:

Given Date construction, parsing, and formatting methods When called with various inputs (ISO strings, timestamps, individual components) Then each method behaves per ECMAScript §21.4 including edge cases (invalid dates, timezone handling)

Given RegExp with all flags (g, i, m, s, u, y, d) and advanced features (named groups, lookbehind, Unicode property escapes) When used with test(), exec(), match(), matchAll(), replace(), split() Then each operation behaves per ECMAScript §22.2

Given Map and Set with their full method sets (set/get/has/delete/clear/forEach/entries/keys/values) When used with various key types (objects, primitives, NaN, -0) Then each method behaves per ECMAScript §24.1-24.2

Given WeakMap and WeakSet with object keys When keys are no longer referenced elsewhere Then entries are eligible for garbage collection (not required to be immediate)

And Test262 tests for each built-in are promoted in the manifest, feature matrix is updated, and just ci passes.

Story 3.7: WeakRef, FinalizationRegistry & Strict Mode Edge Cases

As a web developer using JavaScript, I want advanced memory management APIs and complete strict mode support, So that all ECMAScript edge cases are handled correctly.

Acceptance Criteria:

Given a WeakRef wrapping an object When deref() is called Then the target object is returned if still alive, or undefined if collected per ECMAScript §26.1

Given a FinalizationRegistry with a registered target When the target is garbage collected Then the cleanup callback is eventually called with the held value per ECMAScript §26.2

Given strict mode code with assignments to undeclared variables When executed Then a ReferenceError is thrown instead of creating a global

Given strict mode edge cases (duplicate parameter names, with statement, octal literals, delete on unqualified identifiers) When parsed or executed in strict mode Then SyntaxError or appropriate errors are thrown per ECMAScript §10.2.1

And Test262 tests for WeakRef, FinalizationRegistry, and strict mode are promoted, feature matrix is updated, and just ci passes.

Story 3.8: DOM Bindings via web_api

As a web developer using JavaScript, I want full DOM manipulation capabilities from JavaScript, So that dynamic web pages can create, modify, and style elements at runtime.

Acceptance Criteria:

Given JavaScript calling document.createElement(tagName) When the element is created and appended to the DOM Then the element is rendered with correct default styling and behavior

Given JavaScript accessing element.classList (add, remove, toggle, contains) When classes are modified Then the element's class attribute updates and styles are recomputed on the next render

Given JavaScript accessing element.style.propertyName for reading and writing When inline styles are set or read Then the values affect rendering and reflect the current inline style

Given JavaScript accessing element.getAttribute(), setAttribute(), removeAttribute() When attributes are modified Then the DOM reflects the changes and dependent behavior updates (e.g., src triggers fetch)

Given JavaScript accessing node properties (textContent, innerHTML, childNodes, parentNode, nextSibling) When read or written Then the values reflect the current DOM state and mutations trigger re-rendering

And integration tests verify each binding, DOM checklist is updated, and just ci passes.

Story 3.9: Event Dispatch Completeness

As a web developer using JavaScript, I want all event types and dispatch phases to work correctly, So that interactive elements respond to user actions as expected.

Acceptance Criteria:

Given an event listener registered with addEventListener(type, handler, {capture: true}) When the event is dispatched Then the handler fires during the capture phase (root to target) per DOM §2.9

Given mouse events (click, mousedown, mouseup, mouseover, mouseout, mousemove) When dispatched to JavaScript handlers Then event objects include correct properties (clientX, clientY, button, target)

Given keyboard events (keydown, keyup, keypress) When dispatched to JavaScript handlers Then event objects include correct properties (key, code, ctrlKey, shiftKey, altKey)

Given focus events (focus, blur, focusin, focusout) When focus changes between elements Then events fire in the correct order with correct relatedTarget values

Given event.stopPropagation() or event.stopImmediatePropagation() called in a handler When the event continues dispatching Then propagation stops at the current target (stopPropagation) or current handler (stopImmediatePropagation)

And integration tests verify each event type and dispatch behavior, and just ci passes.

Story 3.10: Web API Exposure

As a web developer using JavaScript, I want fetch, console, and scheduling APIs to work correctly, So that network requests, debugging, and async task scheduling function properly.

Acceptance Criteria:

Given JavaScript calling fetch(url) When the request completes Then a Response object is returned with correct status, headers, and body methods (text(), json(), arrayBuffer())

Given JavaScript calling console.log(), console.warn(), console.error() with multiple arguments When executed Then all arguments are formatted and output correctly including object inspection

Given setTimeout and setInterval with callbacks and delay values When the event loop runs Then callbacks execute after the specified delay in correct macrotask order per HTML §8.6

Given Promise.then() microtasks interleaved with setTimeout macrotasks When the event loop runs Then all microtasks drain before the next macrotask executes

Given requestAnimationFrame callbacks When the render loop runs Then callbacks execute before the next paint in registration order

And integration tests verify each API's behavior, and just ci passes.


Epic 4: User Input & Forms

Users fill out and submit forms on real websites. All form controls work, client-side validation provides feedback, multipart/form-data supports file uploads, focus and keyboard navigation work correctly.

FRs covered: FR26, FR27, FR28, FR29, FR30

Story 4.1: Text Inputs & Textareas

As a web user, I want to type text into input fields and textareas, So that I can enter data into forms on websites.

Acceptance Criteria:

Given an <input type="text"> element When the user clicks on it and types Then text appears in the input field with a visible cursor at the insertion point

Given an <input> with type="password" When the user types Then characters are masked (displayed as dots or asterisks)

Given an <input> with placeholder attribute and no value When the input is rendered Then the placeholder text is displayed in a dimmed style and disappears when the user types

Given a <textarea> element When the user types multiple lines of text Then the text wraps and the textarea scrolls to accommodate content exceeding its height

Given an <input> with value, maxlength, or readonly attributes When the user interacts with it Then the initial value is displayed, input is limited to maxlength characters, and readonly inputs reject editing

And integration tests verify each input type's behavior, golden tests cover rendering, and just ci passes.

Story 4.2: Buttons, Checkboxes & Radio Buttons

As a web user, I want to click buttons, toggle checkboxes, and select radio options, So that I can make choices and trigger actions in web forms.

Acceptance Criteria:

Given a <button> or <input type="submit"> element When the user clicks it Then the button's click event fires and submit buttons trigger form submission

Given an <input type="checkbox"> When the user clicks it Then the checked state toggles and the change event fires

Given multiple <input type="radio"> elements with the same name attribute When the user selects one Then the previously selected radio in the group is deselected and the change event fires

Given a <label> element associated with a form control (via for attribute or nesting) When the user clicks the label Then the associated control is activated (focused, toggled, or clicked)

Given form controls with disabled attribute When the user attempts to interact Then the control does not respond and is rendered in a disabled visual style

And integration tests verify each control type, golden tests cover rendering states, and just ci passes.

Story 4.3: Select Menus & Option Elements

As a web user, I want to choose from dropdown menus on web forms, So that I can select options from predefined lists.

Acceptance Criteria:

Given a <select> element with <option> children When the user clicks the select element Then a dropdown list of options is displayed

Given an open select dropdown When the user clicks an option Then the option is selected, the dropdown closes, and the change event fires

Given a <select> with an <option selected> attribute When the page is rendered Then the pre-selected option is displayed as the current value

Given a <select multiple> element When the user clicks options (with Ctrl/Cmd for multi-select) Then multiple options can be selected simultaneously

Given a <select> with <optgroup> elements When the dropdown is displayed Then options are grouped under non-selectable group labels

And integration tests verify select behavior, golden tests cover dropdown rendering, and just ci passes.

Story 4.4: Form Submission

As a web user, I want forms to submit my data to the server, So that I can log in, search, and interact with web applications.

Acceptance Criteria:

Given a <form method="GET"> with filled form controls When the form is submitted Then form data is serialized as application/x-www-form-urlencoded and appended to the action URL as a query string

Given a <form method="POST"> with filled form controls When the form is submitted Then form data is serialized as application/x-www-form-urlencoded in the request body

Given a <form enctype="multipart/form-data" method="POST"> When the form is submitted Then form data is encoded using multipart MIME format with correct boundary delimiters

Given a form with disabled controls or controls without name attributes When the form is submitted Then those controls are excluded from the submitted data per HTML §4.10.21.3

Given a form with action, method, and target attributes When submitted Then the request is sent to the action URL using the specified method

And integration tests verify each submission method and encoding, and just ci passes.

Story 4.5: Client-Side Form Validation

As a web user, I want the browser to validate my form input before submission, So that I get immediate feedback on errors without a server round-trip.

Acceptance Criteria:

Given an <input required> that is empty When the form is submitted Then submission is blocked and a validation message is shown on the invalid control

Given an <input pattern="[A-Z]{3}"> with a value that doesn't match When the form is submitted Then submission is blocked and a pattern mismatch message is shown

Given an <input type="number" min="1" max="100"> with a value outside the range When the form is submitted Then submission is blocked with a range overflow/underflow message

Given an <input minlength="3" maxlength="50"> with a value outside the length bounds When the form is submitted Then submission is blocked with a too-short/too-long message

Given an <input type="email"> or <input type="url"> with an invalid value When the form is submitted Then submission is blocked with a type mismatch message

Given a form with novalidate attribute or a submit button with formnovalidate When the form is submitted Then client-side validation is skipped

And integration tests verify each constraint type, and just ci passes.

Story 4.6: Click, Keyboard & Scroll Interaction

As a web user, I want my clicks, key presses, and scroll actions to work correctly on all page content, So that I can interact with web pages naturally.

Acceptance Criteria:

Given the user clicks on an element When the click event is processed Then the correct element receives the event based on hit testing (topmost visible element at the click coordinates)

Given the user presses keys while an element is focused When the keydown/keyup events are processed Then the correct key information is delivered to the focused element and default behaviors fire (e.g., typing in inputs, Enter on links)

Given the user scrolls via mouse wheel or trackpad When the scroll event is processed Then the correct scrollable container scrolls by the appropriate amount

Given a page with nested scrollable containers When the inner container reaches its scroll boundary Then scroll events propagate to the outer container (scroll chaining)

And integration tests verify hit testing, keyboard dispatch, and scroll behavior, and just ci passes.

Story 4.7: Focus Management & Keyboard Navigation

As a web user, I want to navigate between interactive elements using the Tab key, So that I can use web forms and pages without a mouse.

Acceptance Criteria:

Given a page with focusable elements (links, form controls, elements with tabindex) When the user presses Tab Then focus moves to the next focusable element in document order

Given the user pressing Shift+Tab When an element is focused Then focus moves to the previous focusable element in document order

Given elements with tabindex="0" When the user tabs through the page Then those elements are included in the tab order at their document position

Given elements with tabindex="-1" When the user tabs through the page Then those elements are skipped but can be focused programmatically via JavaScript

Given elements with positive tabindex values When the user tabs through the page Then those elements are visited first in ascending tabindex order, before tabindex="0" elements

And integration tests verify tab order with various tabindex configurations, and just ci passes.


Epic 5: Navigation & Browser Shell

Complete browsing experience -- history navigation, error pages, loading indicators, reload/stop, and polished chrome UI. Maintains already-delivered networking capabilities (cookies, caching, sessions).

FRs covered: FR18, FR19, FR20a, FR20b, FR24, FR31, FR33, FR34, FR35, FR36 (+ maintained: FR21, FR22, FR23, FR41)

Story 5.1: URL Navigation & Protocol Schemes

As a web user, I want to navigate to any URL and have the correct content load, So that I can browse websites, local files, and embedded data content.

Acceptance Criteria:

Given the user enters an HTTP or HTTPS URL in the address bar When the navigation is initiated Then the resource is fetched over the network, parsed, and rendered

Given the user enters a file:// URL When the navigation is initiated Then the local file is read from disk and rendered

Given the user enters a URL without a scheme (e.g., example.com) When the navigation is initiated Then a reasonable default scheme is prepended (e.g., https://)

And integration tests verify navigation for each protocol scheme, and just ci passes.

Story 5.2: Redirect Handling

As a web user, I want the browser to follow redirects automatically, So that I reach the correct page even when URLs have moved.

Acceptance Criteria:

Given an HTTP response with status 301 or 302 and a Location header When the browser processes the response Then the browser automatically navigates to the redirect target URL

Given an HTTP 303 redirect after a POST request When the browser follows the redirect Then the subsequent request uses the GET method

Given an HTTP 307 or 308 redirect When the browser follows the redirect Then the original request method and body are preserved

Given a redirect chain exceeding 20 hops When the browser follows the chain Then navigation stops and an error is displayed to the user

And integration tests verify each redirect status code and the hop limit, and just ci passes.

Story 5.3: Error Pages

As a web user, I want to see a clear error message when a page fails to load, So that I understand what went wrong instead of seeing a blank screen.

Acceptance Criteria:

Given an HTTP response with a 404 status code When the page is rendered Then the user sees an error page displaying the status code and a descriptive message

Given an HTTP response with a 500 status code When the page is rendered Then the user sees an error page indicating a server error

Given a DNS resolution failure When the navigation fails Then the user sees an error page indicating the domain could not be found

Given a connection timeout or connection refused error When the navigation fails Then the user sees an error page within 10 seconds of the failure per NFR15

Given any network or HTTP error When the error page is displayed Then the address bar still shows the attempted URL so the user can retry or edit it

And integration tests verify error page display for each failure type, and just ci passes.

Story 5.4: History Navigation

As a web user, I want to go back and forward through pages I've visited, So that I can return to previously viewed content.

Acceptance Criteria:

Given the user has navigated to 3+ pages in sequence When the user clicks the back button or presses the back shortcut Then the previous page is restored with its content re-rendered

Given the user has gone back one or more pages When the user clicks the forward button Then the next page in the forward history is restored

Given the user is on the first page in history When the back button is rendered Then it appears disabled or inactive

Given the user navigates to a new page after going back When the navigation completes Then the forward history is cleared (standard browser behavior)

And integration tests verify history navigation across 3+ entries, and just ci passes.

Story 5.5: Page Scrolling

As a web user, I want to scroll through pages that are taller or wider than my window, So that I can access all content on the page.

Acceptance Criteria:

Given a page with content taller than the viewport When the user scrolls vertically (mouse wheel, trackpad, or keyboard) Then the page content scrolls smoothly revealing content below

Given a page with content wider than the viewport When the user scrolls horizontally Then the page content scrolls horizontally revealing content to the right

Given the user presses Page Down, Page Up, Home, or End keys When the page is scrollable Then the page scrolls by the appropriate amount (viewport height for Page keys, top/bottom for Home/End)

Given the user scrolls to the top or bottom of the page When further scroll input is received in that direction Then no further scrolling occurs (scroll position clamps to content bounds)

And integration tests verify vertical/horizontal scrolling and keyboard scroll, and just ci passes.

Story 5.6: Browser Chrome Completeness

As a web user, I want a polished browser interface with working navigation controls and loading feedback, So that I have a complete browsing experience.

Acceptance Criteria:

Given the browser is running When the chrome UI is rendered Then the address bar, back/forward buttons, reload button, and stop button are visible and correctly laid out at window widths from 800px to 2560px

Given the user navigates to a page When the page is loading Then a loading indicator is visible in the chrome UI

Given a page has finished loading or failed to load When the loading completes Then the loading indicator is cleared

Given the user clicks the reload button When a page is currently displayed Then all resources are re-fetched and the page is re-rendered

Given the user clicks the stop button When a page is currently loading Then pending resource fetches are cancelled and the page displays whatever has loaded so far

Given the user navigates to a new page When the navigation completes Then the address bar updates to reflect the current URL

And integration tests verify each chrome UI behavior, and just ci passes.


Epic 6: Security, Storage & Robustness

Safe browsing with same-origin policy enforcement, URI navigation blocking, localStorage/sessionStorage for web apps, and crash-free handling of malformed input across all parsers.

FRs covered: FR38, FR39, FR42, FR50

Story 6.1: Same-Origin Policy Enforcement

As a web user, I want the browser to prevent malicious scripts from accessing my data on other sites, So that my browsing sessions are secure.

Acceptance Criteria:

Given JavaScript on origin A attempting to read DOM content from an iframe on origin B When the access is attempted Then a SecurityError is thrown and access is denied

Given JavaScript on origin A attempting to read cookies scoped to origin B When the access is attempted Then the cookies are not accessible

Given JavaScript on origin A making a fetch request to origin B without CORS headers When the response is received Then the response body is opaque and not readable by the script

Given two pages on the same origin (same scheme, host, and port) When JavaScript on one page accesses the other's resources Then access is permitted

And cross-origin integration tests verify blocked access for DOM, cookies, and fetch responses, and just ci passes.

Story 6.2: URI Navigation Blocking

As a web user, I want the browser to block dangerous URI navigations, So that I am protected from javascript: and data: URI attacks.

Acceptance Criteria:

Given a top-level navigation to a javascript: URI (e.g., clicking a link with href="javascript:alert(1)") When the navigation is initiated Then the navigation is blocked and no script is executed

Given a top-level navigation to a data: URI (e.g., data:text/html,...) When the navigation is initiated Then the navigation is blocked

Given a sub-resource using a data: URI (e.g., <img src="data:image/png;base64,...">) When the resource is loaded Then the data: URI is permitted and the resource loads correctly

Given JavaScript attempting window.location = "javascript:..." or window.location = "data:..." When the assignment is executed Then the navigation is blocked

And integration tests verify blocked and permitted cases for each URI scheme, and just ci passes.

Story 6.3: localStorage & sessionStorage

As a web developer using JavaScript, I want localStorage and sessionStorage APIs to work, So that web applications can persist data on the client side.

Acceptance Criteria:

Given JavaScript calling localStorage.setItem(key, value) and localStorage.getItem(key) When the operations execute Then the value is stored persistently and retrievable across page navigations within the same origin

Given JavaScript calling sessionStorage.setItem(key, value) When the value is retrieved in the same browsing session Then the value is available, but cleared when the tab/session closes

Given JavaScript calling localStorage.removeItem(key) or localStorage.clear() When the operation executes Then the specified key or all keys are removed from storage

Given JavaScript on origin A accessing localStorage When JavaScript on origin B attempts to access the same storage Then each origin has isolated storage and cannot access the other's data

Given localStorage data exceeding 5MB for a single origin When a setItem call would exceed the limit Then a QuotaExceededError is thrown

And integration tests verify getItem/setItem/removeItem/clear, storage limits, and cross-origin isolation, and just ci passes.

Story 6.4: Malformed Input Resilience

As a web user, I want the browser to handle broken or adversarial content without crashing, So that I can browse safely even on malformed pages.

Acceptance Criteria:

Given malformed HTML (unclosed tags, invalid nesting, truncated documents, binary content) When the HTML parser processes it Then parsing completes without panics, producing a best-effort DOM tree

Given malformed CSS (invalid property names, unclosed blocks, garbage bytes, deeply nested selectors) When the CSS parser processes it Then parsing completes without panics, skipping invalid rules per CSS error recovery

Given malformed JavaScript (syntax errors, deeply nested expressions, extremely long strings, invalid Unicode) When the JS parser/engine processes it Then a SyntaxError or appropriate error is reported to console.error without process termination

Given adversarial input designed to trigger resource exhaustion (billion-laughs HTML, regex backtracking, deeply recursive structures) When the parsers process it Then processing terminates gracefully within reasonable time and memory bounds

And fuzz tests and malformed-input test suites covering each parser run without panics, and just ci passes.