diff --git a/README.md b/README.md
index 6bb1900..143e1e4 100644
--- a/README.md
+++ b/README.md
@@ -1,433 +1,232 @@
-# hyper
+# Hyper
-**hyper** provides native 3D hypergraph exploration for **Python scientific
-workflows** and **embedded Rust applications**. Explore explicit group memberships
-with picking, search, lasso selection, and neighborhood isolation.
+**A native 3D hypergraph viewer for Python workflows and Rust applications.**
-The Rust core provides HIF interchange, projections, and force-directed layout
-without Bevy. The typed Python package exposes HIF interchange and can launch
-the separately installed native viewer. Use scientific libraries for analysis
-and Hyper to explore their exported datasets.
+A hypergraph represents a group relationship as one edge connecting any number
+of nodes: authors on a paper, participants in an interaction, or modules in a
+dependency group. Hyper lets you inspect those memberships, find overlapping
+groups, and explore neighborhoods with search, picking, and lasso selection.
-[](docs/media/mathlib.mp4)
+[Try the viewer](#try-the-viewer) · [Use Python](#use-from-python) ·
+[Use Rust](#use-from-rust) · [Documentation](#documentation)
-**[Watch the full-resolution Mathlib demo](docs/media/mathlib.mp4)** — the complete source-file
-import graph of mathlib v4.34.1, rendered at 1080p. Includes 9,112 source files
-and 272 external-module placeholders. The video uses a settled layout;
-[reproduction instructions and live benchmarks](docs/mathlib-demo.md) explain
-the workload and rendering limits.
+[](docs/media/mathlib.mp4)
-## Choose a workflow
+[Full-resolution Mathlib demo](docs/media/mathlib.mp4) ·
+[Reproduce the demo](docs/mathlib-demo.md).
+The recording uses a settled layout; it is not a live-layout performance test.
-| Workflow | Entry point |
-|---|---|
-| Exchange scientific datasets from Python | `hyper_viz.HifDocument`: load, validate, retain metadata, and export HIF |
-| Explore a dataset in a native 3D window | `hyper` CLI or Python `hyper_viz.show()` |
-| Embed projections and layout in a Rust application | Bevy-free `hyper-viz` library and render-independent scene |
-| Embed the native viewer in a Rust host | `hyper-viz-bevy` plugin and live scene channel |
-
-Inputs include scientific **HIF**, native **`hypergraph.v1`** JSON, and supported
-legacy exports. The model is domain-agnostic: vertices, hyperedges, and memberships.
-
-## Python and scientific interoperability
+## Try the viewer
-Install the **`hypergraph-viz`** Python distribution with **CPython 3.10+**:
+Install [uv](https://docs.astral.sh/uv/getting-started/installation/), then open
+the built-in coauthorship demo:
```bash
-python -m pip install hypergraph-viz
+uvx --python 3.12 --from hypergraph-viz-viewer hyper
```
-The import name is `hyper_viz`. Wheels cover Linux x86_64, macOS arm64/x86_64,
-and Windows x86_64; a compatible wheel requires no Rust compiler. Install the native desktop viewer through the optional extra:
+No project, repository checkout, or Rust compiler is needed. `--from` selects
+the package that supplies the `hyper` executable. To open your own dataset:
```bash
-python -m pip install --upgrade "hypergraph-viz[viewer]"
+uvx --python 3.12 --from hypergraph-viz-viewer hyper dataset.hif.json
```
-Use `--upgrade` when the core package is already installed so pip selects the
-release that provides the viewer extra. The viewer needs a desktop session and
-graphics driver. Linux desktop wheels
-require glibc 2.28+; macOS targets 11.0+. Rust is needed only for source builds.
-For a Python development build from this checkout with **Rust 1.89+**:
+Requires a **desktop session and working graphics drivers**. Prebuilt viewer
+wheels support Linux x86_64 (glibc 2.28+), macOS arm64/x86_64 (11.0+), and
+Windows x86_64. The viewer opens on the machine running the command.
+See [platform requirements](docs/DESKTOP_PACKAGE.md).
-```bash
-python -m venv .venv
-. .venv/bin/activate # Windows: .venv\Scripts\activate
-python -m pip install maturin==1.9.6
-cd crates/hyper-viz-python
-maturin develop --locked
-cd ../..
-```
+Once the window opens, drag to orbit, scroll to zoom, and click a node or group
+to inspect it. Press **Space** to pause the layout, **F** to frame the camera,
+or **Cmd+F / Ctrl+F** to search. Press **Enter** in search to isolate matching
+neighborhoods. The [viewer guide](docs/VIEWER.md#controls) covers all controls.
-```python
-import hyper_viz
+## Use from Python
-document = hyper_viz.HifDocument.load("dataset.hif.json")
-document.save("roundtrip.hif.json")
-print(document.to_json())
+Create a project and install the API with its matching desktop viewer:
-# Install hypergraph-viz[viewer] first.
-viewer = hyper_viz.show(document, projection="bipartite")
-exit_code = viewer.wait() # or viewer.close() to terminate
+```bash
+uv init --python 3.12 hyper-example
+cd hyper-example
+uv add "hypergraph-viz[viewer]"
```
-Pass `executable="/path/to/hyper"` to select a viewer explicitly. Otherwise the
-launcher finds the matching companion package, then `hyper` on PATH. The launcher
-validates compatibility, starts the process asynchronously without a shell, and
-owns a temporary native snapshot that is cleaned up after exit. The Python
-extension itself does not depend on Bevy or download a viewer.
-
-Keep the `HifDocument` for scientific export: it preserves JSON values, record
-order, metadata, integer/string ID identity, isolated nodes, empty edges, and
-incidence properties. Whitespace and object-key order are not preserved.
-Validation uses a bundled, pinned schema and works offline.
-
-**Document interchange supports more semantics than the viewer.** Viewer
-conversion accepts undirected memberships and rejects directed or simplicial
-semantics, incidence direction, weights, or attributes, and duplicate identities
-or memberships. Node/edge weights round to finite `f32` for viewing; original
-numbers remain in the document. Validation and compatibility exceptions expose
-`location` and `reason`. Retained attributes are not automatically mapped to
-viewer colors or exposed by the stock inspector.
-
-See [HIF and Python integration](docs/HIF.md) for API details, generated typing,
-wheel builds, and runnable [XGI](crates/hyper-viz-python/examples/xgi_interop.py)
-and [Julia](examples/hif_interop.jl) interchange examples. Direct scientific
-object adapters, notebook embedding, layout bindings, and live updates from
-Python are deferred. The [notebook prototype roadmap](docs/NOTEBOOK_ROADMAP.md)
-sets out an anywidget canvas probe and Bevy/WASM feasibility checks.
-
-## Ecosystem fit and measured findings
-
-Hyper complements scientific analysis libraries and offers a Rust/native route
-to exploring groups. The ecosystem comparison suggests this positioning; user
-preference and adoption have not been measured.
-
-| Tool family | Fit alongside Hyper |
-|---|---|
-| XGI, HyperNetX, Hypergraphx | Scientific analysis and figures; exchange datasets through HIF where semantics are compatible |
-| HyperGodot | Dedicated interactive 2D hypergraph exploration; an alternative when a 2D workflow fits |
-| Sigma.js, Cytoscape.js, 3d-force-graph | Browser graph components; represent groups through incidence adapters and custom drawing |
-| Graphia, Gephi | General graph analysis and attribute-driven exploration; useful references for richer inspection and filtering |
-
-The [October 3, 2026 benchmark](docs/benchmarks/ecosystem-2026-10-03/README.md)
-records **445 measured attempts across 89 configurations** on one Apple M5 Pro
-Mac. Scientific figures, browser rendering, native rendering, and import/save
-workflows are separate tracks; these results do not establish an overall speed
-ranking or native-versus-browser speed advantage.
-
-| Finding | Evidence and implication |
-|---|---|
-| Dense hulls are expensive | For 1,000 nodes / 2,000 groups in frozen bipartite mode, median per-run p95 application interval rose from **9.68 ms** without hulls to **62.08 ms** with hulls; both completed 5/5 attempts. Profile geometry and update costs before adding visual effects. |
-| A successful demo is not a capacity guarantee | Full Mathlib bipartite runs completed 0/5 attempts within the 180-second budget in each frozen mode. Star mode with hulls and the default label policy completed 5/5, but frozen p95 was **219.91 ms**. Projection and settings change both work and responsiveness. |
-| Failures need investigation | **16/120 native attempts** did not complete, including a small fixture. Completed-run timings exclude those failures; their cause remains unresolved. |
-| Model fidelity must be checked | XGI preserved every tested model record. Our HNX adapter omitted isolated nodes and empty groups; HGX merged parallel groups by membership. Keep the original HIF document and validate adapter boundaries. |
-| Smooth navigation does not guarantee fast updates | Sigma completed all 35 browser attempts, but its Mathlib update command took **13.24 s**. Update strategies differed across tools; evaluate updates separately from camera motion. |
-
-Application intervals and browser callback cadence are not GPU timings or
-input-to-visible latency. Hulls approximate large groups, representations differ,
-and display refresh was not locked across browser batches. Read the
-[method and limitations](docs/benchmarks/ecosystem-2026-10-03/methodology.md),
-[raw results](docs/benchmarks/ecosystem-2026-10-03/summary.csv), and
-[rerun instructions](scripts/benchmarks/README.md) before interpreting timings.
-
-The next priorities are **attribute inspection and filtering**, **measured
-responsiveness during dense geometry updates**, and **easier installation with
-accurate documentation**. The [community and ecosystem research](docs/ecosystem-comparison.md)
-explains the evidence behind those priorities. Browser distribution, directed
-rendering, and timeline views remain outside the current viewer scope.
-
-## Docs for external readers
-
-| Doc | Contents |
-|---|---|
-| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Package boundary, host coupling policy |
-| [docs/API.md](docs/API.md) | Library API overview |
-| [docs/VIEWER.md](docs/VIEWER.md) | How to run the viewer + example scene |
-| [docs/HIF.md](docs/HIF.md) | Scientific interchange, Python API, supported semantics, and packaging |
-| [Measured ecosystem comparison](docs/benchmarks/ecosystem-2026-10-03/README.md) | Results, completion counts, raw evidence, and limitations |
-| [Community and ecosystem research](docs/ecosystem-comparison.md) | Positioning and roadmap evidence |
-| [Notebook prototype roadmap](docs/NOTEBOOK_ROADMAP.md) | Small-dataset anywidget plan and WASM feasibility checks |
-| [Python release guide](docs/PYTHON_RELEASE.md) | PyPI Trusted Publisher setup and tag-based releases |
-| [docs/PUBLIC_RELEASE_CHECKLIST.md](docs/PUBLIC_RELEASE_CHECKLIST.md) | Maintainer release-decision checklist |
-| [CONTRIBUTING.md](CONTRIBUTING.md) | Dev setup and PR norms |
-
-## Use as a library
+In an existing uv project using CPython 3.10+, run only `uv add`.
+uv manages the environment and lockfile; `uv run` needs no activation.
-```toml
-# Headless: schema, JSON, projections, 3D layout (no Bevy)
-hyper-viz = { git = "https://github.com/atomicstrata/hyper.git" }
+Save this as `explore.py`. It creates two papers with a shared author, saves a
+HIF dataset, and opens the viewer:
-# Optional native 3D window
-hyper-viz-bevy = { git = "https://github.com/atomicstrata/hyper.git" }
-```
-
-Path dep while this repo sits next to the host:
+```python
+import json
+import hyper_viz
-```toml
-hyper-viz = { path = "../hyper/crates/hyper-viz" }
-hyper-viz-bevy = { path = "../hyper/crates/hyper-viz-bevy" }
+document = hyper_viz.HifDocument.from_json(json.dumps({
+ "network-type": "undirected",
+ "nodes": [{"node": name} for name in ["alice", "bob", "carol", "dana"]],
+ "edges": [{"edge": "paper-a"}, {"edge": "paper-b"}],
+ "incidences": [
+ {"node": "alice", "edge": "paper-a"},
+ {"node": "bob", "edge": "paper-a"},
+ {"node": "carol", "edge": "paper-a"},
+ {"node": "bob", "edge": "paper-b"},
+ {"node": "dana", "edge": "paper-b"},
+ ],
+}))
+document.save("papers.hif.json")
+
+viewer = hyper_viz.show(document)
+viewer.wait() # Keep the script running until the window closes.
```
-`hyper-viz` has **no Bevy dependency**. Embed it in a WASM, SVG, or custom renderer.
-
-### Headless
-
-```rust
-use hyper_viz::prelude::*;
-
-let graph = Hypergraph::new()
- .with_title("Reactions")
- .vertex("h2o", "H2O", "molecule")
- .vertex("h2", "H2", "molecule")
- .vertex("o2", "O2", "molecule")
- .hyperedge("combust", ["h2", "o2", "h2o"], "2H2 + O2 → 2H2O");
-
-let scene = graph.project(Projection::Bipartite);
-let mut layout = ForceLayout3D::from_scene(&scene, LayoutConfig::default());
-layout.step();
+```bash
+uv run explore.py
```
-Load JSON (automatic HIF, native, or supported legacy format detection):
+For existing data, replace the constructor with
+`document = hyper_viz.HifDocument.load("dataset.hif.json")`.
+You can also open the saved example with `uv run hyper papers.hif.json`.
-```rust
-use hyper_viz::{from_json_str, load_json};
-
-let graph = load_json("fixtures/sample.json")?;
-let graph = from_json_str(r#"{"version":"hypergraph.v1","vertices":[],"hyperedges":[]}"#)?;
-```
+| Name | Purpose |
+|---|---|
+| `hypergraph-viz` | Python distribution for HIF validation and interchange |
+| `hypergraph-viz[viewer]` | Python API plus the matching `hypergraph-viz-viewer` distribution |
+| `hyper_viz` | Python import |
+| `hyper` | Desktop viewer executable |
-A quarantined one-way importer can still load a legacy host export prefix; it is
-**not** part of the public domain model (see architecture docs).
+For interchange alone, install `hypergraph-viz` and omit the `show()` and
+`wait()` calls. The API works without a desktop or Bevy. Use `uv run` for
+project scripts; `uvx` runs tools in a separate environment and the API package
+has no executable. See [uv's tool guide](https://docs.astral.sh/uv/guides/tools/).
-### Native viewer
+
+Use pip instead of uv
-```rust
-use hyper_viz_bevy::{run_from_graph, run_visualizer, run_visualizer_live};
+Requires CPython 3.10+. With Python 3.12 installed, create a virtual environment:
-run_from_graph(graph); // bipartite + blocking window
-run_visualizer(scene); // already projected
-run_visualizer_live(scene, rx, None); // host thread pushes scenes
+```bash
+python3.12 -m venv .venv
+source .venv/bin/activate
+python -m pip install --upgrade "hypergraph-viz[viewer]"
+hyper
```
-A new scene on the live channel (or a file-watch reload) rebuilds the scene
-while retaining positions by stable ID and remapping surviving selection and
-focus. Invalid watched input leaves the previous scene visible.
-
-### Embed in a Bevy app
-
-```rust
-use bevy::prelude::*;
-use hyper_viz_bevy::HyperVisualizerPlugin;
+On Windows, create it with `py -3.12 -m venv .venv` and activate it in
+PowerShell with `.venv\Scripts\Activate.ps1`. Run the example with
+`python explore.py`. For the API alone, install `hypergraph-viz`.
+If installation reports no matching distribution, check `python --version`;
+upgrading pip does not upgrade Python.
+
+
+
+## Data and scientific use
+
+The viewer reads [HIF](docs/HIF.md) (Hypergraph Interchange Format) and native
+`hypergraph.v1` JSON, detecting the format automatically. See the
+[native JSON example](docs/VIEWER.md#example-scene) and
+[projection guide](docs/VIEWER.md#quick-start) for `bipartite` (default),
+`clique`, and `star` projections, and `--watch` for file reloads.
+
+Hyper complements analysis tools such as [XGI](https://github.com/xgi-org/xgi),
+[HyperNetX](https://github.com/pnnl/HyperNetX), and
+[Hypergraphx](https://github.com/HGX-Team/hypergraphx). Export supported data to
+HIF, explore it in Hyper, and keep your analysis in the original library.
+The [XGI example](crates/hyper-viz-python/examples/xgi_interop.py) demonstrates
+export and round-trip interchange.
+
+Before using a visualization in research:
+
+- **Check viewer compatibility.** The viewer supports undirected memberships.
+ Directed or simplicial semantics and incidence properties are rejected during
+ conversion. HIF document interchange preserves richer data; keep the original
+ `HifDocument` for export. See [supported semantics](docs/HIF.md#supported-semantics).
+- **Read hulls as visual aids.** Large groups use approximate hulls. Confirm
+ membership in the selection panel; spatial proximity is a layout result.
+- **Measure your workload.** Dense hulls can be expensive. The
+ [benchmarks](docs/benchmarks/ecosystem-2026-10-03/README.md) report completion
+ counts, methods, and limits; they do not establish an overall speed ranking.
+
+Hyper is **early-stage software**. The current Python API exposes HIF
+interchange and viewer launching; Rust exposes projections and layout too.
+The viewer opens a native window, including when launched from Python.
+Notebook embedding, live Python updates, and direct scientific-library object
+adapters are not yet available; see the [notebook roadmap](docs/NOTEBOOK_ROADMAP.md)
+for browser plans.
+
+## Use from Rust
+
+The `hyper-viz` core handles JSON I/O, projections, and 3D force layout without
+Bevy or a window. Add it to your application's `Cargo.toml`:
-App::new()
- .add_plugins(DefaultPlugins)
- .add_plugins(HyperVisualizerPlugin::from_scene(scene))
- .run();
+```toml
+[dependencies]
+hyper-viz = { git = "https://github.com/atomicstrata/hyper.git" }
```
-`VisualizerConfig` sets window title and size for the standalone helpers.
-Pass `Some(shutdown_flag)` to `run_visualizer_live` so a host thread can exit
-the Bevy app.
+Build and lay out a group:
-## Crate map
+```rust
+use hyper_viz::prelude::*;
-```text
-HIF JSON → HifDocument → compatibility check
-Native JSON / Rust builder API
- → Hypergraph
- → project(Bipartite | Clique | Star)
- → HypergraphScene # render-agnostic IR
- → ForceLayout3D # Barnes-Hut octree, CPU
- → hyper-viz-bevy # native 3D window (optional)
+fn main() {
+ let graph = Hypergraph::new()
+ .vertex("alice", "Alice", "person")
+ .vertex("bob", "Bob", "person")
+ .vertex("carol", "Carol", "person")
+ .hyperedge("paper-a", ["alice", "bob", "carol"], "Paper A");
+
+ let scene = graph.project(Projection::Bipartite);
+ let mut layout = ForceLayout3D::from_scene(&scene, LayoutConfig::default());
+ layout.step();
+ println!("{} layout nodes", layout.positions.len());
+}
```
-| Crate | Role | Depend on this? |
-|---|---|---|
-| [`crates/hyper-viz`](crates/hyper-viz) | HIF, scene IR, projections, layout, hulls, JSON I/O | **Yes** — library |
-| [`crates/hyper-viz-bevy`](crates/hyper-viz-bevy) | Bevy 0.18 + egui native viewer | Only if you want the window |
-| [`crates/hyper-viz-python`](crates/hyper-viz-python) | Typed Python HIF bindings and viewer launcher; no Bevy | For Python workflows |
-| `hyper` (this binary) | CLI: load JSON or open the built-in demo | No — not a library |
+Add `hyper-viz-bevy` from the same Git repository for a standalone window or a
+plugin in an existing Bevy app. The [Rust API guide](docs/API.md) covers viewer
+embedding and live scene updates; [architecture](docs/ARCHITECTURE.md) explains
+the crate boundaries. Rust builds require **1.89+**.
-## Quick start (CLI)
+
+Run from source
```bash
-# Built-in coauthorship demo
-cargo run
-
-# Example scene
-cargo run -- fixtures/sample.json
-
-# Scientific HIF dataset (also auto-detected without --format)
-cargo run -- dataset.hif.json --format hif
-
-# Hot-reload while you edit the file
-cargo run -- --watch fixtures/sample.json
-
-# Other projections: bipartite (default), clique, star
-cargo run -- --projection clique fixtures/sample.json
-
-# Headless library example (no window)
-cargo run -p hyper-viz --example project_scene
-```
-
-Requires Rust 1.89+. The first Bevy build can take several minutes, depending
-on the machine. For regular use, build with `cargo build --release --bin hyper`
-or install with `cargo install --path . --locked`. See [docs/VIEWER.md](docs/VIEWER.md)
-for native viewer setup.
-
-## JSON schema (`hypergraph.v1`)
-
-```json
-{
- "version": "hypergraph.v1",
- "meta": { "id": "g1", "title": "Coauthorship" },
- "vertices": [
- { "id": "alice", "label": "Alice", "kind": "person" },
- { "id": "bob", "label": "Bob", "kind": "person" },
- { "id": "carol", "label": "Carol", "kind": "person" }
- ],
- "hyperedges": [
- { "id": "paper-a", "label": "Paper A", "vertices": ["alice", "bob", "carol"] }
- ]
-}
+git clone https://github.com/atomicstrata/hyper.git
+cd hyper
+cargo run --locked --release -- fixtures/sample.json
```
-| Field | Required | Notes |
-|---|---|---|
-| `vertices[].id` | yes | Stable id referenced by hyperedges |
-| `vertices[].label` | no | Falls back to `id` |
-| `vertices[].kind` | no | Free-form; used only for color |
-| `vertices[].status` | no | `active` (default), `shadowed`, `rejected`, `attention` |
-| `hyperedges[].vertices` | yes | Member vertex ids |
-| `hyperedges[].status` | no | `active` (default), `shadowed`, `rejected`, `attention` |
-| `*.attrs` | no | Opaque JSON map for the host app |
-
-## How the graph is drawn
-
-Default projection is **bipartite** (one extra-node hub per hyperedge). The
-viewer hides those hubs by default so the hyperedge is read as a **set**:
-
-| Arity | Drawing |
-|---|---|
-| 2 | Colored line between the two members |
-| 3 | Triangle hull |
-| 4 | Tetrahedron hull |
-| 5+ | Convex hull, using at most 24 sampled members |
-
-Large-group hulls are approximate: the geometry cap does not remove memberships
-from the graph, and a hull is not an exact membership boundary. Empty edges have
-no drawable geometry.
-
-Each hyperedge keeps a **stable hue** from its id (hash), so nested sets stay
-distinguishable. Nested hulls are inflated slightly to avoid z-fighting.
-Vertex color comes from `kind` (fixed palette for well-known names, hash otherwise).
-
-Uncheck **Hide extra-node hubs** in the Hyperedge hulls panel to show the
-bipartite hubs as spheres.
-
-## Controls
-
-Left button is dual-purpose. **Drag** orbits; **click** (press + release with
-almost no movement) selects. Orbiting does not change selection.
-
-| Input | Action |
-|---|---|
-| Left drag | Orbit camera (selection is kept) |
-| Left click | Select the vertex or hyperedge under the cursor |
-| Click empty space | Clear selection |
-| Shift / Cmd + click | Add to selection |
-| Scroll | Zoom (HUD windows steal scroll when the pointer is over them) |
-| Lasso (UI panel) | Polygon select (disables orbit while on) |
-| Space | Toggle force layout |
-| A | Isolate `attention` status: hide other hulls, boost remaining fills, label those nodes |
-| F | Frame camera (ignored while the find bar is focused) |
-| ⌘F / Ctrl+F | Focus the find bar |
-| ⌃⌘F | Isolate the selected incident neighborhood (toggle) |
-| / | Focus the find bar (when not typing) |
-| Enter (in find) | Isolate the match neighborhood and frame the camera |
-| Esc | Clear the find query, or clear focus |
-| Clear selection | Button in the Selection window |
-
-The find bar at the bottom highlights matches as you type (BM25 + Jaro–Winkler
-on label, id, kind, and status). Hits use the existing selection glow and the
-**Selection** window. While focus is on, each new query also re-isolates the
-match neighborhood and reframes the camera.
-
-The **Selection** window lists selected hyperedges and vertices with kind,
-label, status, and a location taken from the id (`repo:…`, `wt:…`, `pr:…`).
-Click a row to narrow the selection to that node. Pointer over any HUD window
-does not orbit or zoom the scene.
-
-Picking hits vertices, hull triangles, and arity-2 segments. Hidden hubs are
-not pickable.
-
-## Hover vs selected
-
-Both states keep the object's own hue. They do **not** swap to a highlight
-color.
-
-| State | Look |
-|---|---|
-| Hover | Nodes grow slightly; hull/line wires brighten |
-| Selected | Same hue, higher saturation and glow |
-| Hover + selected | Selected treatment wins (still a bit larger) |
-
-## Projections
-
-- **Bipartite** (default): one hub node per hyperedge + incidence links (Ouvrard extra-node).
-- **CliqueExpansion** (`--projection clique`): all pairs within each hyperedge (no hubs).
-- **StarCentroid** (`--projection star`): centroid attraction, no hub nodes.
-
-## Tests
+The native viewer requires a desktop graphics environment; the first build can
+take several minutes. To run the core example without a window:
```bash
-cargo test -p hyper-viz
-cargo test -p hyper-viz-bevy --lib
-cargo clippy -p hyper-viz -p hyper-viz-bevy --all-targets -- -D warnings
+cargo run --locked -p hyper-viz --example project_scene
```
-## Observability
+See the [viewer guide](docs/VIEWER.md) for more commands, and the
+[Python build instructions](docs/HIF.md#python-installation) for extension development.
-JSON-friendly `tracing` logs on scene init, file-watch reload, and live-channel
-reload (`nodes`, `hyperedges`, `graph_id`). Set `RUST_LOG=hyper_viz_bevy=info`
-(see [`.env.example`](.env.example)).
+
-No secrets. The viewer restores HUD, navigation (lasso), camera pose,
-selection, focus neighborhood, and find query from a `hyperviz.session.v1`
-JSON blob:
+## Documentation
-| Host | Where |
+| Guide | What you'll find |
|---|---|
-| Desktop | `~/Library/Application Support/hyper-viz/session.json` (macOS), `%APPDATA%/hyper-viz/session.json` (Windows), `$XDG_CONFIG_HOME/hyper-viz/session.json` (Linux) |
-| Browser (wasm) | `localStorage["hyperviz.session.v1"]` |
-
-Override the file with `HYPER_VIZ_SESSION=/path/to/session.json`. Set
-`HYPER_VIZ_SESSION=off` to disable. Prefs (including navigation) are global;
-camera / selection / isolate are keyed by graph id. Layout positions are not
-stored.
-
-## License
-
-Dual-licensed under **MIT OR Apache-2.0**. See [LICENSE](LICENSE),
-[LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and
-[NOTICE](NOTICE).
+| [Viewer](docs/VIEWER.md) | Setup, controls, projections, display settings, and saved sessions |
+| [Python and HIF](docs/HIF.md) | Interchange, Python API, scientific semantics, and source builds |
+| [Rust API](docs/API.md) | Build graphs, run layouts, and embed the viewer |
+| [Architecture](docs/ARCHITECTURE.md) | Crate responsibilities and integration boundaries |
+| [Benchmarks](docs/benchmarks/ecosystem-2026-10-03/README.md) | Measured results, methods, and limitations |
-## Directory layout
+For questions or bug reports, [open an issue](https://github.com/atomicstrata/hyper/issues).
+To contribute, start with [CONTRIBUTING.md](CONTRIBUTING.md) for development
+setup, checks, and pull request guidelines.
-```text
-crates/hyper-viz/ # library other projects depend on
-crates/hyper-viz-bevy/ # optional Bevy renderer
-crates/hyper-viz-python/ # Python extension, typed package, and launcher
-scripts/benchmarks/ # opt-in ecosystem benchmark harness
-docs/ # API, interoperability, ecosystem research, benchmark evidence
-fixtures/sample.json # coauthorship demo
-src/main.rs # CLI
-```
+If you use Hyper in research, record the package version or Git commit,
+dataset, projection, and viewer settings so others can reproduce the view.
-## Non-goals
+## License
-- PAOH timeline view
-- WASM / browser serve (session JSON is ready for `localStorage`)
-- Euler-style set diagrams (convex-hull member shells only)
-- Bundling any proprietary memory engine
+Dual-licensed under [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE).
+See [NOTICE](NOTICE) for third-party notices.
diff --git a/crates/hyper-viz-python/README.md b/crates/hyper-viz-python/README.md
index fab45ad..1ca2292 100644
--- a/crates/hyper-viz-python/README.md
+++ b/crates/hyper-viz-python/README.md
@@ -7,10 +7,21 @@ The package includes generated extension type stubs, typed Python wrappers, and
## Installation
+With [uv](https://docs.astral.sh/uv/getting-started/installation/), create a project
+with a supported Python version and add the package:
+
```sh
-python -m pip install hypergraph-viz
+uv init --python 3.12 hyper-example
+cd hyper-example
+uv add hypergraph-viz
```
+uv manages `.venv` and `uv.lock`, and can download Python 3.12 if needed.
+Save your Python code as `explore.py` and run it with `uv run explore.py`.
+In an existing uv project, run only `uv add hypergraph-viz`.
+Alternatively, use `python -m pip install hypergraph-viz` in a Python 3.10+
+virtual environment. Upgrading pip does not upgrade Python.
+
Requires standard CPython 3.10 or newer. Platform wheels cover Linux x86_64,
macOS arm64/x86_64, and Windows x86_64; installing a compatible wheel requires
no Rust compiler. Building from source requires Rust 1.89 or newer and maturin.
@@ -40,12 +51,30 @@ not preserved.
## Launch the native viewer
-Install the matching prebuilt desktop viewer with the optional extra:
+From your uv project, install the matching prebuilt desktop viewer:
```sh
-python -m pip install --upgrade "hypergraph-viz[viewer]"
+uv add "hypergraph-viz[viewer]"
+uv run hyper
```
+`uv run hyper` opens the built-in demo; use
+`uv run hyper dataset.hif.json --projection bipartite` for your own dataset.
+For pip, use `python -m pip install --upgrade "hypergraph-viz[viewer]"`.
+
+To launch only the desktop viewer without creating a project:
+
+```sh
+uvx --python 3.12 --from hypergraph-viz-viewer hyper
+# Open your dataset:
+uvx --python 3.12 --from hypergraph-viz-viewer hyper dataset.hif.json
+```
+
+`--from` selects the distribution that supplies the `hyper` executable.
+`hypergraph-viz` supplies the Python API and has no executable of its own;
+use `uv add "hypergraph-viz[viewer]"` for Python integration in a project.
+See [uv's tool guide](https://docs.astral.sh/uv/guides/tools/).
+
Wheels cover Linux x86_64, macOS arm64/x86_64, and Windows x86_64. No Rust
compiler or repository checkout is needed on these platforms. A desktop session
and graphics driver are required. Linux viewer wheels require glibc 2.28+;
@@ -53,9 +82,13 @@ macOS wheels target 11.0+. Notebook kernels on remote machines cannot open a
window on your laptop; see the
[notebook prototype roadmap](https://github.com/atomicstrata/hyper/blob/python-v0.1.2/docs/NOTEBOOK_ROADMAP.md).
-Then launch it from Python:
+Save the following as `explore.py` alongside `dataset.hif.json`, then run
+`uv run explore.py`:
```python
+import hyper_viz
+
+document = hyper_viz.HifDocument.load("dataset.hif.json")
viewer = hyper_viz.show(document, projection="bipartite")
exit_code = viewer.wait()
# Or viewer.close() to terminate and clean up.
diff --git a/docs/DESKTOP_PACKAGE.md b/docs/DESKTOP_PACKAGE.md
index 15bad5b..941543d 100644
--- a/docs/DESKTOP_PACKAGE.md
+++ b/docs/DESKTOP_PACKAGE.md
@@ -1,12 +1,39 @@
# Hyper desktop viewer
Prebuilt native viewer for [hypergraph-viz](https://pypi.org/project/hypergraph-viz/).
-Install the Python API and matching viewer together:
+Launch the built-in demo with [uv](https://docs.astral.sh/uv/getting-started/installation/):
```sh
-python -m pip install --upgrade "hypergraph-viz[viewer]"
+uvx --python 3.12 --from hypergraph-viz-viewer hyper
```
+Open your own dataset:
+
+```sh
+uvx --python 3.12 --from hypergraph-viz-viewer hyper dataset.hif.json
+```
+
+`--from` selects this package, which supplies the `hyper` executable.
+See [uv's tool guide](https://docs.astral.sh/uv/guides/tools/).
+
+For Python integration, install the API and matching viewer in a project:
+
+```sh
+uv init --python 3.12 hyper-example
+cd hyper-example
+uv add "hypergraph-viz[viewer]"
+```
+
+In an existing uv project using Python 3.10+, run only `uv add`.
+Save the Python example below as `explore.py` alongside `dataset.hif.json`,
+then run `uv run explore.py`. No environment activation is needed.
+uv can download Python 3.12 when necessary.
+`hypergraph-viz` provides the Python API and has no executable of its own;
+`uvx hypergraph-viz` cannot launch the viewer.
+
+For pip, use `python -m pip install --upgrade "hypergraph-viz[viewer]"` in a
+Python 3.10+ virtual environment.
+
```python
import hyper_viz
diff --git a/docs/VIEWER.md b/docs/VIEWER.md
index 92c59ab..e12ab45 100644
--- a/docs/VIEWER.md
+++ b/docs/VIEWER.md
@@ -1,7 +1,31 @@
# Running the native viewer
-The Bevy viewer is **native window only** (not a web app). First compile is
-slow (~40s cold); subsequent runs are fast.
+The Bevy viewer opens a native desktop window. It requires a desktop session
+and working graphics drivers.
+
+## Install
+
+With [uv](https://docs.astral.sh/uv/getting-started/installation/), open the
+prebuilt viewer without creating a project:
+
+```bash
+uvx --python 3.12 --from hypergraph-viz-viewer hyper
+uvx --python 3.12 --from hypergraph-viz-viewer hyper dataset.hif.json
+```
+
+Omitting the file opens the built-in coauthorship demo. `--from` selects the
+distribution containing the `hyper` executable. For Python integration, use
+`uv add "hypergraph-viz[viewer]"` in a CPython 3.10+ project and run scripts
+with `uv run`; see the [complete Python example](../README.md#use-from-python).
+
+Alternatively, run `python -m pip install --upgrade "hypergraph-viz[viewer]"`
+in a CPython 3.10+ virtual environment, then run
+`hyper`. See [platform requirements](DESKTOP_PACKAGE.md) for supported wheels.
+
+For a source build, use Rust 1.89+ and run the commands below from this checkout.
+The first Bevy build can take several minutes. For regular use, build with
+`cargo build --release --bin hyper` or install with
+`cargo install --path . --locked`.
## Quick start
@@ -14,6 +38,9 @@ cargo run
# Example scene (fixtures/sample.json)
cargo run -- fixtures/sample.json
+# Scientific HIF dataset (also detected without --format)
+cargo run -- dataset.hif.json --format hif
+
# Hot-reload while editing JSON
cargo run -- --watch fixtures/sample.json
@@ -24,6 +51,18 @@ cargo run -- --projection clique fixtures/sample.json
cargo run -p hyper-viz-bevy --example view -- fixtures/sample.json
```
+For prebuilt wheels, replace `cargo run --` with
+`uvx --python 3.12 --from hypergraph-viz-viewer hyper`, `uv run hyper` in a
+project with the viewer extra, or `hyper` in an activated pip environment.
+`--watch` reloads the graph while retaining positions by stable ID and remapping
+surviving selection and focus. Invalid input leaves the previous scene visible.
+
+The projections are:
+
+- **Bipartite** (default): one hub per hyperedge, connected to its members.
+- **Clique**: links between every pair of members within each hyperedge.
+- **Star**: attraction toward each hyperedge's centroid, without hub nodes.
+
Headless (no window) library smoke:
```bash
@@ -50,7 +89,9 @@ Minimal shape:
"version": "hypergraph.v1",
"meta": { "id": "g1", "title": "Coauthorship" },
"vertices": [
- { "id": "alice", "label": "Alice", "kind": "person" }
+ { "id": "alice", "label": "Alice", "kind": "person" },
+ { "id": "bob", "label": "Bob", "kind": "person" },
+ { "id": "carol", "label": "Carol", "kind": "person" }
],
"hyperedges": [
{ "id": "paper-a", "label": "Paper A", "vertices": ["alice", "bob", "carol"] }
@@ -58,22 +99,93 @@ Minimal shape:
}
```
-## Controls (summary)
+| Field | Required | Notes |
+|---|---|---|
+| `vertices[].id` | yes | Stable ID referenced by hyperedges |
+| `vertices[].label` | no | Falls back to `id` |
+| `vertices[].kind` | no | Free-form; used for color |
+| `vertices[].status` | no | `active` (default), `shadowed`, `rejected`, `attention` |
+| `hyperedges[].id` | yes | Stable ID for the group |
+| `hyperedges[].vertices` | yes | Member vertex IDs |
+| `hyperedges[].status` | no | `active` (default), `shadowed`, `rejected`, `attention` |
+| `*.attrs` | no | Opaque JSON map for the host app |
+
+For scientific interchange and viewer compatibility, see the
+[HIF guide](HIF.md#supported-semantics).
+
+## Controls
+
+Left drag orbits; a click with almost no movement selects. Orbiting keeps the
+current selection. Pointer input over a UI panel does not orbit or zoom the scene.
| Input | Action |
|---|---|
| Left drag | Orbit (keeps selection) |
| Left click | Select vertex / hyperedge |
| Click empty | Clear selection |
+| Shift / Cmd + click | Add to selection |
| Scroll | Zoom |
+| Lasso (UI panel) | Polygon selection; disables orbit while enabled |
| Space | Toggle force layout |
+| A | Isolate `attention` status: hide other hulls, boost remaining fills, label those nodes |
+| F | Frame the camera (ignored while typing in search) |
| ⌘F / Ctrl+F | Find bar |
+| ⌃⌘F | Toggle isolation of the selected incident neighborhood |
+| / | Find bar (when not typing) |
+| Enter (in find) | Isolate the match neighborhood and frame the camera |
| Esc | Clear find / focus |
+| Clear selection | Button in the Selection window |
+
+The find bar highlights matches as you type. Search covers label, ID, kind, and
+status using BM25 and Jaro–Winkler matching. While neighborhood focus is active,
+each new query also isolates the matches and reframes the camera.
+
+The **Selection** window lists selected hyperedges and vertices with kind,
+label, status, and a location taken from the ID (`repo:…`, `wt:…`, `pr:…`).
+Click a row to narrow the selection to that node. Picking hits vertices, hull
+triangles, and two-member segments. Hidden hubs are not pickable.
+
+## Display settings
+
+The default bipartite projection adds a hub for each hyperedge. Hubs are hidden
+by default so groups appear as sets. Uncheck **Hide extra-node hubs** in the
+**Hyperedge hulls** panel to show them as spheres.
+
+| Group size | Drawing |
+|---|---|
+| 2 | Colored line between members |
+| 3 | Triangle hull |
+| 4 | Tetrahedron hull |
+| 5+ | Convex hull using at most 24 sampled members |
-Full interaction notes live in the [root README](../README.md).
+Large-group hulls are approximate. The geometry cap does not remove memberships,
+and a hull is not an exact membership boundary. Empty edges have no drawable
+geometry.
+
+Each hyperedge has a stable hue derived from its ID. Nested hulls are inflated
+slightly to avoid overlapping surfaces flickering. Vertex color comes from
+`kind`, using a fixed palette for known names and a hash otherwise.
+
+Hover and selection keep the object's hue:
+
+| State | Appearance |
+|---|---|
+| Hover | Nodes grow slightly; hull and line wires brighten |
+| Selected | Higher saturation and glow |
+| Hover + selected | Selection treatment wins; nodes still grow slightly |
## Session persistence
-Desktop writes `hyperviz.session.v1` under the OS config dir
-(`hyper-viz/session.json`). Override with `HYPER_VIZ_SESSION=/path` or disable
-with `HYPER_VIZ_SESSION=off`.
+The viewer restores UI preferences, navigation (including lasso), camera pose,
+selection, neighborhood focus, and the find query from a `hyperviz.session.v1`
+JSON file.
+
+| Platform | Default file |
+|---|---|
+| macOS | `~/Library/Application Support/hyper-viz/session.json` |
+| Windows | `%APPDATA%/hyper-viz/session.json` |
+| Linux | `$XDG_CONFIG_HOME/hyper-viz/session.json`, or `~/.config/hyper-viz/session.json` when unset |
+
+Override the file with `HYPER_VIZ_SESSION=/path/to/session.json`, or set
+`HYPER_VIZ_SESSION=off` to disable persistence. Preferences are global; camera,
+selection, and focus are keyed by graph ID. Layout positions are not stored.
diff --git a/docs/readme-research.md b/docs/readme-research.md
new file mode 100644
index 0000000..927a7a8
--- /dev/null
+++ b/docs/readme-research.md
@@ -0,0 +1,134 @@
+# README communication research
+
+Reviewed October 5, 2026 (America/Lima), while consolidating documentation PRs
+[#10](https://github.com/atomicstrata/hyper/pull/10) and
+[#11](https://github.com/atomicstrata/hyper/pull/11).
+
+## Purpose and method
+
+The README must help a scientist explore a supported dataset and help a developer
+integrate Hyper without first learning the entire implementation. Success means a
+reader can identify the tool’s purpose, choose the correct package, run a complete
+example, and understand the representation’s limits.
+
+This review examined ten primary-source READMEs: four hypergraph projects, three
+graph visualization projects, and three scientific or spatial visualization
+projects with native viewers or multiple language interfaces. The latter are
+communication references, not claims of feature equivalence. Sources below are
+pinned to the most recent commit modifying each README on its default branch at
+the time of retrieval. Their linked assets and tutorials were inspected as README
+entry points; competitor installation instructions and applications were not run.
+
+The review considered six questions: what problem the introduction communicates;
+how a reader chooses a workflow; how installation handles prerequisites and
+package names; whether the first example supplies its data and execution context;
+how semantics, limitations, and research use are explained; and where API,
+contributor, and maintenance details live. Observations describe the documents;
+the recommendations are editorial judgments. No user study or conversion-rate
+measurement was performed, and this is not a performance comparison.
+
+## Project-by-project findings
+
+| Primary source | Comparison role | Observed communication | Applied lesson for Hyper |
+|---|---|---|---|
+| [xgi-org/xgi](https://github.com/xgi-org/xgi/blob/b8164bca1ce6b8b5c613223c33365dc61e432f28/README.md) | Scientific hypergraphs | Defines the model and supported operations, links a gallery and datasets, and provides citation and contribution routes. Installation leads to external user guides rather than an inline first example. | Explain group relationships and ecosystem fit; retain visible scientific and contributor routes. Supply a complete first example in Hyper itself. |
+| [pnnl/HyperNetX](https://github.com/pnnl/HyperNetX/blob/17534c3806a3666e421881b3fb314e787024a6b5/README.md) | Scientific hypergraphs | Connects HIF to other libraries and provides Colab tutorials. Release history, maintainer credits, environment choices, and developer tooling occupy substantial space before and after installation. | Explain HIF interoperability, but keep release history, build variants, and long analysis outside the landing README. |
+| [HGX-Team/hypergraphx](https://github.com/HGX-Team/hypergraphx/blob/a71d3c2c2f97fc8d9e7492a633a87668d6b4ab67/README.md) | Scientific hypergraphs | Introduces group interactions with familiar domains, then installs and constructs a small graph before showing metadata and analysis. Separate tutorials and citation guidance support deeper use. | Use a concrete coauthorship example before API details. Keep advanced semantics in the HIF guide rather than copying HGX’s analysis scope. |
+| [pnnl/hypernetx-widget](https://github.com/pnnl/hypernetx-widget/blob/11a9f59551e131928367fee092d8bbbb80bde6b0/README.md) | Interactive hypergraphs | Starts with a browser demo, then a notebook example that defines its own graph and shows the resulting widget. Explains selection and alternate representations with screenshots and interactions. | Offer an immediate demo and explicit first interactions. State that Hyper opens a native window; put the full interaction reference in the viewer guide. |
+| [graphia-app/graphia](https://github.com/graphia-app/graphia/blob/d7c339c5cc94575edfad39cdfb49b84ea86e1f10/README.md) | Desktop graph exploration | Pairs a short purpose statement with a video and domain-specific applications. Links a user guide and separates help from building, but gives source-build commands rather than a short packaged launch walkthrough. | Keep the visual demo and recognizable use cases. Make the packaged viewer command directly available, with source builds later. |
+| [vasturiano/3d-force-graph](https://github.com/vasturiano/3d-force-graph/blob/2a901f53eb9b427635c74f20bfdf0cfc4b3812bc/README.md) | Browser 3D graph component | Shows a linked visual preview and a large gallery whose demos link to source. Follows a short integration sketch with extensive API tables. The sketch uses placeholder container and data arguments. | Keep a reproducible visual example and concise developer entry point. Use defined inputs and move exhaustive API material into dedicated guides. |
+| [jacomyal/sigma.js](https://github.com/jacomyal/sigma.js/blob/a923c1676c4f035a6f1b98a465f0d4bd39df6b34/README.md) | Browser graph component | Names both required packages, then shows imports, nodes, an edge, and renderer creation. Separates project use from local development and links documentation, Storybook, and a demo. | Make package roles explicit and show a small constructed dataset. Separate consuming the library from contributing or building it. |
+| [nmwsharp/polyscope](https://github.com/nmwsharp/polyscope/blob/63c09627e8252050e7be50e9de9cdeb40cc42799/README.md) | Scientific native 3D viewer | Explains its structure/quantity model and integration philosophy, then gives parallel C++ and Python examples and citation guidance. Example arrays are supplied by the reader. | Give Python and Rust distinct routes and explain the core/viewer boundary. Improve first-run completeness by constructing all example data. |
+| [napari/napari](https://github.com/napari/napari/blob/bb3fdfda8567fc84284b1b721553cf1e6bf1da3c/README.md) | Scientific Python desktop viewer | Offers a uvx trial before environment installation, tells users how to open sample data, and distinguishes interactive-shell use from scripts that need an event loop. Includes roadmap, citation, and help routes. | Lead with a standalone uvx demo and retain a project workflow. Include viewer.wait() in the Python script and state where the window opens. |
+| [rerun-io/rerun](https://github.com/rerun-io/rerun/blob/44bb79b9c65357f3ee57c2fdf616281243269dfc/README.md) | Rust and Python visualization SDK | Connects purpose to concrete workflows, separates language onboarding from viewer installation, and documents active development, limitations, and research citation. Its short code taste assumes pre-existing arrays. | Explain SDK/viewer installation and evolving scope. Preserve measured limitations without reproducing a benchmark report or assuming missing example data. |
+
+## What the comparison changes
+
+### One entry point per reader task
+
+A single README has three real entry points here: try the desktop viewer, use
+Python with a dataset, and integrate the Rust core. These are tasks rather than
+skill levels. A scientist may write Rust and a developer may only need the CLI.
+Top-level jump links let either reader choose immediately. The viewer trial comes
+first because it demonstrates the project without a checkout or a new Python
+project. The documented Python 3.12 command selects a supported interpreter rather
+than relying on whichever system Python happens to be installed.
+
+The alternative of leading with Cargo and the architecture diagram makes every
+new user perform developer setup. Leading with a generic pip command leaves the
+package/command mismatch unresolved. Leading with a comparison or benchmark table
+asks the reader to evaluate implementation details before they have seen a group.
+Those materials remain available in the existing guides.
+
+### Complete examples and visible results
+
+The Python example defines four authors, two papers, and every incidence. The
+shared author makes overlapping membership concrete, while saving HIF connects the
+example to a real file workflow. It ends with show() and wait(), explains the
+expected window, and supplies uv run explore.py. Readers need no unpublished
+fixture or scientific-library installation. Existing data replaces the constructor
+with HifDocument.load().
+
+The Rust example is a complete main() with a small group, projection, layout step,
+and printed node count. The dependency snippet uses the repository because the
+Rust crates are not published. The core has no window dependency; optional Bevy
+integration has a separate explanation and API link. Source-build instructions
+remain available in an expandable section.
+
+### Scientific trust depends on boundaries
+
+A compelling screenshot cannot establish faithful interchange, exact hull
+membership, analysis capabilities, or interactive performance. Hyper’s opening
+explains membership exploration and later places three concise boundaries beside
+the data workflow: viewer conversion accepts undirected memberships; large hulls
+are approximate; and workload-specific benchmark results need their methods and
+completion counts. Full scientific values belong to the original HifDocument.
+The HIF guide remains authoritative for incidence properties, identity mapping,
+precision changes, and metadata interpretation.
+
+The README positions Hyper alongside scientific analysis libraries through
+supported HIF exchange. It does not imply that their in-memory objects can be
+passed directly to show(). It distinguishes the Python API’s current interchange
+and launcher surface from Rust’s layout API, and states that the native window is
+not a notebook widget. The package metadata identifies the software as alpha, so
+the README calls it early-stage without promising a stability policy.
+
+Scientific projects often provide publication citations or archived software
+identifiers. Hyper has no CITATION.cff or verified project DOI in this checkout.
+Rather than invent one, the README asks researchers to record the version or
+commit, dataset, projection, and settings. A formal citation policy can be added
+when maintainers establish one.
+
+### Link depth to a maintained guide
+
+PR #10’s useful change is progressive detail: essential actions on the landing
+page, complete controls, schema fields, drawing behavior, and session persistence
+in docs/VIEWER.md. PR #11’s useful change is installation reliability: the viewer
+distribution for uvx, the matching viewer extra for Python projects, supported
+Python, and uv run for scripts. The consolidation keeps both, then aligns the
+viewer and package guides so navigation never returns a reader to conflicting
+launch instructions.
+
+A compact package-name table resolves distribution, import, extra, and executable
+roles. pip remains available for existing Python environments. Contributor checks
+stay in CONTRIBUTING.md, and launcher internals stay in the Python/HIF guide.
+The README retains one visual demo, with descriptive alternate text and a caption
+that identifies the settled layout. Competitor marketing, capacity claims, and
+visual assets were not copied.
+
+## Consolidation and verification criteria
+
+| Requirement | Result to review |
+|---|---|
+| Keep #10’s simpler entry page | Purpose, demo, three reader paths, short explanations, and guide links |
+| Preserve #10’s viewer reference | Complete controls, drawing rules, schema example, and sessions in docs/VIEWER.md |
+| Keep #11’s correct uv launch | uvx selects hypergraph-viz-viewer; Python projects install hypergraph-viz[viewer] |
+| Preserve #11’s complete Python path | Project creation, example data, saved HIF, viewer lifetime, and script command |
+| Align companion documentation | Python package and desktop package guides retain uv and pip workflows |
+| Support Rust integration | Git dependency, compilable headless example, optional viewer boundary, source path |
+| Support scientific interpretation | Interchange/viewing distinction, approximate hulls, benchmark link, reproducibility note |
+| Avoid regressions in navigation | Check local paths, section anchors, code fences, and retained documentation |
+| Check executable examples | Run published CLI help/version, Python construction/save/reload/conversion, and Rust example |
+
+This document records the editorial evidence. The consolidated PR records the
+actual verification results, including any checks that did not exercise a GUI.