Install BMAD workflow framework with agent commands and templates. Create product brief, PRD, project context, and architecture decision document covering networking/persistence strategy, JS engine evolution path, threading model, web_api scaling, system integration, and tab/process model. Add generated project documentation (architecture overview, component inventory, development guide, source tree analysis). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
32 KiB
stepsCompleted, lastStep, status, completedAt, inputDocuments, workflowType, project_name, user_name, date
| stepsCompleted | lastStep | status | completedAt | inputDocuments | workflowType | project_name | user_name | date | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
8 | complete | 2026-03-12 |
|
architecture | rust_browser | Zach | 2026-03-09 |
Architecture Decision Document
This document builds collaboratively through step-by-step discovery. Sections are appended as we work through each architectural decision together.
Project Context Analysis
Requirements Overview
Functional Requirements:
50 FRs spanning 9 categories. The heaviest architectural weight falls on:
- Web Content Rendering (FR1-10): Full CSS 2.1 pipeline (parse/cascade/compute/layout/paint) plus images, generated content, and visual effects. Currently ~30% of CSS 2.1 checklist complete — the remaining 70% will systematically expand every engine crate.
- JavaScript Execution (FR11-17): Custom engine must reach near-100% Test262 conformance. Currently at 70% on 550 vendored tests. Requires generators, async/await, ES modules, and complete built-in coverage — each touching js_parser, js_vm, and potentially web_api.
- Navigation & Networking (FR18-25): Milestone 7's immediate focus. Cookie jar, HTTP caching, session persistence, and improved error handling require expanding the
netandstoragecrates and wiring them throughbrowser_runtime. - Browser Shell & UI (FR31-36): Tabbed browsing, reload/stop, loading status. Currently single-tab with URL bar and basic chrome. Tab management will expand
browser_runtimeandapp_browser. - System Integration (FR43-46): OS font discovery, clipboard, file dialogs, URL handler registration. All must route through
crates/platform/per layering rules.
Non-Functional Requirements:
21 NFRs with the most architecturally significant being:
- NFR1-5 (Performance): 3-second page load, smooth scrolling, 100ms JS yield budget, 2-second startup, stable memory. The single-threaded model must eventually accommodate these without architectural rewrites.
- NFR6-10 (Security): Untrusted input everywhere, unsafe forbidden outside platform/graphics, same-origin policy, no telemetry. These are hard constraints on every architectural decision.
- NFR11-15 (Reliability): No-crash guarantee on any input, CI gate on every change, regression tests mandatory, graceful network failure recovery.
- NFR16-21 (Maintainability): 4-layer hierarchy enforced by CI, single-responsibility crates, file size limits, spec citations, comprehensible to one person.
Scale & Complexity:
- Primary domain: Systems software — desktop browser engine
- Complexity level: High (web standards surface area, multi-subsystem interaction, custom JS engine)
- Existing architectural components: 22 crates across 4 layers
- Estimated growth: web_api, net, storage, and browser_runtime will see the most expansion; new crates unlikely in near term
Technical Constraints & Dependencies
| Constraint | Source | Architectural Impact |
|---|---|---|
No unsafe outside platform/graphics |
CI-enforced policy | All new subsystems must use safe Rust; FFI or GPU work funneled through two crates |
| No upward dependencies between layers | CI-enforced (check_deps.sh) |
New features in engine crates cannot import browser_runtime or app_browser |
| Single-threaded rendering pipeline | Design principle (determinism) | Compositor thread or parallel style must be introduced carefully when performance demands it |
| Arena-based cross-crate IDs | Existing pattern (NodeId, StyleId, LayoutId) | New subsystems must follow this pattern rather than introducing lifetime-based references |
| Phase-based mutation model | Existing pattern | Parse → DOM → Style → Layout → Paint sequence must be preserved; no skipping phases |
| Blocking HTTP client (ureq) | Current dependency | Async networking would require architectural change; current model uses worker threads for I/O |
| Bundled fonts only (no system fonts) | Known limitation | System font discovery (FR43) requires expanding fonts crate and platform integration |
| ~1 minute CI gate | Existing practice | Architecture changes must not significantly increase CI time; test262-full runs separately |
Cross-Cutting Concerns Identified
-
Spec compliance pipeline — Every CSS/HTML/JS feature addition touches 3-6 crates in sequence. The architecture must make this pipeline predictable and testable at each stage.
-
Error resilience at every boundary — HTML, CSS, JS parsers plus network responses all handle untrusted input. Error recovery patterns must be consistent across all parsers without crashing or undefined behavior.
-
Resource lifecycle management — Stylesheets, scripts, images, and fonts all follow a fetch → decode → use pattern routed through
net. As caching and cookies are added, resource lifecycle becomes a cross-cutting concern touching net, browser_runtime, and every consumer crate. -
Testing infrastructure scaling — Golden tests, WPT harness, Test262 harness, and unit tests all need to grow proportionally with features. The testing architecture must accommodate 50,000+ Test262 tests and growing WPT coverage without CI becoming a bottleneck.
-
State spanning navigation — Cookies, session data, browsing history, and cached resources must persist across navigations and eventually across restarts. This requires coordinating
net,storage,browser_runtime, and eventuallyapp_browser. -
Web API surface growth — The
web_apicrate bridges JS ↔ DOM and will absorb every new DOM API, event type, and Web API binding. It needs a scalable internal organization pattern to avoid becoming monolithic.
Starter Template Evaluation
Primary Technology Domain
Rust systems software — desktop browser engine. Brownfield project with established architecture.
Starter Template: Not Applicable (Brownfield)
rust_browser is not a greenfield project requiring a starter template. The codebase has been through 6+ milestones and has a mature, CI-enforced architecture.
Existing Technical Foundation
Language & Runtime:
- Rust edition 2021, stable toolchain (pinned via
rust-toolchain.toml) - Cargo workspace with 22 member crates
- No async runtime on main thread; blocking is acceptable in the rendering path
Build & CI Tooling:
justtask runner withjust cias the single validation command (~1 min)cargo fmt,cargo xclippy -- -D warnings, policy scriptsdeny.tomlfor license/advisory policy (cargo-deny)
Testing Framework:
- Inline
#[cfg(test)]unit tests + roottests/integration tests - Golden regression tests (layout tree + display list dumps)
- WPT harness for CSS/HTML spec compliance
- Test262 harness (two-tier: vendored PR gate + full upstream suite)
- proptest for property-based testing
Key Dependencies:
- winit 0.30 (windowing), softbuffer 0.4 (pixel presentation)
- ureq 2.x (HTTP), url 2.x, encoding_rs 0.8
- image 0.25, resvg 0.47 (image decoding/SVG)
- ab_glyph (font rasterization), bundled Noto Sans fonts
- logos 0.14 (CSS tokenizer), regress 0.10 (JS regex)
- thiserror 1.x + anyhow 1.x (error handling)
- tracing 0.1 (structured logging)
Code Organization:
- Strict 4-layer hierarchy enforced by
scripts/check_deps.sh - Arena-based data flow with integer IDs across crate boundaries
- Phase-based pipeline: parse → DOM → style → layout → display list → render
unsafeforbidden globally except platform/ and graphics/ (enforced by CI)
Note: No project initialization needed. Future architectural decisions build on this established foundation.
Core Architectural Decisions
Decision Priority Analysis
Critical Decisions (Block Implementation):
- Networking & state persistence architecture (Milestone 7 blocker)
- Web API crate scaling strategy (affects all new API work)
Important Decisions (Shape Architecture):
- JS engine bytecode introduction timing
- Threading model evolution path
- System integration routing through platform/
Deferred Decisions (Decide When Needed):
- Multi-process tab architecture (when tabs are implemented)
- Tab state sharing model (when tabs exist + performance data)
- JIT compilation (after bytecode + high spec compliance)
Networking & State Persistence
| Decision | Choice | Rationale |
|---|---|---|
| Cookie jar location | Module within net, interface designed for swappable backing store |
Cookies are consumed at the HTTP layer; keep them close. Interface allows later migration to storage-backed persistence. Extract to own crate if complexity warrants. |
| HTTP cache | In-memory first, disk persistence later via storage |
In-memory caching is already partially implemented. Disk persistence adds complexity that can wait. |
| Storage crate role | General-purpose persistence layer for all disk-persisted data | storage manages the persistence engine; cookies, cache, localStorage, sessionStorage ride on top. Each consumer starts in-memory and plugs into storage when disk persistence is needed. |
JavaScript Engine Evolution
| Decision | Choice | Rationale |
|---|---|---|
| Bytecode introduction | When generators/async-await become the next JS priority | AST walker is sufficient for current spec compliance work (built-ins, Test262 gaps). Bytecode IR (not JIT) introduced as a bytecode interpreter when suspension semantics require it. Provides natural model for generators, better dispatch performance, and future JIT foundation. |
| Generators/async-await | Forcing function for bytecode introduction | Implementing suspension on the AST walker is architecturally awkward. Let this feature drive the bytecode transition. |
| ES modules registry | Lives in js_vm |
Keeps JS engine self-contained. Module fetching involves net but the registry and linking semantics are JS-internal. |
| JIT compilation | Deferred until bytecode exists + spec compliance is high | Interpreter remains the correctness oracle. JIT is a performance optimization, not a correctness requirement. |
Threading Model Evolution
| Decision | Choice | Rationale |
|---|---|---|
| First concurrency step | Compositor thread consuming immutable display lists | Already hinted at in architecture exploration doc. Display list abstraction is built for this. Main thread produces display list, compositor thread rasterizes asynchronously. |
| JS yield mechanism | Cooperative yielding via statement counter | Existing max_statements in VmConfig provides the infrastructure. Check budget periodically, yield to rendering. Simpler than preemptive interruption. Less critical once JS eventually moves to its own thread. |
Web API Crate Scaling
| Decision | Choice | Rationale |
|---|---|---|
| Organization strategy | Module-per-domain initially, extract to web_api_<domain> crates when complexity warrants |
Start with internal module organization (dom_bindings/, events/, scheduling/, etc.). When a domain crosses ~10-15 files or develops internal module structure, extract to web_api_events, web_api_storage, etc. Original web_api becomes facade/coordinator. Follows js/js_vm/js_parser pattern. |
System Integration
| Decision | Choice | Rationale |
|---|---|---|
| System font discovery | platform/ handles OS-specific discovery via trait; fonts crate provides FontProvider facade |
Platform-specific behavior belongs in platform/. fonts owns the facade the rest of the project uses, with platform implementation injected at startup. Bundled Noto Sans remains fallback. |
| Clipboard & file dialogs | Wrapped in platform/ behind traits (ClipboardProvider, FileDialogProvider); consumed by app_browser |
Cross-platform crates (arboard, rfd) wrapped behind traits for testability and platform-agnosticism in app_browser. |
Tab & Process Model
| Decision | Choice | Rationale |
|---|---|---|
| Process model | Single-process now; multi-process when tabs are implemented | No reason to build multi-process complexity before tabs exist. Design the multi-process architecture when tabbed browsing is the active milestone. |
| Tab state isolation | Fully isolated per tab (each tab owns its own DOM, JS engine, styles, layout) | Simpler starting point. Maps naturally to multi-process later. Shared caches (fonts, images) can be introduced as optimization. Cookie jar will need semantic sharing across tabs — design with tab implementation. |
Decision Impact Analysis
Implementation Sequence:
- Cookie module in
net+storagecrate persistence interface (Milestone 7) - HTTP cache improvements using in-memory store (Milestone 7)
- Web API internal module reorganization (ongoing, as APIs are added)
- System font discovery via
platform/+fontsfacade (Phase 3) - Bytecode IR introduction (when generators/async-await are prioritized)
- Compositor thread (when performance NFRs become blocking)
- Tab architecture + multi-process model (Phase 3)
Cross-Component Dependencies:
- Storage persistence interface must be designed before cookies can be persisted to disk
- Bytecode IR must exist before generators/async-await can be cleanly implemented
- Compositor thread requires display list to be fully immutable after generation (already the case)
- Multi-process tabs require fully isolated tab state (chosen as the default)
Implementation Patterns & Consistency Rules
Feature Implementation Checklists
CSS Property Implementation Order:
- Parse in
css/(tokenizer + parser + CssValue variant) - Add computed style field in
style/(ComputedStyles + inheritance + initial value) - Implement layout effect in
layout/(if layout-affecting) - Implement paint effect in
display_list/(if visual) - Add golden test(s) in
tests/goldens/ - Update
docs/CSS2.1_Implementation_Checklist.md - Run
just ci
HTML Element/Feature Implementation Order:
- Add parsing support in
html/(tokenizer recognition, tree builder handling) - Add DOM representation in
dom/if needed (new NodeKind variant, element-specific data) - Add default styling in
style/(UA stylesheet rules for the element) - Implement layout behavior in
layout/(if element has special layout semantics) - Implement paint behavior in
display_list/(if element has special visual rendering) - Wire runtime behavior in
web_api/(if element has JS-observable behavior) - Add golden test(s) in
tests/goldens/ - Update
docs/HTML5_Implementation_Checklist.md - Run
just ci
JS Feature Implementation Order:
- Add tokenization in
js_parser/(if new syntax) - Add AST node(s) in
js_parser/ - Implement execution in
js_vm/ - Add unit tests inline in the implementing crate
- Add/update Test262 conformance tests in manifest
- Update
docs/js_feature_matrix.md - Run
just ci
Not every feature needs every step — a semantic HTML element may only need parsing + UA styling + golden test + checklist. But the ordering is always: parser first, work down the pipeline, tests and docs last.
Error Handling Patterns
| Crate Category | Pattern | Details |
|---|---|---|
| Parser crates (html, css, js_parser) | Specific error types with source locations | thiserror derive. Never panic on malformed input — return error or recover gracefully. |
| Engine crates (style, layout, display_list, render) | SharedResult<T> for fallible operations |
Internal bug indicators use debug_assert! but must not panic in release builds. |
| Bridge crates (web_api, browser_runtime) | Convert between error domains at boundaries | JS-visible errors become JsValue error objects. Navigation errors become NavigationState::Failed. |
Error type conventions:
- Always derive
Debug, Error, Clone, PartialEq, Eqvia thiserror - Include constructor helpers (e.g.,
NavigationError::network(msg)) - Implement
Fromconversions for related error types manually
Test Placement & Naming
| Test Type | Location | Naming | When to Use |
|---|---|---|---|
| Unit tests | Inline #[cfg(test)] mod tests |
test_<what_is_being_tested> |
Internal/private logic within a single crate |
| Split test files | src/tests/ with mod.rs |
_tests suffix (e.g., flex_layout_tests.rs) |
When inline test module exceeds ~200 lines |
| Integration tests | tests/*.rs |
Descriptive name + [[test]] in Cargo.toml |
Cross-crate behavior requiring full pipeline |
| Golden tests | tests/goldens/fixtures/ + expected/ |
NNN-descriptive-name.html (sequential) |
Any rendering behavior change |
| Regression tests | Inline or integration depending on scope | Named for the bug, not the fix | Every bug fix (mandatory) |
Spec Citation Format
- CSS:
// CSS 2.1 §8.3.1or// Per CSS 2.1 §17.5.2.1 - HTML:
// HTML §12.2.6.4.7(WHATWG section numbers) - ECMAScript:
// ECMAScript §13.15.3 - When: Any non-obvious behavior implementing a specific spec rule. Not needed for plumbing code.
- Where: Inline comment on the implementing line/block, not in doc comments.
New Crate & Module Introduction
| Action | When | Requirements |
|---|---|---|
| New file within a crate | Adding a logically distinct subsystem | Don't add unrelated functionality to existing files. Respect file size limits. |
| New crate | Subsystem needed by multiple Layer 1 crates, or extracting from an overgrown crate | Add to workspace Cargo.toml members. Update check_deps.sh layer assignment. |
| Module visibility | Always | New modules are mod (private) in lib.rs. Public API re-exported via pub use. No pub mod. |
Dependency Addition Protocol
- Check if
stdcan do it — don't add a crate for what the standard library provides - Pin in
[workspace.dependencies]in rootCargo.tomlwith exact version - Crates reference via
dep.workspace = true - Document rationale in PR/commit message (why needed, alternatives considered)
- Must pass
deny.tomllicense/advisory checks - Prefer lightweight crates — avoid large dependency trees for small functionality
Enforcement
All AI agents MUST:
- Follow feature implementation checklists in order (parser → pipeline → tests → docs)
- Update the relevant checklist document when implementing any CSS, HTML, or JS feature
- Include a regression test with every bug fix
- Cite spec sections for non-obvious behavior
- Run
just ciafter every code change - Never add
unsafeoutside platform/ and graphics/ - Never introduce upward dependencies between layers
Violations are caught by:
just ci(formatting, linting, tests, policy scripts)scripts/check_deps.sh(layer violations)scripts/check_unsafe.sh(unsafe policy)scripts/check_file_size.sh(file size limits)- Code review (naming, spec citations, test quality)
Project Structure & Boundaries
Complete Project Directory Structure
rust_browser/
├── Cargo.toml # Workspace root: members, dependency versions, lints
├── Cargo.lock # Pinned dependency versions
├── CLAUDE.md # AI agent development instructions
├── AGENTS.md # Agent contract and rules
├── rust-toolchain.toml # Toolchain: stable, rustfmt, clippy
├── deny.toml # License/advisory policy (cargo-deny)
├── justfile # Task runner: ci, test, lint, fmt, policy, metrics
├── src/lib.rs # Root crate: re-exports for integration tests
│
├── crates/ # ── All workspace crates ──
│ ├── shared/ # [Layer 0] Common types, geometry, errors
│ │
│ ├── js_parser/ # [Layer 1] JS tokenization + AST
│ ├── js_vm/ # [Layer 1] JS interpreter + runtime
│ ├── js/ # [Layer 1] JS engine facade
│ │
│ ├── html/ # [Layer 1] HTML tokenizer + tree builder
│ ├── dom/ # [Layer 1] DOM tree representation
│ ├── css/ # [Layer 1] CSS tokenizer + parser
│ ├── selectors/ # [Layer 1] Selector matching + specificity
│ ├── style/ # [Layer 1] Cascade + computed styles + UA stylesheet
│ │
│ ├── layout/ # [Layer 1] Layout engine (block/inline/flex/table/positioned)
│ ├── display_list/ # [Layer 1] Display list builder
│ ├── render/ # [Layer 1] CPU rasterizer
│ ├── graphics/ # [Layer 1] Graphics backend abstraction (unsafe allowed)
│ │
│ ├── net/ # [Layer 1] HTTP/file/data-URI loading + caching
│ │ └── src/
│ │ ├── cookie_jar.rs # [PLANNED] Cookie storage + domain scoping
│ │ └── cache.rs # [EXISTS] In-memory HTTP cache
│ ├── storage/ # [Layer 1] Persistent storage engine (placeholder → expand)
│ ├── image/ # [Layer 1] Image decode pipeline
│ ├── fonts/ # [Layer 1] Font loading + metrics + rasterization
│ │ └── data/ # Bundled Noto Sans fonts (3.1 MB)
│ ├── platform/ # [Layer 1] OS windowing + events (unsafe allowed)
│ ├── web_api/ # [Layer 1] JS↔DOM bridge, events, scheduling
│ │ └── src/
│ │ ├── dom_bindings/ # [PLANNED] querySelector, classList, style, ...
│ │ ├── events/ # [PLANNED] click, keyboard, focus, ...
│ │ └── scheduling/ # [EXISTS] setTimeout, microtasks, promises
│ │
│ ├── browser_runtime/ # [Layer 2] Tabs, navigation, history
│ └── app_browser/ # [Layer 3] Desktop shell, event loop, chrome
│
├── tests/ # Integration tests (each in root Cargo.toml)
│ ├── goldens.rs # Golden rendering regression tests
│ ├── goldens/ # Fixtures + expected outputs
│ ├── wpt_harness.rs # Web Platform Tests
│ ├── js262_harness.rs # Test262 JS conformance
│ ├── js_tests.rs # JS execution tests
│ ├── js_dom_tests.rs # DOM + JS interaction tests
│ ├── js_events.rs # Event system tests
│ ├── js_scheduling.rs # Microtask/promise tests
│ ├── navigation_tests.rs # Navigation lifecycle
│ ├── external_css_test.rs # CSS parsing tests
│ ├── main_cli_tests.rs # CLI integration tests
│ ├── regen_goldens.rs # Regenerate golden expected outputs
│ └── external/ # External test data (WPT, Test262)
│
├── scripts/ # Policy enforcement + utilities
├── investigations/ # Site rendering reports
└── docs/ # Project documentation + checklists
Architectural Boundaries
Layer Boundaries (enforced by CI):
Layer 3: app_browser → can depend on anything below
Layer 2: browser_runtime → can depend on Layer 1 and 0
Layer 1: engine crates → can depend on Layer 1 and 0 (no upward deps)
Layer 0: shared → no internal dependencies
Unsafe Boundary:
unsafecode allowed ONLY incrates/platform/andcrates/graphics/- All other crates inherit
unsafe_code = "forbid"from workspace lints - Enforced by
scripts/check_unsafe.sh
Pipeline Phase Boundaries:
html (parse) → dom (tree) → css (parse) → selectors (match) → style (compute)
→ layout (position) → display_list (paint commands) → render (pixels)
Each phase produces a stable representation. No phase may skip ahead or reach back.
JS ↔ DOM Boundary:
web_apiis the sole bridge between JS engine and DOM/browser- JS crates (
js,js_vm,js_parser) never import DOM types directly - DOM crate (
dom) never imports JS types directly - All interaction flows through
web_apihost bindings
Network Boundary:
netis the sole network access point for all resource loading- Engine crates request resources via
net; they don't make HTTP calls directly browser_runtimecoordinates resource loading throughnet
Requirements to Structure Mapping
| PRD Requirement Category | Primary Crates | Supporting Crates |
|---|---|---|
| Web Content Rendering (FR1-10) | css, selectors, style, layout, display_list, render | html, dom, fonts, image, shared |
| JavaScript Execution (FR11-17) | js_parser, js_vm, js, web_api | dom, shared |
| Navigation & Networking (FR18-25) | net, browser_runtime | storage, shared |
| Forms & User Input (FR26-30) | app_browser, web_api, dom | html, layout, display_list |
| Browser Shell & UI (FR31-36) | app_browser, browser_runtime | platform, shared |
| Content Security & Privacy (FR37-39) | net, browser_runtime | web_api |
| Offline & Storage (FR40-42) | storage, net | browser_runtime |
| System Integration (FR43-46) | platform, fonts | app_browser |
| Conformance & Testing (FR47-50) | All crates | tests/, scripts/ |
Planned Structural Evolution
| Change | Trigger | Crates Affected |
|---|---|---|
Cookie jar module in net |
Milestone 7 | net, browser_runtime |
| Storage crate expansion (disk persistence) | Milestone 7 (post-cookie) | storage, net |
| web_api internal module reorganization | As APIs are added | web_api |
| web_api_events extraction | When events/ exceeds ~15 files | web_api → web_api_events |
| web_api_storage extraction | When Web Storage APIs are added | web_api → web_api_storage |
| Platform font discovery | Phase 3 (system fonts) | platform, fonts |
| Platform clipboard/file dialog traits | Phase 3 (system integration) | platform, app_browser |
| Bytecode crate (js_bytecode or within js_vm) | When generators/async-await are prioritized | js_vm (or new crate) |
Data Flow
User Input (URL/click/keyboard)
→ app_browser (event handling)
→ browser_runtime (navigation lifecycle)
→ net (fetch resource)
→ html (parse HTML)
→ dom (build tree)
→ css (parse stylesheets)
→ selectors (match rules to nodes)
→ style (compute cascaded styles)
→ layout (compute box geometry)
→ display_list (generate paint commands)
→ render (rasterize to pixels)
→ platform (present to screen)
JS execution (orthogonal):
→ web_api (script execution trigger)
→ js (facade) → js_parser (parse) → js_vm (execute)
→ web_api (host bindings: DOM reads/writes, event dispatch)
→ dom (mutations) → [re-style → re-layout → re-paint]
Architecture Validation Results
Coherence Validation
Decision Compatibility: All architectural decisions are mutually compatible. No contradictions found. Key compatibility checks:
- Cookie jar in
netwith swappable backing store aligns withstorageas persistence layer - Bytecode deferral until generators/async-await is consistent with current AST walker spec compliance focus
- Compositor thread model is compatible with existing immutable display list abstraction
- web_api extraction pattern follows established
js/js_vm/js_parserprecedent - Platform traits for system integration extend existing
FontProviderpattern
Pattern Consistency: Implementation checklists follow uniform principle (parser → pipeline → tests → docs). Error handling patterns align with existing thiserror/anyhow usage. Test placement and naming rules match established practice.
Structure Alignment: All planned evolution points (cookie_jar.rs, web_api subdirectories, storage expansion) fit into existing crate layout without layer violations.
Requirements Coverage
Functional Requirements: 49 of 50 FRs have clear architectural support. FR37 (tracker/ad blocking) is architecturally unspecified — deferred to Phase 3 design.
Non-Functional Requirements: All 21 NFRs are architecturally addressed. Performance NFRs have evolution paths (compositor thread, JS yield). Security NFRs are enforced by CI. Reliability NFRs are covered by error patterns and testing mandate. Maintainability NFRs are enforced by layer hierarchy and policy scripts.
Implementation Readiness
Decision Completeness: All critical and important decisions are documented with rationale. Deferred decisions have clear triggers for when they need to be made.
Structure Completeness: Project structure is fully defined with existing layout, planned additions marked, and evolution triggers specified.
Pattern Completeness: Feature implementation checklists, error handling, test placement, spec citations, module introduction, and dependency protocols are all specified with concrete rules.
Architecture Completeness Checklist
Requirements Analysis
- Project context thoroughly analyzed (50 FRs, 21 NFRs, 42 project context rules)
- Scale and complexity assessed (High — web standards surface area)
- Technical constraints identified (8 constraints documented)
- Cross-cutting concerns mapped (6 concerns identified)
Architectural Decisions
- Critical decisions documented with rationale (networking, web API scaling)
- Technology stack fully specified (existing brownfield foundation)
- Evolution paths defined (JS bytecode, compositor thread, multi-process tabs)
- Performance considerations addressed (yield mechanism, compositor thread)
Implementation Patterns
- Feature implementation checklists established (CSS, HTML, JS)
- Error handling patterns defined by crate category
- Test placement and naming rules specified
- Spec citation format standardized
- Module introduction and dependency protocols documented
Project Structure
- Complete directory structure defined with annotations
- Architectural boundaries established (layers, unsafe, pipeline, JS↔DOM, network)
- Requirements mapped to specific crates
- Planned structural evolution documented with triggers
Architecture Readiness Assessment
Overall Status: READY FOR IMPLEMENTATION
Confidence Level: High — brownfield project with 6 milestones of proven architecture; decisions extend rather than replace existing patterns.
Key Strengths:
- Architecture is battle-tested through 6 milestones of real implementation
- CI enforcement (layers, unsafe, formatting, linting) prevents architectural drift
- Clear evolution paths for major subsystems avoid premature complexity
- Deferred decisions have explicit triggers, preventing analysis paralysis
Areas for Future Enhancement:
- Tracker/ad blocking architecture (Phase 3)
- Multi-process tab isolation details (when tabs are implemented)
- GPU rendering pipeline architecture (when CPU rasterization becomes a bottleneck)
- JIT compilation architecture (after bytecode + high spec compliance)
Implementation Handoff
AI Agent Guidelines:
- Follow all architectural decisions exactly as documented
- Use feature implementation checklists for every CSS, HTML, or JS addition
- Respect layer boundaries and unsafe policy — CI will reject violations
- Consult this document + project-context.md + CLAUDE.md for all architectural questions
First Implementation Priority:
Milestone 7 — Cookie jar module in net with domain scoping and swappable backing store, followed by HTTP cache improvements and session persistence via storage.