tauri-runtime-servocat 0.5.0

Servo-replacement runtime for Tauri: wires html-cat, css-cat, dom-cat, layout-cat, paint-cat, net-cat, boa-cat, ecma-runtime-cat, and web-api-cat into a single rendering + scripting pipeline. v0.5.0 adds an IPC bridge so JS scripts can call host commands via `__TAURI__.invoke(cmd, ...args)`, and back-propagates scripted DOM mutations into layout via `web_api_cat::extract_document`. tauri_runtime::Runtime trait impl is the remaining committed deliverable. The Servo no-AI policy disqualifies upstream contribution; this is the AI-built parallel.
# CLAUDE.md -- Rust Project Conventions

## Philosophy

Functional, type-driven, domain-driven.

## Architecture

- Modules by domain context.
- One module per concern (error, pipeline, script, frame).
- Thin lib.rs that exposes `render(html, css, viewport)` and
  `run_script(html, css, js, viewport)`.

## Types

- Newtypes for `RenderInput`, `ScriptInput`, `Frame`.
- Sum types for error variants.
- No public struct fields.
- `#[must_use]` on getters and constructors.

## Error Handling

- Single project-wide `Error` enum.
- Display + std::error::Error impls by hand; no thiserror, no anyhow.
- Never panic.

## Style

- Prefer match over if/else, except on bool.
- No `return` keyword.
- No `mut`.
- Combinators over loops.
- Never match on Option<_>; use combinators.
- No unwrap()/expect() anywhere.
- No loop or for.
- No scan.
- No Rc/Arc.
- No naked `as` casts.
- Exhaustive matches; no `_` wildcard arm on enums.

## Traits

- No dyn Trait.
- Implement standard traits over ad-hoc methods.

## Linting

```toml
[lints.clippy]
all = { level = "deny", priority = -1 }
pedantic = { level = "warn", priority = -1 }
needless_pass_by_value = "warn"
manual_map = "warn"
```

## Verification

- Always run `RUSTFLAGS="-D warnings" cargo clippy --all-targets`.
- Always run `cargo fmt`.

## Testing

- Tests return `Result<(), Error>` and propagate failures with `?`.
- No assert!, assert_eq!, panic!, unreachable!, unwrap, expect.

## Dependencies

- The full cat-stack: `html-cat`, `css-cat`, `dom-cat`, `layout-cat`,
  `paint-cat`, `net-cat`, `boa-cat`, `ecma-runtime-cat`, `web-api-cat`,
  `ecma-lex-cat`, `ecma-parse-cat`.
- `proptest` dev-dep.
- No path dependencies.

## Documentation

- `///` doc comments on every public item.
- `# Examples` with runnable code blocks.

## Layer context

This is the **meta-crate** at the top of the cat-stack:

1. `ecma-syntax-cat`, `ecma-lex-cat`, `ecma-parse-cat` -- JS AST/parse.
2. `boa-cat`, `ecma-runtime-cat` -- JS engine + built-ins.
3. `html-cat`, `css-cat` -- web-spec parsers.
4. `dom-cat`, `layout-cat`, `paint-cat` -- rendering pipeline.
5. `net-cat` -- HTTP transport.
6. `web-api-cat` -- JS<->DOM/fetch bridge.
7. **`tauri-runtime-servocat`** -- meta-crate wiring all of the above
   into a single pipeline targeting Tauri integration.

## v0.5.0 scope (current)

Headless pipeline + script driver + tiny-skia rasterizer + cosmic-text
glyph raster + winit/softbuffer window + IPC bridge + DOM back-prop.

- `render(html, css, viewport)` -- parses HTML+CSS, builds the DOM, runs
  cascade + block layout, emits the paint-cat `DisplayList`.  Returns a
  [`Frame`] carrying the document, layout tree, and display list.
- `run_script(html, css, js, viewport)` -- as above, plus an inline JS
  step driven by `boa-cat` + `ecma-runtime-cat` + `web-api-cat`.  Script
  value lands on the returned `Frame`; layout is the pre-script one.
- `run_script_with_commands(.., &HostCommands)` -- same but installs
  the registry as the `__TAURI__` global.
- `run_script_with_backprop(.., &HostCommands)` -- additionally walks
  the post-script JS-side DOM via `web_api_cat::extract_document` and
  re-runs layout + paint so the returned `Frame`'s display list
  reflects scripted mutations.
- `HostCommands` -- registry of `NativeFn` host commands callable from
  JS via `__TAURI__.invoke('cmd', ...args)` (dispatcher) or
  `__TAURI__.cmd(...args)` (direct method).  Function-pointer-only
  (no captured state); host state threads through the boa-cat heap.
- `render_to_pixels(frame, w, h)` / `render_to_pixels_with(.., &mut TextRenderer)`
  -- tiny-skia rasterization with cosmic-text + swash glyph rendering
  for `FillText`.
- `run_window(frame, viewport)` -- opens a winit window and presents
  the rasterized frame via softbuffer; composites premultiplied RGBA
  over white before writing to softbuffer's 0RGB word format.
- `cargo run --bin demo` -- v0.4 demo (windowed render).
- `cargo run --bin demo_ipc` -- v0.5 demo (registers a host command,
  invokes from JS, mutates the DOM, back-props, shows the updated
  render in a window).

## Roadmap (committed for subsequent versions)

- v1.0.0 -- `tauri_runtime::Runtime` trait impl wiring the above into
  Tauri's expected backend shape; remaining trait methods stubbed and
  filled in over patch releases.

## Deferred to post-v1.0

- Live re-render in the open window after IPC calls or user input
  (currently the window renders the v0.5 back-propped frame once at
  startup; mutations during the event loop don't trigger a redraw).
- Async / Promise-returning host commands (needs comp-cat-rs
  scheduler integration).
- Multiple `__TAURI__` invocation flavours that don't rely on `this`
  (e.g. a globally-bound `invoke` function).

The Servo no-AI policy disqualifies upstream contribution; this stack
is the AI-built parallel.