From 496a1fb3d1abda3fea9d21901e12458c88889dcb Mon Sep 17 00:00:00 2001 From: Noah Date: Thu, 18 Jun 2026 19:51:50 -0700 Subject: [PATCH 1/2] docs: full documentation audit + remediation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit all of docs/ (564 files) + CLAUDE.md/README.md for accuracy, quality, and spec alignment, and fix every finding. Documentation-only — no code changed (verified: only docs/, CLAUDE.md, README.md, .claude/skills touched). The docs lagged the code: an adversarial code-verification pass over every flagged spec<->code mismatch confirmed ZERO code defects. The dominant failure was stale "deferred/draft" status left in place after work shipped. - Catalog: new ### Render area; 11 missing plan entries added (render r1/r2/r6, the GPU-verify campaign, editing e1-e6, follow-ups.md); dead reference-designs link + stray list break removed; "Where to start" expanded to 5; broken prior-art cross-refs repointed. - Statuses flipped to reality across specs/plans: render-pipeline spec [draft]->[active], docs-org [draft]->[landed], R8 [partial]->[superseded], R8b/R9 ->[landed], T9 proposed->landed, editing e1-e6, the 5 render sub-designs, open-questions, text README; the non-standard [partial] is gone everywhere. - Misleading "deferred/future" claims rewritten to landed reality across the layout/render/text/verification specs and follow-ups.md (the layout pipeline now lists steps 0-9 + text; TaffyTree; the Transform bridge; node_skip_reason; the GPU-orchestration framing; matrix_goldens). - Authored the 2 missing prior-art READMEs (bevy-a11y, bevy-feathers); swept 51 files of fictional /home/user/buiy paths to repo-relative; converted drifted :NNNN citations to symbol-only. - Added 3 audit docs: the findings report, this remediation plan (executed), and a code-side findings report (stale in-code comments + dead-legacy extract path — open for a separate session; no functional code defects). Decision: the 5 dated render-pipeline children were NOT renamed (renaming would break path references in 5 code files); they are blessed as a documented exception in the docs-organization spec + organizing-buiy-docs skill instead, keeping this change documentation-only. Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/skills/organizing-buiy-docs/SKILL.md | 4 +- CLAUDE.md | 6 + README.md | 4 +- docs/README.md | 51 +++++-- ...26-06-03-buiy-render-r1-component-model.md | 3 + .../plans/2026-06-03-buiy-render-r10-atlas.md | 3 + ...y-render-r11-color-forced-colors-verify.md | 3 + .../2026-06-03-buiy-render-r2-clip-rects.md | 3 + ...6-06-03-buiy-render-r3-transform-bridge.md | 3 + ...2026-06-03-buiy-render-r4-effect-groups.md | 3 + .../2026-06-03-buiy-render-r5-extract.md | 3 + ...26-06-03-buiy-render-r6-prepare-buffers.md | 3 + ...-06-03-buiy-render-r7-pipelines-shaders.md | 3 + ...6-03-buiy-render-r8-paint-clip-toplayer.md | 5 + ...-06-03-buiy-render-r9-effect-compositor.md | 20 ++- .../2026-06-07-buiy-render-r8b-node-draw.md | 2 +- .../2026-06-07-render-gpu-verify-campaign.md | 10 ++ ...06-11-buiy-text-t9-verification-closure.md | 4 +- ...26-06-13-buiy-text-editing-e1-substrate.md | 2 +- .../2026-06-13-buiy-text-editing-e2-input.md | 3 +- ...13-buiy-text-editing-e3-caret-selection.md | 2 +- ...-13-buiy-text-editing-e4-clipboard-undo.md | 3 +- .../2026-06-13-buiy-text-editing-e5-ime.md | 3 +- ...ext-editing-e6-lifecycle-widget-closure.md | 5 +- .../2026-06-18-docs-audit-remediation.md | 110 +++++++++++++++ docs/plans/follow-ups.md | 48 ++++--- docs/prior-art/accesskit/api.md | 4 +- docs/prior-art/accesskit/architecture.md | 6 +- docs/prior-art/accesskit/capabilities.md | 2 +- docs/prior-art/accesskit/critiques.md | 8 +- docs/prior-art/accesskit/ecosystem.md | 4 +- docs/prior-art/accesskit/governance.md | 4 +- docs/prior-art/accesskit/history.md | 2 +- docs/prior-art/accesskit/integration.md | 6 +- docs/prior-art/accesskit/platform-adapters.md | 2 +- docs/prior-art/accesskit/tree-model.md | 2 +- docs/prior-art/bevy-a11y/README.md | 80 +++++++++++ docs/prior-art/bevy-a11y/api.md | 14 +- docs/prior-art/bevy-a11y/architecture.md | 8 +- docs/prior-art/bevy-a11y/coexistence.md | 14 +- docs/prior-art/bevy-a11y/comparisons.md | 4 +- .../bevy-a11y/component-model-incident.md | 22 +-- docs/prior-art/bevy-a11y/focus-model.md | 14 +- docs/prior-art/bevy-egui/critiques.md | 4 +- .../bevy-egui/immediate-mode-paradigm.md | 2 +- docs/prior-art/bevy-egui/lessons.md | 2 +- docs/prior-art/bevy-egui/open-problems.md | 4 +- docs/prior-art/bevy-feathers/README.md | 87 ++++++++++++ docs/prior-art/bevy-flair/architecture.md | 2 +- docs/prior-art/bevy-ui/README.md | 2 +- docs/prior-art/bevy-ui/architecture.md | 2 +- docs/prior-art/bevy-ui/component-model.md | 2 +- docs/prior-art/bevy-ui/lessons.md | 4 +- docs/prior-art/bevy-ui/styling.md | 2 +- docs/prior-art/cosmic-text/README.md | 8 +- docs/prior-art/cosmic-text/capabilities.md | 2 +- docs/prior-art/cosmic-text/critiques.md | 2 +- docs/prior-art/cosmic-text/editing.md | 2 +- docs/prior-art/cosmic-text/integration.md | 2 +- docs/prior-art/cosmic-text/lessons.md | 2 +- docs/prior-art/egui/lessons.md | 2 +- docs/prior-art/egui/styling-and-theming.md | 2 +- docs/prior-art/godot-control/README.md | 10 +- docs/prior-art/godot-control/accessibility.md | 4 +- .../distribution-and-governance.md | 2 +- .../ecosystem-and-comparisons.md | 2 +- docs/prior-art/godot-control/lessons.md | 10 +- docs/prior-art/gpui/README.md | 10 +- docs/prior-art/gpui/accessibility.md | 4 +- .../gpui/critiques-and-open-problems.md | 2 +- .../gpui/ecosystem-and-comparisons.md | 10 +- docs/prior-art/gpui/element-tree.md | 4 +- docs/prior-art/gpui/lessons.md | 12 +- docs/prior-art/gpui/text-and-input.md | 2 +- docs/prior-art/iced/README.md | 4 +- docs/prior-art/iced/critiques.md | 4 +- docs/prior-art/iced/governance.md | 2 +- docs/prior-art/iced/history.md | 4 +- docs/prior-art/iced/lessons.md | 2 +- docs/prior-art/iced/open-problems.md | 10 +- docs/prior-art/kayak-ui/README.md | 2 +- docs/prior-art/sickle-ui/distribution.md | 2 +- docs/prior-art/slint/accessibility.md | 6 +- docs/prior-art/slint/architecture.md | 4 +- docs/prior-art/slint/dsl-language.md | 2 +- docs/prior-art/unity-ui/README.md | 2 +- .../unity-ui/critiques-and-open-problems.md | 2 +- .../unity-ui/uxml-uss-web-parallels.md | 2 +- docs/prior-art/unreal-slate-umg/README.md | 4 +- docs/prior-art/wgpu-testing/README.md | 4 - docs/prior-art/woodpecker-ui/api.md | 2 +- docs/prior-art/woodpecker-ui/architecture.md | 4 +- docs/prior-art/woodpecker-ui/critiques.md | 2 +- docs/prior-art/woodpecker-ui/integration.md | 2 +- docs/prior-art/wpt-reftests/README.md | 4 - docs/reports/2026-06-18-docs-audit.md | 126 ++++++++++++++++++ docs/reports/2026-06-18-spec-code-findings.md | 42 ++++++ .../2026-05-07-buiy-foundation/README.md | 14 +- .../accessibility.md | 2 +- .../architecture.md | 6 +- .../2026-05-07-docs-organization-design.md | 14 +- .../2026-05-08-buiy-layout-design/README.md | 8 +- .../architecture.md | 37 +++-- .../box-model.md | 12 +- .../container-queries-and-writing-modes.md | 2 +- .../display-and-positioning.md | 2 +- .../transforms-and-containment.md | 12 +- ...026-06-06-render-node-draw-model-design.md | 9 +- ...r-subtree-visibility-suppression-design.md | 2 +- ...-07-render-extract-retain-damage-design.md | 9 +- ...026-06-08-render-atlas-glyph-gpu-design.md | 24 ++-- ...-08-render-effect-compositor-gpu-design.md | 16 ++- .../README.md | 8 +- .../architecture.md | 4 +- .../paint-order-and-top-layer.md | 15 ++- .../README.md | 13 +- .../editing-and-ime.md | 10 +- .../README.md | 4 +- .../determinism.md | 20 +-- .../goldens.md | 34 ++--- .../invariants.md | 41 +++--- .../metric.md | 14 +- .../open-questions.md | 8 +- .../reftests.md | 4 +- 124 files changed, 948 insertions(+), 346 deletions(-) create mode 100644 docs/plans/2026-06-18-docs-audit-remediation.md create mode 100644 docs/prior-art/bevy-a11y/README.md create mode 100644 docs/prior-art/bevy-feathers/README.md create mode 100644 docs/reports/2026-06-18-docs-audit.md create mode 100644 docs/reports/2026-06-18-spec-code-findings.md diff --git a/.claude/skills/organizing-buiy-docs/SKILL.md b/.claude/skills/organizing-buiy-docs/SKILL.md index b1a49f1..c34d4e1 100644 --- a/.claude/skills/organizing-buiy-docs/SKILL.md +++ b/.claude/skills/organizing-buiy-docs/SKILL.md @@ -48,6 +48,8 @@ Implications: The date is **when the doc was written**, not the implementation target. The `-design.md` suffix on specs is what visually distinguishes specs from plans in `ls` output. Plans omit it. Prior-art files use the system name (no date prefix) because they're living docs — track revision history via git, not filename. +**Exception to the dated-plan rule:** a rolling, intentionally-undated backlog file (`docs/plans/follow-ups.md`) is permitted. It is a living cross-phase tracker, not a one-shot dated migration, so it carries no date prefix — its entries are flipped to `LANDED` in place as work ships rather than being superseded by a new dated plan. + **Existing files predating these rules are not renamed.** The convention applies to new docs only; the master index labels older entries explicitly so the missing suffix does not affect discovery. ## Document headers @@ -87,7 +89,7 @@ Use a folder (`docs/specs/YYYY-MM-DD-/`) only when one logical document i Rules: - The parent `README.md` is **required**. It states the folder's purpose and links every child. -- Children use kebab-case topic names with **no date prefix** — they inherit the parent's date. +- Children use kebab-case topic names with **no date prefix** — they inherit the parent's date. *Exception:* a dated **design-note / ADR** child that records its own decision date and status is permitted inside a spec folder (it reads like a miniature dated report scoped to the parent design — e.g. the render-pipeline folder's `2026-06-*` children — where the date marks when that decision was made). These are the only children that may carry a date prefix. - Children are facets of one design, not phase numbers. Phases imply ordering; children do not. - Maximum one level deep. If a child needs its own children, promote it to a top-level spec. diff --git a/CLAUDE.md b/CLAUDE.md index 41ca9a3..bbe811c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -62,8 +62,14 @@ does **not** require a display: ```sh cargo test -p buiy_core -j 2 -- --ignored --test-threads=1 +cargo test -p buiy_verify -j 2 -- --ignored --test-threads=1 ``` +The GPU lane has **two legs**, both of which CI runs: `buiy_core` (the render +GPU path above) and `buiy_verify` (the visual-bug verification suite — goldens, +reftests, the perceptual metric). Run both before pushing, or you skip the +`buiy_verify` GPU tests and can land a regression that fails CI's GPU lane. + `--test-threads=1` serializes the GPU work (one adapter context at a time). This lane is **additive** — it must pass on a GPU host, and the headless gate above must stay green independently (CI has no adapter). When adding a render GPU test, diff --git a/README.md b/README.md index 54ff06e..f2aa23d 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ fn on_press(mut presses: MessageReader) { ## Demos -Two runnable example crates live under `examples/`: +Two runnable visual demos (plus the headless `capture` tool) live under `examples/`: ```sh cargo run -p hello_button # a single clickable "Save" button; logs OnPress to stdout @@ -124,7 +124,7 @@ cargo run -p hello_text # a themed title above a wrapped body paragraph ### Requirements -- **Rust:** stable, edition 2024 (MSRV 1.85) — selected automatically via `rust-toolchain.toml`. +- **Rust:** stable, edition 2024. The MSRV (1.85) is enforced by `rust-version` in the workspace manifest; `rust-toolchain.toml` pins the floating `stable` channel and the `rustfmt`/`clippy` components. - **Bevy:** 0.18. - **Linux system deps** (Bevy needs these to open a window): diff --git a/docs/README.md b/docs/README.md index db9341b..868c8f3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,7 +9,10 @@ For build/test/dev commands, see `../CLAUDE.md`. This file does not duplicate th Reading order for newcomers: 1. [Buiy foundation design](specs/2026-05-07-buiy-foundation/README.md) — the target shape of the library: feature inventory, architectural foundation, sub-spec roadmap. Multi-file folder; start at the README, then read children in the order it lists. -2. [Docs organization design](specs/2026-05-07-docs-organization-design.md) — how this docs tree is structured. +2. [Buiy layout design](specs/2026-05-08-buiy-layout-design/README.md) — the Taffy bridge and the layout/render boundary every other subsystem builds on (multi-file). +3. [Buiy text-rendering design](specs/2026-06-09-buiy-text-rendering-design/README.md) — the cosmic-text engine, glyph producer, and text/editing surface (multi-file). +4. [Buiy verification design](specs/2026-06-15-buiy-verification-design/README.md) — how visual/layout/render correctness is gated (the 5-tier pyramid + golden harness) (multi-file). +5. [Docs organization design](specs/2026-05-07-docs-organization-design.md) — how this docs tree is structured. ## Document types @@ -59,7 +62,6 @@ If a doc spans areas, file it under its primary area only. Reference any adjacen **Specs** - [Buiy layout design](specs/2026-05-08-buiy-layout-design/README.md) — Taffy bridge, hybrid `Style` builder + decomposed components, anchor positioning, container queries, writing modes, stacking + top layer, transforms + containment (multi-file). `[active]` -- [Buiy render-pipeline design](specs/2026-06-03-buiy-render-pipeline-design/README.md) — Bevy render-graph integration, render-side component model, clipping, top-layer compositing, effect compositor, atlasing, forced-colors; consumes layout's immutable paint inputs (multi-file). `[draft]` **Plans** @@ -77,15 +79,29 @@ If a doc spans areas, file it under its primary area only. Reference any adjacen - [Buiy layout table layout](plans/2026-05-29-buiy-layout-table-layout.md) — Phase 12: real `table_layout` sub-pass 6b — synthetic-flex column-width resolution + document-order row/row-group grid placement; `colspan`/`rowspan`, caption, ``/`` still deferred (tier-C). `[landed]` - [Buiy layout content-visibility](plans/2026-05-29-buiy-layout-content-visibility.md) — Phase 11: real `content-visibility: auto` off-screen skip (last-frame `ResolvedLayout` vs margin-expanded viewport + `ContainIntrinsicSize` sentinel size, descendants detached, stateless hysteresis) and `content-visibility: hidden` descendant prune, both in step-1 `sync_styles` + mirrored in `cq_flip_rerun`; blanket deferred-warn retired (repurposed to the Auto-without-hint residual). Auto paint-only skip + `contain-intrinsic-size: auto` remembered-size still deferred. `[landed]` - [Buiy layout descendant invalidation](plans/2026-05-29-buiy-layout-descendant-invalidation.md) — Phase 14: multi-level container-query geometric cascade — step-8 `cq_descendant_invalidate` walks the descendants of every query container whose `ResolvedLayout` changed this frame into a private `ContainerSizeDirty` set, and step-9 `cq_descendant_rerun` re-translates that set, recomputes Taffy, re-writes `ResolvedLayout`, and re-evaluates container queries so a `Cqw`-sized intermediate `B` re-resolves and a rule-bearing descendant `C` flips its marker the same frame `A` resizes (capped at one re-run per frame; deeper chains settle one level per frame). `[landed]` + +### Render + +**Specs** + +- [Buiy render-pipeline design](specs/2026-06-03-buiy-render-pipeline-design/README.md) — Bevy render-graph integration, render-side component model, clipping, top-layer compositing, effect compositor, atlasing, forced-colors; consumes layout's immutable paint inputs (multi-file). `[active]` + +**Plans** + +- [2026-06-03-buiy-render-r1-component-model](plans/2026-06-03-buiy-render-r1-component-model.md) — render-side decomposed component model; sole definer of the shared render types (`components.rs` + `color.rs`). `[landed]` +- [2026-06-03-buiy-render-r2-clip-rects](plans/2026-06-03-buiy-render-r2-clip-rects.md) — `WriteClipRects` render-prep pass; the `ClipRect`/`AncestorClip` clip-chain components. `[landed]` - [2026-06-03-buiy-render-r3-transform-bridge](plans/2026-06-03-buiy-render-r3-transform-bridge.md) — Transform/GlobalTransform bridge (clip-and-transform § B): single-writer compose + Update propagation chain. `[landed]` - [2026-06-03-buiy-render-r4-effect-groups](plans/2026-06-03-buiy-render-r4-effect-groups.md) — `WriteEffectGroups` render-prep pass (effect-compositor.md § 1): `effect_reason_for` former predicate + `EffectGroup`/`EffectReason` marker derivation (opacity<1 / isolate / filter / mix-blend / backdrop-filter), inserted/removed as derived state, scheduled `.after(Animate).before(Picking)`. Per-group geometry/targets deferred to a later Prepare pass. `[landed]` - [2026-06-03-buiy-render-r5-extract](plans/2026-06-03-buiy-render-r5-extract.md) — per-view `Changed`-gated `extract_buiy_nodes` (architecture § 1.2/§ 3/§ 4) replacing `extract_buiy_draws` at the schedule level: pure `resolve_color_token`/`node_skip_reason`/`extracted_node_for`/`assemble_in_paint_order` mapping (CssHidden + OffscreenAuto skips, `painters_z` forward order) + R5-owned per-view `ExtractedNodes` carrier. Extract rework landed; node-side consumption swap (`ExtractedDraws` → `ExtractedNodes`) pending R6/R8, Phase-0 draw path intact. `[landed]` +- [2026-06-03-buiy-render-r6-prepare-buffers](plans/2026-06-03-buiy-render-r6-prepare-buffers.md) — Prepare phase: single persistent per-frame instance buffer + view uniform; owns `BuiyPrimitiveKind`. `[landed]` - [2026-06-03-buiy-render-r7-pipelines-shaders](plans/2026-06-03-buiy-render-r7-pipelines-shaders.md) — typed-primitive `SpecializedRenderPipeline`s keyed on target format (`BuiyPrimitiveKey { kind, format }` importing R6's `BuiyPrimitiveKind`): quad `..01` + shadow `..02` SDF WGSL under the `0xB01A_01XX` octets, border folded into the quad SDF, outline is the clip-suppressed quad. Device-free key/descriptor/dedup + `naga` parse tests gate; live `PipelineCache` allocation rides the `#[ignore]` GPU path. `[landed]` -- [2026-06-03-buiy-render-r8-paint-clip-toplayer](plans/2026-06-03-buiy-render-r8-paint-clip-toplayer.md) — R8 render-consumer helpers for clip + top layer (paint-order-and-top-layer.md §1–§6, clip-and-transform.md § A consumption): pure `scissor_rect` (logical `ClipRect` → physical wgpu scissor, `None` ⇒ skip), `clip_for_primitive` (outline clips against `AncestorClip`, else own `ClipRect` — § A.2 / component-model § 7), and `partition_top_layer` (top-layer tail split without re-sort, § 3.1), with `render_paint_order` integrating R5's live `assemble_context_tree` walk + the partition. The forward `painters_z` walk, the hit-test-reverse identity, and the `CssVisibility::Hidden`/`OffscreenAuto` per-entity skip are **reused from R5** (`assemble_in_paint_order`/`node_skip_reason`), not re-implemented (the earlier `flatten_paint_order`/`skips_paint` drafts were dropped as duplicates). Device-free helper tests gate. **Deferred:** the GPU consumer — per-entity scissored draw + top-layer composite in `BuiyNode::run` — blocked on the node-draw-model design (per-entity scissor + composite passes on R6's single persistent-buffer draw), a decision shared with R9; see [2026-06-06-render-node-draw-model-design.md](specs/2026-06-03-buiy-render-pipeline-design/2026-06-06-render-node-draw-model-design.md). `[partial]` -- [2026-06-07-buiy-render-r8b-node-draw](plans/2026-06-07-buiy-render-r8b-node-draw.md) — R8b hybrid node-draw model (node-draw-model-design Option C; supersedes R8 Task 8 only): per-instance clip-AABB fragment-discard threaded `ClipRect` → `ExtractedNode.clip` → `PackedInstance.clip_min/clip_max` (stride 36→52, raw `[f32;13]`) → `@location(6)/(7)` vertex attrs → clip-aware quad/shadow WGSL discard, keeping R6's single order-safe `draw` (no grouping/re-sort — `painters_z` preserved verbatim). Top-layer members pack the `[±INFINITY]` full-view sentinel (`clip = None`) so they paint unclipped at the painters_z tail; R9 multi-pass effect-group composite reserved as a documented stub in `BuiyNode::run`. Device-free layout/packing/naga-parse/extract/ordering tests gate; live pipeline registration rides the `#[ignore]` GPU path. `[active]` -- [2026-06-03-buiy-render-r9-effect-compositor](plans/2026-06-03-buiy-render-r9-effect-compositor.md) — Off-screen effect-group compositor (pillar 6 / effect-compositor.md), **foundations**. Landed + headless-tested: the full compositor MATH as pure fns in `render/compositor.rs` — `painted_bounds` (§2.1 union + ink + clip-last), next-pow2-capped-at-view `bucket_extent` (§2.2), `post_order_indices` (§3 bottom-up), `plan_allocation`/`rt_pool_budget` degradation (§2.3, ISOLATION/reserved degrade last), `group_target_descriptor` (fixed `Rgba16Float` linear), `composite_src_over` (linear group-opacity) — plus the structural seams `compositor::register`, the `PreparedEffectGroups` per-view component, and the `BuiyNode::run` step-1/step-2 composite loops. **Deferred (GPU orchestration):** `prepare_effect_groups` has a skeleton body and the node composite loops are inert — the working compositor needs an effect-group extract→prepare data flow (group membership/bounds to the render world) that R5's flat extract does not yet carry, plus a wgpu adapter to write+verify the pooled-target rasterize/composite. Tracked in follow-ups.md. `[partial]` +- [2026-06-03-buiy-render-r8-paint-clip-toplayer](plans/2026-06-03-buiy-render-r8-paint-clip-toplayer.md) — R8 render-consumer helpers for clip + top layer (paint-order-and-top-layer.md §1–§6, clip-and-transform.md § A consumption): pure `scissor_rect` (logical `ClipRect` → physical wgpu scissor, `None` ⇒ skip), `clip_for_primitive` (outline clips against `AncestorClip`, else own `ClipRect` — § A.2 / component-model § 7), and `partition_top_layer` (top-layer tail split without re-sort, § 3.1), with `render_paint_order` integrating R5's live `assemble_context_tree` walk + the partition. The forward `painters_z` walk, the hit-test-reverse identity, and the `CssVisibility::Hidden`/`OffscreenAuto` per-entity skip are **reused from R5** (`assemble_in_paint_order`/`node_skip_reason`), not re-implemented (the earlier `flatten_paint_order`/`skips_paint` drafts were dropped as duplicates). Device-free helper tests gate. Tasks 1–7 landed; Task 8 (the GPU consumer — per-entity scissored draw + top-layer composite in `BuiyNode::run`) was superseded by R8b's Option-C node-draw model and delivered on real hardware in the [GPU-verify campaign](plans/2026-06-07-render-gpu-verify-campaign.md). `[superseded]` +- [2026-06-07-buiy-render-r8b-node-draw](plans/2026-06-07-buiy-render-r8b-node-draw.md) — R8b hybrid node-draw model (node-draw-model-design Option C; supersedes R8 Task 8 only): per-instance clip-AABB fragment-discard threaded `ClipRect` → `ExtractedNode.clip` → `PackedInstance.clip_min/clip_max` (stride 36→52, raw `[f32;13]`) → `@location(6)/(7)` vertex attrs → clip-aware quad/shadow WGSL discard, keeping R6's single order-safe `draw` (no grouping/re-sort — `painters_z` preserved verbatim). Top-layer members pack the `[±INFINITY]` full-view sentinel (`clip = None`) so they paint unclipped at the painters_z tail; R9 multi-pass effect-group composite reserved as a documented stub in `BuiyNode::run`. Device-free layout/packing/naga-parse/extract/ordering tests gate; live pipeline registration verified on real hardware in the GPU-verify campaign. `[landed]` +- [2026-06-03-buiy-render-r9-effect-compositor](plans/2026-06-03-buiy-render-r9-effect-compositor.md) — Off-screen effect-group compositor (pillar 6 / effect-compositor.md). The full compositor MATH as pure fns in `render/compositor.rs` — `painted_bounds` (§2.1 union + ink + clip-last), next-pow2-capped-at-view `bucket_extent` (§2.2), `post_order_indices` (§3 bottom-up), `plan_allocation`/`rt_pool_budget` degradation (§2.3, ISOLATION/reserved degrade last), `group_target_descriptor` (fixed `Rgba16Float` linear), `composite_src_over` (linear group-opacity) — plus the structural seams `compositor::register`, the `PreparedEffectGroups` per-view component, and the `BuiyNode::run` step-1/step-2 composite loops. The GPU orchestration (the effect-group extract→prepare data flow, the full `prepare_effect_groups` system, and the live pooled-target rasterize/composite) landed on real hardware in the [GPU-verify campaign](plans/2026-06-07-render-gpu-verify-campaign.md). `[landed]` - [2026-06-03-buiy-render-r10-atlas](plans/2026-06-03-buiy-render-r10-atlas.md) — the shared `BuiyAtlas` render resource (guillotiere allocation, LRU eviction, page-budget pressure, warmup, pooling), the glyph-alpha + icon primitive shapes, and the reserved gradient/mask entry kinds. Realizes atlas-and-text-seam.md. `[landed]` - [2026-06-03-buiy-render-r11-color-forced-colors-verify](plans/2026-06-03-buiy-render-r11-color-forced-colors-verify.md) — color + forced-colors + verification (color-and-forced-colors.md). Consolidates the token resolver to the single canonical `render::color::resolve_token` (R1's mod.rs + R5's extract copies removed; missing-token `warn!` preserved in `resolve_named`; `SystemColor(kw)` resolved through the active theme); `SystemColorKeyword::{token, ALL}`; the forced-colors stub theme + main-world `Theme`-swap system (`BuiySet::Style`, before extract) + `Theme::is_changed()` re-resolve; the WCAG contrast helper (`buiy_verify` delegates to `render::color::contrast_ratio`, no dup — gate #9); and the gate-#11 static analyzers (token-flow + no-shadow-only-affordance) over a `CatalogPaint` seam. Headless-gated; the gate-#2 golden harness is GPU `#[ignore]`. **Final render-pipeline phase.** `[landed]` +- [2026-06-07-render-gpu-verify-campaign](plans/2026-06-07-render-gpu-verify-campaign.md) — verified the R6–R11 GPU path on real hardware; built the deferred atlas-glyph + effect-compositor + node-draw GPU orchestration (R8b/R9 GPU consumers); added the `--ignored` GPU CI lane; fixed 4 real GPU bugs. `[landed]` +- [Cross-phase follow-ups](plans/follow-ups.md) — rolling cross-phase deferral backlog (layout / render / text / verification items, with `LANDED` flips); intentionally undated. `[active]` ### Text @@ -109,18 +125,30 @@ If a doc spans areas, file it under its primary area only. Reference any adjacen **Editing campaign** - [Buiy text-editing campaign](plans/2026-06-13-buiy-text-editing-campaign.md) — E1–E6 phasing realizing `editing-and-ime.md`: editor substrate over `cosmic_text::Editor` → input/keymap → caret/selection → clipboard/undo → IME → lifecycle/widget/closure. Consumes T7's painting primitives; OQ#1 (edit→layout) resolved as one-frame latency; no new GPU work. `[landed]` +- [Buiy text-editing E1 — Editor substrate + Buffer ownership](plans/2026-06-13-buiy-text-editing-e1-substrate.md) — the editor substrate over `cosmic_text::Editor` and `TextBuffer` ownership handoff. `[landed]` +- [Buiy text-editing E2 — input translation + editing operations](plans/2026-06-13-buiy-text-editing-e2-input.md) — input translation, the editing-operation vocabulary, and the typing-latency gate. `[landed]` +- [Buiy text-editing E3 — caret + selection model + painting](plans/2026-06-13-buiy-text-editing-e3-caret-selection.md) — the caret + selection model and its painting via T7's primitives. `[landed]` +- [Buiy text-editing E4 — clipboard + undo/redo](plans/2026-06-13-buiy-text-editing-e4-clipboard-undo.md) — clipboard and undo/redo with composition-aware grouping. `[landed]` +- [Buiy text-editing E5 — IME composition](plans/2026-06-13-buiy-text-editing-e5-ime.md) — IME composition (preedit, candidate window, commit). `[landed]` +- [Buiy text-editing E6 — focus/lifecycle + widget + closure](plans/2026-06-13-buiy-text-editing-e6-lifecycle-widget-closure.md) — focus/lifecycle, placeholder, auto-scroll, the `TextInput` widget, and campaign closure. `[landed]` ### Reports -- [Text-editing design-readiness review](reports/2026-06-13-text-editing-design-readiness.md) — three-verifier audit of `editing-and-ime.md` against current `main` before the `buiy-text-editing` campaign: every integration seam confirmed in code, the no-new-GPU-work painting claim upheld, and OQ#1 (edit→layout frame-ordering) resolved as accepted one-frame latency. Verdict: ready-with-patches (now applied). `[2026-06-13]` -- [Visual-bug detection strategy](reports/2026-06-14-visual-bug-detection-strategy.md) — how to catch visual regressions as Buiy scales: a five-tier pyramid (layout-number → display-list/paint-order → metamorphic/property → reftests + CPU-cross-check → golden screenshots), reftests-first, grounded on canonical `main`. Audits the existing golden/forced-colors/text-shaping infra and names the gaps; input to `buiy-verification-design`. Pairs with the five `prior-art/` folders below. `[2026-06-14]` -- [Verification-harness adversarial review](reports/2026-06-15-verification-harness-adversarial-review.md) — fresh-agent cold-context review of the landed `buiy_verify` harness (20-agent find → verify → synthesize workflow). Found + **fixed** 7 real bugs (2 high: a blank render silently passing any golden; `GoldenKey` dropping the forced-colors axis), 1 maintainability trap, and the recurring "docstrings oversell coverage" theme; recorded 3 coverage gaps as follow-ups. Both gates green. `[2026-06-15]` +- [Text-editing design-readiness review](reports/2026-06-13-text-editing-design-readiness.md) — three-verifier audit of `editing-and-ime.md` against current `main` before the `buiy-text-editing` campaign: every integration seam confirmed in code, the no-new-GPU-work painting claim upheld, and OQ#1 (edit→layout frame-ordering) resolved as accepted one-frame latency. Verdict: ready-with-patches (now applied). Its readiness premise is overtaken: the campaign it gated landed as E1–E6 (PRs #62–#67). `[superseded]` +- [Visual-bug detection strategy](reports/2026-06-14-visual-bug-detection-strategy.md) — how to catch visual regressions as Buiy scales: a five-tier pyramid (layout-number → display-list/paint-order → metamorphic/property → reftests + CPU-cross-check → golden screenshots), reftests-first, grounded on canonical `main`. Audits the existing golden/forced-colors/text-shaping infra and names the gaps; input to `buiy-verification-design`. Pairs with the five `prior-art/` folders below. Realized by the [verification design](specs/2026-06-15-buiy-verification-design/README.md) + the landed `buiy_verify` harness. `[superseded]` +- [Verification-harness adversarial review](reports/2026-06-15-verification-harness-adversarial-review.md) — fresh-agent cold-context review of the landed `buiy_verify` harness (20-agent find → verify → synthesize workflow). Found + **fixed** 7 real bugs (2 high: a blank render silently passing any golden; `GoldenKey` dropping the forced-colors axis), 1 maintainability trap, and the recurring "docstrings oversell coverage" theme; recorded 3 coverage gaps as follow-ups. Both gates green. `[landed]` +- [Documentation audit](reports/2026-06-18-docs-audit.md) — full accuracy/quality/spec-alignment pass over all of `docs/` (26-agent workflow + adversarial code-verification): 110 findings, ~50 distinct issues. Headline: docs lag the code, zero code defects; dominant failure is stale "deferred/draft" tags left in place after work shipped. `[landed]` +- [Code-side findings from the docs audit](reports/2026-06-18-spec-code-findings.md) — the code-adjacent observations split out of the docs audit (stale in-code comments, dead-legacy `extract_buiy_draws` path, spec targets not yet built); no functional code defects found. `[active]` ### Docs infrastructure **Specs** -- [Docs organization design](specs/2026-05-07-docs-organization-design.md) — target structure of `docs/`, naming, headers, nesting. `[draft]` +- [Docs organization design](specs/2026-05-07-docs-organization-design.md) — target structure of `docs/`, naming, headers, nesting. `[landed]` + +**Plans** + +- [Documentation audit remediation](plans/2026-06-18-docs-audit-remediation.md) — ordered batches that resolved the [documentation audit](reports/2026-06-18-docs-audit.md) findings (catalog gaps, stale statuses, misleading "deferred" claims, convention drift) and restored conformance to the docs-organization spec. Executed 2026-06-18. `[landed]` ## Prior art @@ -158,7 +186,6 @@ External systems we learn from. Living documents — update on revision, archive - [Unity UI](prior-art/unity-ui/) — Unity Technologies' two-stack UI surface: **UGUI** (legacy `com.unity.ugui` v2.6, GameObject-based, Canvas + RectTransform + CanvasRenderer + EventSystem, shipped Unity 4.6 December 2014, still **officially recommended for runtime** as of Unity 6.3 LTS) and **UI Toolkit** (modern `com.unity.ui`, web-platform-inspired UXML + USS + VisualElement + Yoga + UI Builder, debuted as UIElements in Unity 2017→2019.1, renamed during Unity 2020.1 beta, runtime-stable from Unity 2021 LTS, world-space UI added Unity 6.2 December 2025). Proprietary commercial; Unity 6.3 LTS current. Text via **TextMeshPro** (acquired from Stephan Bouchard 2017, SDF-based; TextCore in UI Toolkit). Accessibility late: `UnityEngine.Accessibility` module since Unity 2023.2 Tech Stream (Oct 2023) — TalkBack + VoiceOver + Narrator + macOS VoiceOver bridges; **no ARIA model, no WCAG conformance claim**, parallel API not integrated into UXML authoring. Editor migration IMGUI → UI Toolkit ongoing 7+ years (Hierarchy / Project / Animator still IMGUI shells in Unity 6.3). Governance shock: **Runtime Fee saga 2023-2024** (announced 2023-09-13, fully cancelled 2024-09-12 after CEO John Riccitiello + CPO Marc Whitten departures). **Strongest existing-art for "web-platform parity inside a game engine"** — UI Toolkit is the only worked example of UXML/USS/VisualElement shipping at production scale (every Unity game uses one or both stacks). Validates: parallel-stack cohabitation (Buiy/`bevy_ui` per-window analog), comprehensive web-platform parity is shippable, day-one accessibility commitment is the differentiator (Unity took 9 years to ship a11y), Taffy > Yoga (Yoga is Flexbox-subset only, no Grid/container queries/anchor positioning). Avoid: 7+-year Editor migration (Buiy commits BSN-friendly day one), USS-vs-CSS divergence (`display: flex|none` only, no `calc()`, no `@keyframes`, no Grid, no media queries — if Buiy ships a stylesheet, match CSS strictly), no-keyframe-animation regret (Buiy commits keyframes day one), no-ARIA-attributes (Buiy ships decomposed A11y components in UXML-equivalent layer), legacy-stack persistence (UGUI still recommended after 12 years), proprietary lock-in + unilateral pricing changes, per-element field-tweak theming (UGUI `ColorBlock` megacomponent), complex Indic + Arabic shaping gaps (cosmic-text + rustybuzz solves), no vertical writing mode, no WebGL a11y, no Linux AT-SPI. Borrow: VisualElement tree shape, UXML-style declarative authoring → BSN, USS-style cascading + class selectors + custom properties + transitions, UQuery query selector API, SerializedObject data-binding pattern, `` template inclusion, UI Builder WYSIWYG editor (the spec for Buiy BSN visual authoring), UI Toolkit Debugger devtools shape, Accessibility Hierarchy Viewer, 9-slice (`-unity-slice-*`), TMP-style inline rich-text markup, sprite-asset fallback inside text runs, Editor + runtime unified substrate, the IMGUI → UI Toolkit migration playbook. Consult before any spec touching authoring (BSN, foundation § 2.4), styling (CSS-stylesheet open question § 5), render pipeline (§ 2.3), text rendering, accessibility, devtools, or game-vs-app widget catalog scope (foundation goal 6). `[active]` - [Godot Control](prior-art/godot-control/) — Godot Engine's UI subsystem: `Control` as the base GUI node (inherits `Object < Node < CanvasItem < Control`), anchor + offset layout, `Theme` resource skinning with StyleBoxes, the ~60-class Container + widget catalog in `scene/gui/`. **The only open-source MIT-licensed shipping-at-scale game-engine UI** — source readable end-to-end, unlike Unity/Unreal. Steward: Godot Foundation (Dutch Stichting, formed November 2022). Founders: Juan Linietsky + Ariel Manzur (Argentina, public 1.0 release January 14, 2014). UI substrate is fully Godot-owned: Godot's own renderer (Vulkan + OpenGL + D3D12), `TextServerAdvanced` (HarfBuzz + ICU + FreeType, BiDi + complex scripts since 4.0 / March 2023), Godot's own input. **AccessKit shipped in Godot 4.5 (September 2025) as experimental** — closing an ~11-year a11y gap, contributed by Pāvels Nadtočajevs (@bruvzg) who also led the 4.0 TextServer work. Production: the Godot editor itself (dogfooded), plus indie titles at million-copy scale (Brotato ~1M+, Buckshot Roulette ~1M+, Cassette Beasts ~250k+, Dome Keeper ~200k+). Validates: open-source MIT game-engine UI ships commercially at scale; Theme-resource-as-asset works for skinning; AccessKit is the right cross-engine a11y substrate (independent confirmation alongside Bevy). Avoid: anchor+margin positioning (non-intuitive vs CSS box model), accessibility-as-afterthought (Godot's 11-year vacuum is the cautionary tale), BiDi-added-9-years-late (4.0 fix took multi-year effort), BBCode-in-RichTextLabel as the rich-text model, visual properties stuffed on the base Control class (megacomponent shape), per-Container-as-a-C++-class layout (rigid; no third-party layout extensions). Borrow: Theme resource shape + lookup chain, type variations for theme variants, `Range`-abstract-base for min/max/value widgets, Container naming vocabulary, `size_flags_*` + `stretch_ratio` ergonomics, `CodeEdit` feature set as code-editor-grade text widget reference, the MIT-permissive open-source posture, engine-and-editor-share-one-UI dogfood principle. Consult before any spec on theme tokens (validates the shape), accessibility (validates AccessKit + the retrofit-cost lesson), layout model selection (the alternative to Buiy's CSS-via-Taffy bet), text rendering (the 9-year-late-BiDi lesson), or widget catalog naming. `[active]` - [RmlUi](prior-art/rmlui/) — open-source, MIT-licensed C++ UI library parsing **RML** (HTML-flavored markup) + **RCSS** (CSS-flavored stylesheets) via own layout engine + embedder interfaces (Render / System / File / FontEngine / TextInputHandler). Fork of **libRocket** (CodePoint Ltd + Shift Technology Ltd, 2008–2014, dormant since ~2014); RmlUi first official release **2.0 on 2019-10-13** by **Michael Ragazzon** (`mikke89`); latest stable **6.2 on 2026-01-11**. The **closest open-source precedent for "HTML+CSS in a game engine"** — 15+ years cumulative shipping history across Nightdive's KEX engine (The Thing: Remastered, Killing Time: Resurrected), Cfx.re Alchemist (Rockstar-acquired tooling), Unvanquished, ROSE Online, TruckersMP. Flexbox added 5.0 (2022-12-11), filters + masks + box-shadow + render layers + custom-properties added 6.0 (2024-08-26) via breaking render-interface redesign, native touch + inertial scrolling added 6.2. **Conspicuously lacks** CSS Grid, container queries, anchor positioning, logical properties, modern color spaces, `clip-path` / `backdrop-filter` / `mix-blend-mode` / CSS top layer, AccessKit / ARIA / screen-reader integration (no a11y story after 18 years cumulative), BiDi paragraph algorithm in core, first-class HarfBuzz (sample-only). Bus factor 1 (mikke89), no foundation, no corporate steward, single-maintainer cadence (~1 release/year recent). Validates: open-source HTML/CSS-in-game-engine pattern is shippable (libRocket+RmlUi 18-year cumulative proof); embedder-interface decomposition (Render / System / File / FontEngine / TextInputHandler) is portable across GPU APIs (GL2/GL3/Vulkan/DX12/SDL/SDL_GPU) + platforms (Windows/Linux/macOS/Android/iOS/Switch); RCSS subset (CSS 2.1 + Flexbox + transitions + 6.0 effects) is the empirically feasible floor for game UI; spatial controller navigation is solved (since libRocket); data-binding declarative pattern works (`data-model` + `data-bind` + `data-for`). Avoid: C++ embedder integration friction (Buiy is Rust-only, Bevy-only); custom DSL diverging from CSS spec (decorators replace `background-image` — permanent ecosystem-divergence cost, no Stylelint/MDN apply); own-built layout engine (Buiy uses Taffy and inherits Grid + subgrid + container queries); accessibility-as-afterthought (Buiy starts AccessKit-first with WCAG 2.2 AA floor); single-maintainer bus factor (Buiy positions within Bevy Foundation); render-interface designed without effects scope (Buiy must commit filters + masks + `backdrop-filter` + `mix-blend-mode` + top layer day one to avoid RmlUi 6.0–style breaking redesign); HarfBuzz-as-a-sample text strategy (Buiy uses cosmic-text directly). Borrow: the five-interface embedder pattern for Buiy's 3D-anchored UI + render-to-texture surface API (foundation § 5 open question); `DecoratorInstancer` extension mechanism for `BuiyMaterial` custom shaders; the `Context` concept (multi-context per app: window, 3D-anchored, HUD); spatial-navigation primitive (manual `nav-up`/`nav-down`/`nav-left`/`nav-right` edges + auto fallback); the data-model + data-bind shape as reference for the future-signals open question (foundation § 5); the styleable scrollbar-as-DOM-element pattern; the library-as-runtime posture ("never run without being called"); the libRocket → RmlUi fork as cautionary tale for single-maintainer succession + 4-year dormancy precedent. Consult before any spec on render-to-texture surface API, embedder interfaces, future CSS-flavored stylesheet (foundation § 5 open question — pair with [bevy-flair](prior-art/bevy-flair/) + [belly](prior-art/belly/)), or the cost-of-deferring-a11y discussion alongside [makepad](prior-art/makepad/) + [gpui](prior-art/gpui/). `[active]` - - [Coherent Gameface](prior-art/coherent-gameface/) — proprietary commercial **"full HTML5 + CSS3 + JavaScript in a game engine"** middleware by Coherent Labs (Sofia, Bulgaria, founded 2012, ~50–100 staff). Two-product split sharing one runtime: **Coherent Gameface** (code-first developer-facing, HTML5/CSS3/JS + React/Preact/SolidJS/jQuery/Tailwind/TypeScript) and **Coherent Prysm** (artist-first, Adobe Animate plugin) — both released 1.0 on 2018-12-07, latest 3.0.1 / 3.0.1.1. Substrate: in-house **Cohtml** HTML engine (V8 on tier-1 platforms + alternate VM elsewhere) + in-house **Renoir** GPU rendering library (DX11/12, Vulkan, Metal, GLES, console-native; Coherent claims 15–70% rendering-perf uplift over legacy backend). Engines: UE 4 + UE 5, Unity 2020.2+, custom C++. Quote-based commercial licensing, no public price tiers, 30-day watermarked trial; **acquired-by-Hellbender/Streamline pre-amble claim could NOT be verified** (likely confusion with the unrelated laser/photonics **Coherent Corp.** acquired by II-VI in 2022). Product lineage: **Coherent UI** (2012-09-24, WebKit, subscriptions ended 2017-12-05) → **Coherent GT** (~2014, WebKit, PUBG-era) → **Hummingbird** (~2016, first in-house engine) → **Gameface** (2018-12-07 rebrand). Verified AAA customers per Coherent's reel: Borderlands 4, Marvel's Spider-Man 2, Civilization 7, Alan Wake 2, Minecraft, World of Tanks, Sea of Thieves, PUBG, Cricket 24, iRacing (~18 titles total; Cyberpunk 2077 + The Witcher 3 pre-amble rumors NOT verified). **Conspicuously lacks** native CSS Grid (ships JS custom-element `` instead), container queries, anchor positioning, OS-AT-bridged accessibility (uses in-process TTS via `CohtmlARIA*` JS plugins — no UIA/AT-SPI/AXAPI tree publication, no NVDA/VoiceOver/JAWS/TalkBack integration), modern CSS color, view transitions, scroll-driven animations. Validates: full HTML5/CSS3/JS UI in a game engine is shippable at AAA scale (14-year continuous run); the "standards-compliant authoring + standard web tooling" pitch reaches AAA studios; custom-render-pipeline GPU UI works at console scale; commercial proprietary middleware funds a custom HTML engine sustainably for 14 years; per-frame CSS animations evaluated by runtime (not JS) is the right pattern; cross-platform-by-default authoring beats Windows-only tooling chains. Avoid: proprietary HTML5-engine maintenance burden (Cohtml must track Chromium pace indefinitely — ~50–100 engineers vs Chromium thousands, gap is structurally permanent); proprietary licensing (Buiy is MIT/Apache); commercial lock-in for an open ecosystem; per-engine binding tax (3 bindings × ~quarterly engine cadences ≈ 8–10 events/year); JavaScript-engine licensing + dual-VM cost (V8 + alternate VM); custom JS-element replacing CSS-spec features (`` — permanent ecosystem-divergence cost, same pitfall RmlUi commits with `decorator:`); accessibility-via-in-process-TTS (not OS-AT bridge); pricing opacity (quote-based, no public tiers, indies de facto excluded); "develop in Chrome, ship in Cohtml" pitch with documented divergences. Borrow: HTML5/CSS3/JS as the structural authoring-layer pattern (BSN is analogous: declarative, slot-shaped, reflection-driven, hot-reloadable); the engine-binding pattern of engine-agnostic substrate + thin engine-specific bindings (Buiy's public API is engine-agnostic-shaped even though runtime is Bevy); GPU command-stream rendering with engine-owned command queue (Bevy's render graph is the same pattern one layer up); custom memory allocator + per-subsystem GPU-memory attribution (`RenoirGPUMemoryInfo` shape); the "subset of web platform optimized for game UI" empirical feasibility study (Coherent's shipping surface is Buiy's minimum-viable scope, foundation `visuals.md` is the maximum); the two-product split (code-first Gameface + artist-first Prysm) as precedent for future BSN visual-editor authoring path; custom-element-style component decomposition (``, ``) as the shape for Buiy widget catalog primitives; DevTools-style inspector + live-CSS-edit + layout overlay as foundation-tier expectation; console-support-discipline (per-platform SDK builds, not tier-gated); the Scaleform-succession market-positioning pattern. Consult before any spec on render pipeline (§ 2.3), widget catalog scope, BSN authoring (§ 2.4), accessibility (§ 2.6) framing-vs-Coherent's-TTS-only approach, future CSS-flavored stylesheet (§ 5 open question — pair with [rmlui](prior-art/rmlui/), [bevy-flair](prior-art/bevy-flair/), [belly](prior-art/belly/)), or framing Buiy against "what proprietary commercial full-HTML5 game UI middleware looks like today." `[active]` *(Scaleform, Flutter-in-Flame, Defold GUI — pending)* @@ -175,7 +202,7 @@ The reference *implementations* of the CSS modules Buiy implements a typed Rust - [Taffy](prior-art/taffy/) — load-bearing Rust layout engine (Flexbox + Grid + Block + Float since 0.10); DioxusLabs-org, Nico Burns-maintained. MIT, bus-factor risk. Consult before any spec on layout primitives, sticky/anchor/container-queries (which Buiy implements ABOVE Taffy), or `Style` decomposition. `[active]` - [cosmic-text](prior-art/cosmic-text/) — load-bearing Rust text engine; harfrust (since 0.15.0, NOT rustybuzz) + swash + skrifa + unicode-bidi. System76-stewarded. Bevy 0.19-dev migrated to parley+swash — post-0.19 Buiy diverges from bevy_ui on text shaper. Consult before any spec on text shaping, BiDi, editing, IME, color emoji, or font fallback. `[active]` - [AccessKit](prior-art/accesskit/) — load-bearing cross-platform a11y bridge; Pneuma Solutions-stewarded. Windows / macOS / Linux production; Android pre-1.0; **iOS adapter shipped 2026-05-11** (Buiy spec needs update); web adapter NOT yet shipped. Buiy is the *producer*, `accesskit_consumer` is for adapter-side code. Consult before any spec on a11y tree construction, AccessKit integration, ACCNAME 1.2, focus model, or per-window adapter ownership. `[active]` -- [WAI-ARIA APG](prior-art/wai-aria-apg/) — the W3C contract source Buiy implements: WAI-ARIA 1.2 Recommendation (6 June 2023) + ACCNAME 1.2 Working Draft (20 May 2026) + WCAG 2.2 Recommendation (5 October 2023). The Authoring Practices Guide enumerates **32 widget design patterns** at , each pinning keyboard contract + ARIA role/state/property emission + name/description sourcing. **Inverted framing** (not "learns from"; this is the contract Buiy MUST implement): Implements (every Buiy widget follows the APG keyboard contract + ARIA mapping; ACCNAME 1.2 lives in `buiy_core`; WCAG 2.2 Level A + AA gated in CI; live regions via global announcer; `:focus-visible` + roving tabindex + `aria-activedescendant` + `inert` are foundation-tier). Diverge (gamepad navigation, spatial focus, 3D-anchored / diegetic UI, render-to-texture surfaces, game-specific widgets — APG covers none of these; Buiy extends honestly). Implementation strategy (per-widget specs under `buiy-widget-catalog-design`; verification gates 3 / 4 / 7 + linters; real-AT testing as manual-release-gate). Consult before any spec on a widget contract, keyboard interaction, ACCNAME, WCAG verification, focus management, or platform a11y bindings. `[active]` +- [WAI-ARIA APG](prior-art/wai-aria-apg/) — the W3C contract source Buiy implements: WAI-ARIA 1.2 Recommendation (6 June 2023) + ACCNAME 1.2 Working Draft (20 May 2026) + WCAG 2.2 Recommendation (5 October 2023). The Authoring Practices Guide enumerates **30 widget design patterns** at , each pinning keyboard contract + ARIA role/state/property emission + name/description sourcing. **Inverted framing** (not "learns from"; this is the contract Buiy MUST implement): Implements (every Buiy widget follows the APG keyboard contract + ARIA mapping; ACCNAME 1.2 lives in `buiy_core`; WCAG 2.2 Level A + AA gated in CI; live regions via global announcer; `:focus-visible` + roving tabindex + `aria-activedescendant` + `inert` are foundation-tier). Diverge (gamepad navigation, spatial focus, 3D-anchored / diegetic UI, render-to-texture surfaces, game-specific widgets — APG covers none of these; Buiy extends honestly). Implementation strategy (per-widget specs under `buiy-widget-catalog-design`; verification gates 3 / 4 / 7 + linters; real-AT testing as manual-release-gate). Consult before any spec on a widget contract, keyboard interaction, ACCNAME, WCAG verification, focus management, or platform a11y bindings. `[active]` ### Verification & visual testing @@ -195,7 +222,7 @@ External systems Buiy's visual-bug-detection strategy ([report](reports/2026-06- ## Reference designs -Archived design bundles (immutable inputs to specs, not specs themselves) live in [`reference-designs/`](reference-designs/) when they exist. +Archived design bundles (immutable inputs to specs, not specs themselves) will live in `reference-designs/` if/when any are added. ## Conventions diff --git a/docs/plans/2026-06-03-buiy-render-r1-component-model.md b/docs/plans/2026-06-03-buiy-render-r1-component-model.md index 9275be4..4abcac8 100644 --- a/docs/plans/2026-06-03-buiy-render-r1-component-model.md +++ b/docs/plans/2026-06-03-buiy-render-r1-component-model.md @@ -1,5 +1,8 @@ # Render component model (R1) Implementation Plan +**Date:** 2026-06-03 +**Status:** landed + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Depends on:** nothing. **Execution order:** R1 → R2 → R3 → R4 → R5 → R6 → R7 → R8 → (R9, R10) → R11. R1 is the FIRST phase and the **sole creator** of `crates/buiy_core/src/render/components.rs` and `crates/buiy_core/src/render/color.rs`, and the **sole definer** of every shared render type: `Background`, `Border` (+ `BorderSide`, `Radius`, `Corners`, `LineStyle`), `BoxShadow` (+ `Shadow`), `Opacity` (manual `Default 1.0`), `Outline`, `CssVisibility`, `OffscreenAuto`, `ClipRect`, `AncestorClip`, `EffectGroup` (+ `EffectReason`), `Filter` (+ full 10-variant `FilterFn`), `MixBlendMode`, `BackdropFilter`, `Angle`, `ClipRadius`, and `ColorToken` (+ `SystemColorKeyword`, in `render/color.rs`). Every later phase imports these from `render::components` / `render::color` and MUST NOT redefine them, re-`pub mod`, or re-`register_type` them. diff --git a/docs/plans/2026-06-03-buiy-render-r10-atlas.md b/docs/plans/2026-06-03-buiy-render-r10-atlas.md index ed2f234..e31aab5 100644 --- a/docs/plans/2026-06-03-buiy-render-r10-atlas.md +++ b/docs/plans/2026-06-03-buiy-render-r10-atlas.md @@ -1,5 +1,8 @@ # Texture Atlas Infrastructure + Glyph/Icon Seam Implementation Plan +**Date:** 2026-06-03 +**Status:** landed + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Build the shared render-world `BuiyAtlas` resource (guillotiere allocation, LRU eviction, page-budget pressure, warmup, pooling) plus the two F-tier atlas-sampling primitive shapes (`GlyphAlphaInstance`, `IconInstance`) and the `get_or_insert`/`AtlasEntry` seam that `buiy-text-rendering-design` plugs into. diff --git a/docs/plans/2026-06-03-buiy-render-r11-color-forced-colors-verify.md b/docs/plans/2026-06-03-buiy-render-r11-color-forced-colors-verify.md index bca3928..1ac825f 100644 --- a/docs/plans/2026-06-03-buiy-render-r11-color-forced-colors-verify.md +++ b/docs/plans/2026-06-03-buiy-render-r11-color-forced-colors-verify.md @@ -1,5 +1,8 @@ # Color, Forced-Colors, and the Verification Harness Implementation Plan +**Date:** 2026-06-03 +**Status:** landed + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Land the render-side color contract — `ColorToken` resolution against `Res`, the `Theme::is_changed()` re-extract edge, a main-world forced-colors `Theme` swap with a v1 stub system-color map, the two gate-#11 static analyzers (token-flow + no-shadow-only-affordance), and the scaffolded gate-#2 golden-image harness — all proven headless except the goldens. diff --git a/docs/plans/2026-06-03-buiy-render-r2-clip-rects.md b/docs/plans/2026-06-03-buiy-render-r2-clip-rects.md index d8616fb..1b411a2 100644 --- a/docs/plans/2026-06-03-buiy-render-r2-clip-rects.md +++ b/docs/plans/2026-06-03-buiy-render-r2-clip-rects.md @@ -1,5 +1,8 @@ # Clip Render-Prep (WriteClipRects) Implementation Plan +**Date:** 2026-06-03 +**Status:** landed + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Depends on:** R1 (component model — owns `render/components.rs`, the sole home of `ClipRect` / `AncestorClip`). Execution order: R1 → **R2** → R3 → R4 → R5 → R6 → R7 → R8 → (R9, R10) → R11. diff --git a/docs/plans/2026-06-03-buiy-render-r3-transform-bridge.md b/docs/plans/2026-06-03-buiy-render-r3-transform-bridge.md index d0a47af..62f7d6c 100644 --- a/docs/plans/2026-06-03-buiy-render-r3-transform-bridge.md +++ b/docs/plans/2026-06-03-buiy-render-r3-transform-bridge.md @@ -1,5 +1,8 @@ # Transform / GlobalTransform Bridge Implementation Plan +**Date:** 2026-06-03 +**Status:** landed + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Depends on:** R1 (`render/components.rs` + `render/color.rs` and every shared render type — `Background`, `Border`, `ResolvedTransform` consumers, `ColorToken`). **Execution order:** R1 → R2 → R3 → R4 → R5 → R6 → R7 → R8 → (R9, R10) → R11. R3 imports `Background`/`Border`/`ColorToken` and `resolve_token` from R1's `render::components` / `render::color` / `render::mod`; it MUST NOT define or re-export any of them. R3 introduces NO new `BuiySet` variant (spec [architecture.md § 5.1/§ 5.2](../specs/2026-06-03-buiy-render-pipeline-design/architecture.md) forbids a new top-level render set); `write_buiy_transform` + the three `bevy_transform` propagation systems are pinned directly `.after(BuiySet::Animate).before(BuiySet::Picking)` inside the existing chain. diff --git a/docs/plans/2026-06-03-buiy-render-r4-effect-groups.md b/docs/plans/2026-06-03-buiy-render-r4-effect-groups.md index 2dbe886..e0f6790 100644 --- a/docs/plans/2026-06-03-buiy-render-r4-effect-groups.md +++ b/docs/plans/2026-06-03-buiy-render-r4-effect-groups.md @@ -1,5 +1,8 @@ # Effect-group formation (`WriteEffectGroups`) Implementation Plan +**Date:** 2026-06-03 +**Status:** landed + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Depends on:** R1 (sole creator of `render/components.rs` + `render/color.rs` and sole definer of `Opacity`/`Filter`/`FilterFn`/`MixBlendMode`/`BackdropFilter`/`EffectGroup`/`EffectReason`). Execution order: R1 → R2 → R3 → **R4** → R5 → R6 → R7 → R8 → (R9, R10) → R11. diff --git a/docs/plans/2026-06-03-buiy-render-r5-extract.md b/docs/plans/2026-06-03-buiy-render-r5-extract.md index e97fdb5..4383b17 100644 --- a/docs/plans/2026-06-03-buiy-render-r5-extract.md +++ b/docs/plans/2026-06-03-buiy-render-r5-extract.md @@ -1,5 +1,8 @@ # Per-view Extract Rework Implementation Plan +**Date:** 2026-06-03 +**Status:** landed + > **Depends on:** R1 (component-model — owns `render/components.rs` + `render/color.rs` and all shared render types). Execution order across the render-pipeline series: R1 → R2 → R3 → R4 → **R5** → R6 → R7 → R8 → (R9, R10) → R11. R6 consumes this phase's `ExtractedNodes`. > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/docs/plans/2026-06-03-buiy-render-r6-prepare-buffers.md b/docs/plans/2026-06-03-buiy-render-r6-prepare-buffers.md index b397ac0..f901513 100644 --- a/docs/plans/2026-06-03-buiy-render-r6-prepare-buffers.md +++ b/docs/plans/2026-06-03-buiy-render-r6-prepare-buffers.md @@ -1,5 +1,8 @@ # Prepare phase: persistent buffers + view uniform + instance packing Implementation Plan +**Date:** 2026-06-03 +**Status:** landed + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Depends on:** R5 (and R1). Execution order: R1 → R2 → R3 → R4 → R5 → **R6** → R7 → R8 → (R9, R10) → R11. R6 **consumes** R5's per-view `ExtractedNodes` component (owned by R5, `render/extract.rs`) and R1's shared render types (`render/components.rs`); it does **not** redefine them. R6 **owns** the CPU instance bucketing (`render/buckets.rs`) and the shared `BuiyPrimitiveKind` enum that R7 imports. diff --git a/docs/plans/2026-06-03-buiy-render-r7-pipelines-shaders.md b/docs/plans/2026-06-03-buiy-render-r7-pipelines-shaders.md index 9c039e0..332a5eb 100644 --- a/docs/plans/2026-06-03-buiy-render-r7-pipelines-shaders.md +++ b/docs/plans/2026-06-03-buiy-render-r7-pipelines-shaders.md @@ -1,5 +1,8 @@ # Typed-primitive pipelines + SDF shaders Implementation Plan +**Date:** 2026-06-03 +**Status:** landed + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Depends on:** R6 (`render/buckets.rs` — owns the shared `BuiyPrimitiveKind { Shadow, Quad, Glyph, Path }` enum and CPU instance bucketing; R7 **imports** that enum, it does not redefine it). Execution order: R1 → R2 → R3 → R4 → R5 → R6 → **R7** → R8 → (R9, R10) → R11. R7 must land after R6 so `BuiyPrimitiveKind` exists to import. diff --git a/docs/plans/2026-06-03-buiy-render-r8-paint-clip-toplayer.md b/docs/plans/2026-06-03-buiy-render-r8-paint-clip-toplayer.md index feee4fa..6b7fb06 100644 --- a/docs/plans/2026-06-03-buiy-render-r8-paint-clip-toplayer.md +++ b/docs/plans/2026-06-03-buiy-render-r8-paint-clip-toplayer.md @@ -1,5 +1,8 @@ # Paint-order walk + clip scissor + top-layer composite Implementation Plan +**Date:** 2026-06-03 +**Status:** superseded (Task 8 superseded by R8b; Tasks 1–7 landed) + > **STATUS (2026-06-06): partially landed + partially superseded.** Executed > against the landed R5/R6 state, several tasks turned out to be already shipped by > R5: the forward `painters_z` walk (Task 2 `flatten_paint_order`) duplicates R5's @@ -15,6 +18,8 @@ > with R9. See > [2026-06-06-render-node-draw-model-design.md](../specs/2026-06-03-buiy-render-pipeline-design/2026-06-06-render-node-draw-model-design.md) > and the follow-ups.md entry. Tasks below are the original plan, kept for context. +> **Task 8 landed via R8b** (per-instance fragment-discard clip); see +> [2026-06-07-buiy-render-r8b-node-draw.md](2026-06-07-buiy-render-r8b-node-draw.md). > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/docs/plans/2026-06-03-buiy-render-r9-effect-compositor.md b/docs/plans/2026-06-03-buiy-render-r9-effect-compositor.md index 3dca551..b04f4c5 100644 --- a/docs/plans/2026-06-03-buiy-render-r9-effect-compositor.md +++ b/docs/plans/2026-06-03-buiy-render-r9-effect-compositor.md @@ -1,5 +1,8 @@ # Off-screen Effect-Group Compositor Implementation Plan +**Date:** 2026-06-03 +**Status:** landed + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Build the v1 off-screen effect-group compositor — pure-CPU prepare-phase geometry (painted-bounds transitive union, next-pow2-capped-at-view bucketing, post-order indexing, `rt_pool_budget` degradation decision) gating green headless, plus the GPU prepare system, pooled `Rgba16Float` targets, and bottom-up composite passes (group `Opacity` linear + `isolation`) wired into `BuiyNode::run` behind the `#[ignore]` GPU path. @@ -10,6 +13,19 @@ **Tier/Test reality:** Split. The prepare-phase geometry and budget logic are **pure functions** in `render::compositor` — HEADLESS (unit tests on CI, no wgpu adapter). Everything that needs a wgpu adapter — the `RenderSystems::Prepare` system constructed in the `RenderApp`, the pooled-target acquisition, the actual composite draws, the group-opacity golden, and the RSS-leak fixture — is **GPU (code + `#[ignore]`)**, mirroring `tests/render_smoke.rs` (no wgpu adapter on CI or this host). +> **As-landed (2026-06-07):** the GPU orchestration this plan scaffolded — the +> `prepare_effect_groups` body, the extract→prepare effect-group dataflow +> (`EffectGroupExtract` + per-group buffer partition), the pooled `Rgba16Float` +> targets, and the bottom-up `BuiyNode::run` composite passes — was **built and +> verified on real hardware** in the +> [render GPU-verification campaign](2026-06-07-render-gpu-verify-campaign.md) +> (Phase 4 item 5; the overlap-composites-once-at-0.5 and RT-pool-returns-to-baseline +> tests are green on the GPU lane). The `#[ignore]` markers below stay — they gate +> the wgpu-adapter tests off the headless CI gate, which still runs without an +> adapter — but `prepare_effect_groups` and the composite passes are live code, not +> inert stubs. Design note: +> [2026-06-08-render-effect-compositor-gpu-design.md](../specs/2026-06-03-buiy-render-pipeline-design/2026-06-08-render-effect-compositor-gpu-design.md). + --- ## Cross-phase dependencies (assumed, not built here) @@ -1155,4 +1171,6 @@ Steps: ## Cross-phase dependency assumed -The prepare-system **body** (Task 9) and the node **subtree-render** (Task 10) consume types/inputs owned by sibling phases not landed here: `Opacity`/`BoxShadow`/`Outline`/`EffectGroup` (component-model phase), `WriteEffectGroups` (render-prep phase), `ClipRect`/`AncestorClip` (clip-and-transform phase), and the per-view `ExtractedNodes`/extract-of-group-members (architecture phase). To keep the gate green without them, this phase's pure core is written against plain geometry inputs and the component-reading glue rides the `#[ignore]` GPU path — an un-landed upstream phase cannot redden CI. `EffectReason` is defined locally here (Task 1) and unifies with component-model's `EffectGroup` when that lands. +The prepare-system **body** (Task 9) and the node **subtree-render** (Task 10) consume types/inputs owned by sibling phases not yet landed *at plan time*: `Opacity`/`BoxShadow`/`Outline`/`EffectGroup` (component-model phase), `WriteEffectGroups` (render-prep phase), `ClipRect`/`AncestorClip` (clip-and-transform phase), and the per-view `ExtractedNodes`/extract-of-group-members (architecture phase). To keep the gate green without them, this phase's pure core is written against plain geometry inputs and the component-reading glue rides the `#[ignore]` GPU path — an un-landed upstream phase cannot redden CI. `EffectReason` is defined locally here (Task 1) and unifies with component-model's `EffectGroup` when that lands. + +> **As-landed:** all of those sibling phases (R1 component-model, R4 `WriteEffectGroups`, R2 clip-and-transform, R5 extract) shipped, and the prepare-system body + node composite passes were filled in and verified on real hardware in the [render GPU-verification campaign](2026-06-07-render-gpu-verify-campaign.md). The local `EffectReason` unified onto the component-model `EffectGroup` as planned. diff --git a/docs/plans/2026-06-07-buiy-render-r8b-node-draw.md b/docs/plans/2026-06-07-buiy-render-r8b-node-draw.md index 0fc70f7..5203be5 100644 --- a/docs/plans/2026-06-07-buiy-render-r8b-node-draw.md +++ b/docs/plans/2026-06-07-buiy-render-r8b-node-draw.md @@ -1,7 +1,7 @@ # R8b: Hybrid Node-Draw Model Implementation Plan **Date:** 2026-06-07 -**Status:** active +**Status:** landed **Spec:** [specs/2026-06-03-buiy-render-pipeline-design/2026-06-06-render-node-draw-model-design.md](../specs/2026-06-03-buiy-render-pipeline-design/2026-06-06-render-node-draw-model-design.md) (DECIDED: Option C hybrid) **Supersedes:** [plans/2026-06-03-buiy-render-r8-paint-clip-toplayer.md](2026-06-03-buiy-render-r8-paint-clip-toplayer.md) Task 8 only. Tasks 1–7 of that plan (`scissor_rect`, `clip_for_primitive` in `render/clip.rs`; `partition_top_layer` in `render/top_layer.rs`) are landed and consumed here without re-implementation. diff --git a/docs/plans/2026-06-07-render-gpu-verify-campaign.md b/docs/plans/2026-06-07-render-gpu-verify-campaign.md index e6a0d86..52a827e 100644 --- a/docs/plans/2026-06-07-render-gpu-verify-campaign.md +++ b/docs/plans/2026-06-07-render-gpu-verify-campaign.md @@ -1,5 +1,15 @@ # Render GPU-Verification Campaign +**Date:** 2026-06-07 +**Status:** landed +**Spec:** [2026-06-03-buiy-render-pipeline-design](../specs/2026-06-03-buiy-render-pipeline-design/README.md) +**Realizes the render design notes:** +[2026-06-07-render-extract-retain-damage-design.md](../specs/2026-06-03-buiy-render-pipeline-design/2026-06-07-render-extract-retain-damage-design.md) +(damage-retention re-extract), [2026-06-08-render-atlas-glyph-gpu-design.md](../specs/2026-06-03-buiy-render-pipeline-design/2026-06-08-render-atlas-glyph-gpu-design.md) +(coverage-glyph atlas GPU pipeline), and [2026-06-08-render-effect-compositor-gpu-design.md](../specs/2026-06-03-buiy-render-pipeline-design/2026-06-08-render-effect-compositor-gpu-design.md) +(effect-group GPU orchestration); the [2026-06-06-render-node-draw-model-design.md](../specs/2026-06-03-buiy-render-pipeline-design/2026-06-06-render-node-draw-model-design.md) +spine landed via [2026-06-07-buiy-render-r8b-node-draw.md](2026-06-07-buiy-render-r8b-node-draw.md). + > **For agentic workers:** this is a *campaign* plan, not a bite-sized TDD plan. > The bug-fix work is exploratory — the exact bugs are discovered by running the > GPU suite, then each fix is driven TDD-style as it surfaces. Phases are run as diff --git a/docs/plans/2026-06-11-buiy-text-t9-verification-closure.md b/docs/plans/2026-06-11-buiy-text-t9-verification-closure.md index 11efd0b..b795b3e 100644 --- a/docs/plans/2026-06-11-buiy-text-t9-verification-closure.md +++ b/docs/plans/2026-06-11-buiy-text-t9-verification-closure.md @@ -1,7 +1,7 @@ # Buiy Text T9: Verification Closure + Docs Flip — Implementation Plan **Date:** 2026-06-11 -**Status:** proposed +**Status:** landed **Spec:** [specs/2026-06-09-buiy-text-rendering-design/verification.md](../specs/2026-06-09-buiy-text-rendering-design/verification.md) §§ 1.3, 3.3, 4, 5 + [architecture.md](../specs/2026-06-09-buiy-text-rendering-design/architecture.md) § 2.3 + [README.md](../specs/2026-06-09-buiy-text-rendering-design/README.md) (Status block + Open-questions ledger) **Campaign:** [plans/2026-06-09-buiy-text-campaign.md](2026-06-09-buiy-text-campaign.md) — phase T9, the FINAL phase (depends on all of T1–T8; the implementer starts from a branch with T1–T8 merged — T8 landed @ `12cb830`) **Closes:** the text campaign. After this plan the campaign's phase table is all-landed, the spec Status flips from proposed, and the prior-art folders carry their owed correction pass. @@ -734,7 +734,7 @@ line in Orientation § 7, per D6 (correction blockquotes, no rewrites). Attrs lifetimes)"); key-facts table swash row → 0.2.8-as-locked annotation; add one dated line: "2026-06-11 — correction pass (text campaign T9): 0.19-verified errata applied per - [text verification.md § 5](…)". + [text verification.md § 5](../specs/2026-06-09-buiy-text-rendering-design/verification.md)". - [ ] `grep -rn "set_text(" docs/prior-art/cosmic-text/ docs/prior-art/bevy-cosmic-edit/` — annotate every sketch passing a font system (the lazy-setter 0.19 signature: `set_text(&mut self, text, attrs: &Attrs, shaping, diff --git a/docs/plans/2026-06-13-buiy-text-editing-e1-substrate.md b/docs/plans/2026-06-13-buiy-text-editing-e1-substrate.md index e725f6b..47f358c 100644 --- a/docs/plans/2026-06-13-buiy-text-editing-e1-substrate.md +++ b/docs/plans/2026-06-13-buiy-text-editing-e1-substrate.md @@ -1,7 +1,7 @@ # Buiy text-editing E1 — Editor substrate + Buffer ownership **Date:** 2026-06-13 -**Status:** ready to execute +**Status:** landed **Campaign:** [2026-06-13-buiy-text-editing-campaign.md](2026-06-13-buiy-text-editing-campaign.md) § "E1 — Editor substrate + Buffer ownership" **Spec:** [editing-and-ime.md](../specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md) §§ 2.1, 2.2, 2.2a, 2.3; [measure-and-layout.md](../specs/2026-06-09-buiy-text-rendering-design/measure-and-layout.md) § 2.3 diff --git a/docs/plans/2026-06-13-buiy-text-editing-e2-input.md b/docs/plans/2026-06-13-buiy-text-editing-e2-input.md index 4616863..8c5ca60 100644 --- a/docs/plans/2026-06-13-buiy-text-editing-e2-input.md +++ b/docs/plans/2026-06-13-buiy-text-editing-e2-input.md @@ -1,10 +1,11 @@ # Buiy text-editing E2 — input translation + editing operations + the latency gate **Date:** 2026-06-13 +**Status:** landed **Phase:** E2 (of the E1–E6 text-editing campaign) **Branch:** `text-editing-e2` (off `main`, which now includes E1) **Campaign plan:** [2026-06-13-buiy-text-editing-campaign.md](2026-06-13-buiy-text-editing-campaign.md) § "E2 — Input translation + editing operations + the latency gate" -**Spec realized:** [editing-and-ime.md](../specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md) §§ 3, 3.1, 3.2, 3.3, 11 +**Spec:** [editing-and-ime.md](../specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md) §§ 3, 3.1, 3.2, 3.3, 11 **Readiness:** [2026-06-13-text-editing-design-readiness.md](../reports/2026-06-13-text-editing-design-readiness.md) (OQ#1 resolved: one-frame latency; the new Input-driven N→N+1 fixture is E2's gate) --- diff --git a/docs/plans/2026-06-13-buiy-text-editing-e3-caret-selection.md b/docs/plans/2026-06-13-buiy-text-editing-e3-caret-selection.md index 67cfb1f..133868f 100644 --- a/docs/plans/2026-06-13-buiy-text-editing-e3-caret-selection.md +++ b/docs/plans/2026-06-13-buiy-text-editing-e3-caret-selection.md @@ -1,11 +1,11 @@ # Buiy Text-Editing E3 — Caret + Selection Model + Painting **Date:** 2026-06-13 +**Status:** landed **Phase:** E3 of the text-editing campaign (E1–E6) **Campaign:** [2026-06-13-buiy-text-editing-campaign.md](2026-06-13-buiy-text-editing-campaign.md) § "E3 — Caret + selection model + painting" **Spec:** [specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md](../specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md) §§ 4.1, 4.2, 4.3, 5, 11 **Branch:** `text-editing-e3` (off `main`, which now includes E1 + E2) -**Repo root:** `/mnt/storage/projects/buiy/.claude/worktrees/render-pipeline` --- diff --git a/docs/plans/2026-06-13-buiy-text-editing-e4-clipboard-undo.md b/docs/plans/2026-06-13-buiy-text-editing-e4-clipboard-undo.md index e623211..ddfafd4 100644 --- a/docs/plans/2026-06-13-buiy-text-editing-e4-clipboard-undo.md +++ b/docs/plans/2026-06-13-buiy-text-editing-e4-clipboard-undo.md @@ -1,10 +1,11 @@ # Buiy text-editing E4 — clipboard + undo/redo with composition-aware grouping **Date:** 2026-06-13 +**Status:** landed **Phase:** E4 (of the E1–E6 text-editing campaign) **Branch:** `text-editing-e4` (off `main`, which now includes E1 + E2 + E3) **Campaign plan:** [2026-06-13-buiy-text-editing-campaign.md](2026-06-13-buiy-text-editing-campaign.md) § "E4 — Clipboard + undo/redo with composition-aware grouping" -**Spec realized:** [editing-and-ime.md](../specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md) §§ 7 (clipboard), 8 (undo/redo), 11 (`EditUndone`/`EditRedone` Messages) +**Spec:** [editing-and-ime.md](../specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md) §§ 7 (clipboard), 8 (undo/redo), 11 (`EditUndone`/`EditRedone` Messages) **Readiness:** [2026-06-13-text-editing-design-readiness.md](../reports/2026-06-13-text-editing-design-readiness.md) --- diff --git a/docs/plans/2026-06-13-buiy-text-editing-e5-ime.md b/docs/plans/2026-06-13-buiy-text-editing-e5-ime.md index e651a1c..e187cd1 100644 --- a/docs/plans/2026-06-13-buiy-text-editing-e5-ime.md +++ b/docs/plans/2026-06-13-buiy-text-editing-e5-ime.md @@ -1,10 +1,11 @@ # Buiy text-editing E5 — IME composition **Date:** 2026-06-15 +**Status:** landed **Phase:** E5 (of the E1–E6 text-editing campaign) **Branch:** `text-editing-e5` (off `main`, which now includes E1 + E2 + E3 + E4) **Campaign plan:** [2026-06-13-buiy-text-editing-campaign.md](2026-06-13-buiy-text-editing-campaign.md) § "E5 — IME composition" -**Spec realized:** [editing-and-ime.md](../specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md) §§ 6.1 (display-splice decision), 6.2 (the four invariants), 6.3 (popup positioning), 11 (`CompositionStart/Update/End` Messages); § 1 supersession note; § 10 focus-loss preedit removal. +**Spec:** [editing-and-ime.md](../specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md) §§ 6.1 (display-splice decision), 6.2 (the four invariants), 6.3 (popup positioning), 11 (`CompositionStart/Update/End` Messages); § 1 supersession note; § 10 focus-loss preedit removal. **Readiness:** [2026-06-13-text-editing-design-readiness.md](../reports/2026-06-13-text-editing-design-readiness.md) --- diff --git a/docs/plans/2026-06-13-buiy-text-editing-e6-lifecycle-widget-closure.md b/docs/plans/2026-06-13-buiy-text-editing-e6-lifecycle-widget-closure.md index 70bcb53..2ab228e 100644 --- a/docs/plans/2026-06-13-buiy-text-editing-e6-lifecycle-widget-closure.md +++ b/docs/plans/2026-06-13-buiy-text-editing-e6-lifecycle-widget-closure.md @@ -1,10 +1,11 @@ # Buiy text-editing E6 — Focus/lifecycle + placeholder + auto-scroll + widget + closure **Date:** 2026-06-15 +**Status:** landed **Phase:** E6 (the FINAL phase of the E1–E6 text-editing campaign) **Branch:** `text-editing-e6` (off `main`, which now includes E1 + E2 + E3 + E4 + E5) **Campaign plan:** [2026-06-13-buiy-text-editing-campaign.md](2026-06-13-buiy-text-editing-campaign.md) § "E6 — Focus/lifecycle + placeholder + auto-scroll + widget + closure" -**Spec realized:** [editing-and-ime.md](../specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md) §§ 9 (auto-scroll via `ScrollOffset`), 10 (focus & lifecycle + placeholder), 11 (the full Message taxonomy + `EditSubmitted`), 2.3 (crate split — the `TextInput` widget is `buiy_widgets`), 13 (the v1 slice checklist — E6 ticks the LAST items). +**Spec:** [editing-and-ime.md](../specs/2026-06-09-buiy-text-rendering-design/editing-and-ime.md) §§ 9 (auto-scroll via `ScrollOffset`), 10 (focus & lifecycle + placeholder), 11 (the full Message taxonomy + `EditSubmitted`), 2.3 (crate split — the `TextInput` widget is `buiy_widgets`), 13 (the v1 slice checklist — E6 ticks the LAST items). **Readiness:** [2026-06-13-text-editing-design-readiness.md](../reports/2026-06-13-text-editing-design-readiness.md) --- @@ -151,7 +152,7 @@ buffer is recorded and committed (by `TextCommit`) before extract. ## How to work this plan Each task is **failing test → run-it-fail → minimal impl → run-it-pass → commit**. -Run from the repo root `/mnt/storage/projects/buiy/.claude/worktrees/render-pipeline`. +Run from the repo root. The headless gate command (no GPU, what CI runs): ```sh diff --git a/docs/plans/2026-06-18-docs-audit-remediation.md b/docs/plans/2026-06-18-docs-audit-remediation.md new file mode 100644 index 0000000..32c2f2f --- /dev/null +++ b/docs/plans/2026-06-18-docs-audit-remediation.md @@ -0,0 +1,110 @@ +# Documentation audit remediation + +**Date:** 2026-06-18 +**Status:** landed +**Spec:** [docs/specs/2026-05-07-docs-organization-design.md](../specs/2026-05-07-docs-organization-design.md) +**Realizes findings from:** [docs/reports/2026-06-18-docs-audit.md](../reports/2026-06-18-docs-audit.md) + +> **Executed 2026-06-18.** All batches applied; verification clean (catalog↔filesystem 0 gaps, 0 broken internal links, no non-standard doc-header statuses, no code touched). Decision 2 resolved to option (c) — the dated render children were *not* renamed (it would have broken path references in 5 code files); they were blessed as a documented exception instead. Code-side items remain open in the [code-side companion](../reports/2026-06-18-spec-code-findings.md). + +## Goal + +Bring `docs/` back into conformance with the docs-organization spec and remove every misleading/stale claim the audit found, **without touching code** (code-side observations are split into [docs/reports/2026-06-18-spec-code-findings.md](../reports/2026-06-18-spec-code-findings.md) for a separate session). Each batch below cites the audit theme(s)/IDs it resolves. + +## Decision points (resolve before executing the affected batches) + +Five findings need a human convention call. Each has a recommended default so the plan is executable as-is; the recommendation is what the batches assume unless overridden. + +1. **Report status convention (B8 / D5).** Reports use `**Verdict:**` + a date catalog tag, which violates the documented status set. **Recommend:** add `**Status:**` to each report and use real catalog statuses (`[superseded]` for the two whose premise is overtaken, `[landed]` for the adversarial review); do *not* bless date-tags. Alternative: amend the spec to define a report-specific `Date`+`Verdict` header (no lifecycle status) and legitimize date catalog tags. +2. **Render dated sub-design children (D1).** Five date-prefixed children violate the no-date-prefix child rule. **RESOLVED → option (c)** (changed from the original "rename" recommendation): bless dated design-note/ADR children inside a spec folder as an explicit exception in the docs-organization spec, and only normalize their status words. *Why the change:* the five filenames are referenced by path from **5 code files** (`render/components.rs`, `render/visibility.rs`, `render/extract.rs`, `tests/render_paint_skip.rs`, `tests/render_prepare.rs`) plus ~12 docs — renaming would break those code references or force code edits, violating the documentation-only scope. Option (c) keeps everything under `docs/` and breaks nothing. +3. **R8 plan status (B2 / D2).** R8 Task 8 was superseded by R8b; Tasks 1–7 landed. **Recommend:** `**Status:** superseded` with a one-line pointer to R8b, and keep R8's explanatory blockquote. +4. **`### Render` catalog area (A2).** **Recommend:** create it; move the render-pipeline spec out of `### Foundation` and all render plans out of `### Layout` into it. +5. **`follow-ups.md` disposition (A3).** **Recommend:** catalog it as-is (do *not* rename — it is a living tracker referenced by name everywhere), retitle the heading "Layout follow-ups" → "Cross-phase follow-ups," and add one sentence to the docs-organization spec blessing a rolling, intentionally-undated backlog file as an explicit exception to the dated-plan naming rule. + +--- + +## Batch 1 — Catalog completeness & structure (`docs/README.md`) — resolves A1, A2, A4, A5, A6 + +1. **Add a `### Render` catalog area** (decision 4). Move the render-pipeline spec entry from `### Foundation` and all render plan entries from `### Layout` into it. +2. **Add the 11 missing catalog entries** (A1), each `[landed]` unless decision 3 says otherwise: + - `render-r1-component-model` — render-side decomposed component model; sole definer of shared render types (`components.rs` + `color.rs`). + - `render-r2-clip-rects` — `WriteClipRects` prep pass; `ClipRect`/`AncestorClip` clip-chain components. + - `render-r6-prepare-buffers` — Prepare phase: single persistent per-frame instance buffer + view uniform; owns `BuiyPrimitiveKind`. + - `2026-06-07-render-gpu-verify-campaign` — verified R6–R11 GPU path on real hardware; built the deferred atlas-glyph + effect-compositor + node-draw GPU orchestration; added the `--ignored` GPU CI lane; fixed 4 GPU bugs. + - editing `e1`…`e6` — six entries mirroring the T1–T9 style under the Editing campaign subsection. +3. **Catalog `follow-ups.md`** (decision 5 / A3) under the Render or a "Backlog" line: rolling cross-phase deferral backlog; note it is intentionally undated. +4. **Expand "Where to start"** (A4) from 2 to 3–5 entries — add the layout, verification, and/or text-rendering specs. +5. **Remove the dead `reference-designs/` hyperlink** (A5); keep prose only ("…will live in `reference-designs/` if/when any are added"). +6. **Delete the stray blank line** between the RmlUi and Coherent Gameface catalog bullets (A6). + +## Batch 2 — Status-tag flips (catalog + in-file headers) — resolves B1–B7, parts of B8/B9 + +Flip in lockstep (catalog tag *and* in-file `**Status:**`) for each: + +- **render-pipeline spec** `[draft]` → `[active]` (B1); add a one-line note that remaining C-tier seams — filter/backdrop-filter/mix-blend shaders, `ClipRadius` — are tracked in `follow-ups.md`. +- **docs-organization spec** `[draft]` → `[landed]` (B3). +- **Text T9 plan** `proposed` → `landed` (B4). +- **R8 / R8b / R9** drop `[partial]`; R8b `[active]` → `[landed]`, R9 → `[landed]`, R8 → `[superseded]` (decision 3 / B2). Rewrite the R9 catalog "Deferred (GPU orchestration)" clause and the R8 "blocked on the node-draw-model design" clause to past tense, pointing at the GPU-verify campaign. +- **Render dated sub-designs** `proposed`/`implemented`/`DECIDED` → documented set (B5): `extract-retain-damage` → `landed`, `effect-compositor-gpu` → `landed`, `node-draw-model` → `landed`, `subtree-visibility-suppression` → `landed`, `atlas-glyph-gpu` → `landed`. Rewrite the parent README "Children" bullet for node-draw from "open design decision" to "decided (Option C) / landed via R8b." +- **verification `open-questions.md`** `draft` → `landed` (B6). +- **Editing plans** (B7): `e1` `ready to execute` → `landed`; add `**Status:** landed` to `e2`–`e6`; rename their `**Spec realized:**` key to `**Spec:**`. +- **Foundation / layout spec status (B9):** keep `[draft]`/`[active]` respectively but add a one-line rationale note to each header (foundation: "draft = inventory still accreting, not architecture unsettled"; layout: list the genuinely-unbuilt target features). + +## Batch 3 — Rewrite stale "deferred/landed" claims (the misleading class) — resolves C1–C13 + +Edit prose so landed work reads as landed. All are doc-only (code confirmed correct): + +- **Layout `architecture.md`** (C1, C3, C4, C5, C6): rewrite the †footnote (Stacking/Transform/Containment landed Phase 8/9); add `Changed` to the §1.2 trigger `Or` and fix the prose; reword multicol from "stub" to "Phase-13 real packer"; extend the §3/§8 pipeline to steps 0–9 (+ note text-owned `TextSync`/`TextCommit`, thirteen sub-sets total) cross-referencing `container-queries-and-writing-modes.md §1.3`; change `LayoutTree { tree: TaffyTree<()> }` → `TaffyTree` with the node-context/manual-`Default` note. +- **Layout `transforms-and-containment.md §2`** (C2): keep approach (a) as the chosen, *implemented* design; correct the deferral note — the Bevy `Transform` write landed in render Phase R3 (`write_buiy_transform`, `render/bridge.rs`); render reads `GlobalTransform`. Cross-link `render/clip-and-transform.md §B`. +- **Render `architecture.md §7`** (C8): replace "R5 renames `extract_buiy_draws`" with "`extract_buiy_nodes` is registered alongside the retained Phase-0 `extract_buiy_draws`, retired by R6/R8." +- **Render `paint-order-and-top-layer.md §6`** (C9): `node_skip_reason` lives in `render::visibility.rs`; extract reads only `ComputedPaintSkip`. Repoint the test pointer to `tests/render_paint_skip.rs`. +- **Render dated sub-designs** (C7): re-tense `extract-retain-damage` and `effect-compositor-gpu` scope prose from "inert/never implemented" to "landed" (header flips are Batch 2). +- **`follow-ups.md`** (C10, C11): rewrite the `matrix_goldens` entry — option (i) landed (skip un-blessed cells; lane green; keep only the magenta-sentinel note); add a `— LANDED` block to the node-draw-model entry pointing at R8b + the R9 entry. +- **`blink` + `servo-stylo` prior-art READMEs + blink catalog line** (C12): re-tense Phase-9 framing from "NEXT/about to build" to "landed / designed against"; bump the README `Date` headers. +- **Foundation `README.md §4` roadmap** (C13): turn the graduated rows (layout, text-rendering, verification) into links with graduation/status notes; update the render-pipeline row off "drafted"; annotate the text-editing row as realized via `editing-and-ime.md` + the E1–E6 campaign. Leave the genuinely-future rows untouched. + +## Batch 4 — Convention & header conformance — resolves D1, D2, D3, D4 + +1. **Render dated sub-design children (D1, decision 2 → option c):** do **not** rename (would break code references). Instead: (a) add a sentence to the docs-organization spec + the `organizing-buiy-docs` skill blessing dated design-note/ADR children inside a spec folder as an explicit exception to the no-date-prefix rule; (b) normalize the five children's `Status:` words to the documented set (Batch 2 B5). Filenames and all inbound references (docs + code comments) stay valid. +2. **Render plans r1–r11 headers (D2):** retrofit `**Date:** 2026-06-03` + `**Status:** landed` (R8 → `superseded`, decision 3). `**Spec:**` already present except the GPU-verify campaign — add `**Date:** 2026-06-07` / `**Status:** landed` / `**Spec:**` there. +3. **Author the two missing prior-art READMEs (D3):** `prior-art/bevy-feathers/README.md` and `prior-art/bevy-a11y/README.md`, each with the prior-art header (`Date`/`Status: active`/`Subject`), a one-paragraph overview, and a reading-order list of the existing children. Use `bevy-ui/README.md` as the template; anchor bevy-a11y on the megacomponent (#17644/#24308) narrative already in its children, keeping all Buiy-side statements sourced to the foundation spec (target, not decided-here). +4. **Editing plan `e3`/`e6` (D4):** remove the `**Repo root:**` header field and the hard-coded worktree path from `e6` prose. + +## Batch 5 — Broken / misleading links — resolves E1–E4 + +1. **E1:** in `bevy-a11y/comparisons.md` (lines 9, 124) drop/repoint `../accesskit/comparisons.md` → `../accesskit/ecosystem.md`. +2. **E2:** in `egui/styling-and-theming.md` repoint `../bevy-egui/styling.md` → `../bevy-egui/api-surface.md`. +3. **E3:** replace `/home/user/buiy/docs/…` display labels with the matching relative path across the affected prior-art children (`bevy-a11y`, `bevy-ui`, `bevy-egui`, `godot-control`, `unity-ui`). +4. **E4:** replace stale "(pending)" cross-refs with live links in `unreal-slate-umg`, `godot-control`, `kayak-ui` READMEs. + +## Batch 6 — Reports (status + stale framing) — resolves B8, C-reports, D5 + +1. Apply decision 1: add `**Status:**` to all three reports; set catalog tags (`text-editing-design-readiness` → `[superseded]`, `visual-bug-detection-strategy` → `[superseded]`/`[landed]`, `adversarial-review` → `[landed]`). +2. **Do not edit report bodies** (immutable). Surface staleness via extended catalog summaries: the readiness report's "types don't exist yet" premise is overtaken by landed E1–E6; the strategy report was realized by `buiy-verification-design` + the landed harness. + +## Batch 7 — Accuracy nits & citation drift — resolves F1–F15 + +- **F1:** add the `buiy_verify` `--ignored` leg to the `CLAUDE.md` GPU-lane block so it mirrors CI. +- **F2:** reword the root-README MSRV line (enforced by `rust-version` in the manifest; `rust-toolchain.toml` pins the `stable` channel). +- **F3:** fix "two" → "three" example crates (or "two visual demos + the headless `capture` tool"). +- **F4 / F11 / F15:** the citation-drift cluster — fix the specific stale numbers/symbols (`tier_rank` → `top_layer_paint_rank`; `compose_transform` `:3778`; the support/golden line ranges; the README "grep-confirmed" claim) **and** convert `:NNNN` citations to symbol-only across the verification + layout specs to stop recurrence. +- **F5:** correct the `goldens.md` example slug to the 7-field `…__fc0__lavapipe__dpr1`. +- **F6:** fix the `assert_golden(name, …)` mislabel → `assert_golden(&key, …)` in `goldens.md` + `metric.md`. +- **F7:** update the `atlas-glyph-gpu` "4 atlas_gpu.rs tests" framing (now 1; glyph tests in `text_gpu.rs`). +- **F8:** correct the text `README §Status` "E6 `TextInput` golden" → "E6 placeholder golden (`text_placeholder_gpu.rs`)"; note the `TextInput` bundle is verified headlessly only. +- **F9:** drop the BiDi split caret from the `§13` v1-shipped slice (it belongs only in Deferred). +- **F10:** decouple the units/`calc()` work from the "Phase 10" number (collides with landed position-fixed). +- **F12:** reconcile the cosmic-text PR #417 date contradiction. +- **F13:** make the APG pattern count agree (catalog "32" vs folder "30"). +- **F14:** update foundation `accessibility.md`/`architecture.md` iOS wording (`accesskit_ios 0.1.0` shipped 2026-05-11; deferred posture unchanged). +- **D6 / D7:** remove the duplicate framing-disclosure block in `wpt-reftests`/`wgpu-testing`; add the missing H1 to `cosmic-text/README.md`. + +## Execution & verification + +- Each batch is independent and can be a separate PR (Batches 1–2 highest value: they remove the discovery gaps and the misleading statuses). +- After edits: re-run the audit's mechanical scripts (catalog↔filesystem diff, header scan, internal-link scan) — all three should come back clean (0 missing catalog entries, 0 broken in-prose links, every post-2026-05-07 spec/plan/report carrying the required header fields). +- Update `docs/README.md`'s own catalog entries for any doc whose status this plan flips, and update the `organizing-buiy-docs` skill if decision 1/2/5 amends the docs-organization spec (skill mirrors the spec; update in the same change). + +## Out of scope + +Code edits — including stale in-code comments and the dead-legacy `extract_buiy_draws` path — are deferred to [docs/reports/2026-06-18-spec-code-findings.md](../reports/2026-06-18-spec-code-findings.md). No functional code defects were found by the audit. diff --git a/docs/plans/follow-ups.md b/docs/plans/follow-ups.md index 13bb82a..4e00cfa 100644 --- a/docs/plans/follow-ups.md +++ b/docs/plans/follow-ups.md @@ -1,4 +1,4 @@ -# Layout follow-ups +# Cross-phase follow-ups **Date:** 2026-05-21 **Status:** active @@ -534,7 +534,19 @@ goldens (group-opacity correctness, RSS return-to-baseline) run under an adapter **Spec touchpoint:** `effect-compositor.md § 1.1 / § 2 / § 3`; architecture.md § 1.4 / § 4. -## Render — node-draw model: per-entity clip + composite passes (R8 Task 8 / R9 blocker) +## Render — node-draw model: per-entity clip + composite passes (R8 Task 8 / R9 blocker) — LANDED + +**Status:** **Landed** as R8b +([2026-06-07-buiy-render-r8b-node-draw.md](2026-06-07-buiy-render-r8b-node-draw.md)), +ratified as Option C of the design note +(`docs/specs/2026-06-03-buiy-render-pipeline-design/2026-06-06-render-node-draw-model-design.md`). +The recommended **hybrid** shipped: per-instance clip-AABB fragment-discard +(`clip_for_primitive` → `PackedInstance` `clip_min`/`clip_max`, threaded into R6's +instance layout + WGSL) plus the multi-pass composite node (`BuiyNode::run` — +normal pass → `partition_top_layer`-driven top-layer composite pass), which the R9 +effect-compositor passes then build on (see the **effect-compositor GPU +orchestration** LANDED entry above). So this is no longer a blocker before R8 Task +8 / R9: both consumed the ratified model. The original deferral text follows. **Originated:** R8 (paint/clip/toplayer). R8 landed the pure consumer helpers (`scissor_rect`, `clip_for_primitive`, `partition_top_layer`) but **not** the GPU @@ -829,25 +841,21 @@ app, assert inline expected pixels, re-capture in a second fresh app, and color-emoji atlas output are not yet exercised end-to-end by a capturable fixture; the corpus is started with `rect-rounded`/`text-ahem` and these classes are added when the renderer paths land. -- **`coverage_golden::matrix_goldens` is RED on the GPU lane until the `button` - fixture corpus is blessed.** The Tier-5 enrollment driver (`coverage_golden.rs`, - committed in `a73de05`) iterates `Matrix::ci_default()` over the `button` - fixture and `assert_golden`s each cell, but **no `button` golden PNGs are - committed** (only `rect-rounded` + `text-ahem` are blessed), so it correctly - fail-closes (`check.rs:261`, "no golden committed for `button/resting/…`"). The - test's own header documents this as "bless-on-demand." This is the documented - fail-closed contract, NOT a regression — but it means the `--ignored` GPU lane - is not green for this one driver. **Blessing `button` cells is non-trivial**: - the coverage report flagged that the default `Button` under Buiy's *wholesale* - forced-colors swap paints the magenta missing-token sentinel +- **`coverage_golden::matrix_goldens` skips un-blessed cells — LANDED, lane + green.** The Tier-5 enrollment driver (`coverage_golden.rs`) iterates + `Matrix::ci_default()` over the `button` fixture and `assert_golden`s each cell; + cells with **no committed positive** are now skipped (treated as `ignored`, not + `fail` — `coverage_golden.rs:106-109`) rather than fail-closing, so the + `--ignored` GPU lane is green until cells are deliberately blessed. (This is the + landed resolution; the original entry listed it as an open campaign-owner option + (i).) **Residual note — blessing `button` cells is non-trivial:** the coverage + report flagged that the default `Button` under Buiy's *wholesale* forced-colors + swap paints the magenta missing-token sentinel (`color-and-forced-colors.md § 3.1`), so blessing those cells verbatim would - cement a known-wrong pixel as a golden. Resolution options (a campaign-owner - decision, not a doc fix): (i) make `matrix_goldens` skip un-blessed cells - (treat "no positive" as `ignored`, not `fail`) so the lane is green until cells - are deliberately blessed; or (ii) bless only the forced-colors-*safe* cells once - the default widget is forced-colors-safe (`buiy-widget-catalog-design`). Until - then the headless gate (the every-PR CI gate, which never runs `--ignored`) - stays fully green and unaffected. + cement a known-wrong pixel as a golden; bless only the forced-colors-*safe* + cells once the default widget is forced-colors-safe + (`buiy-widget-catalog-design`). The headless gate (the every-PR CI gate, which + never runs `--ignored`) stays fully green and unaffected. - **Forced-colors `BoxShadow` *visual* reftest** — blocked on the unlanded `BoxShadow` extract/draw path (see the R11 entry above); kept as an `#[ignore]`'d assertion-free placeholder, not a green test. diff --git a/docs/prior-art/accesskit/api.md b/docs/prior-art/accesskit/api.md index 22d399b..7b7a657 100644 --- a/docs/prior-art/accesskit/api.md +++ b/docs/prior-art/accesskit/api.md @@ -194,6 +194,6 @@ Everything else (Color, TextSelection, custom-action machinery, ListStyle, AriaC - `accesskit_winit` 0.33.0 docs.rs: https://docs.rs/accesskit_winit/0.33.0/accesskit_winit/ - `common/src/lib.rs` (NodeId, TreeUpdate, Tree, Live, Toggled, Invalid definitions): https://github.com/AccessKit/accesskit/tree/main/common/src - crates.io release history (versions, dates, co-release pattern): https://crates.io/crates/accesskit -- Buiy spec — accessibility integration: `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md` -- Buiy spec — architecture §2.6, §2.9: `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md` +- Buiy spec — accessibility integration: `docs/specs/2026-05-07-buiy-foundation/accessibility.md` +- Buiy spec — architecture §2.6, §2.9: `docs/specs/2026-05-07-buiy-foundation/architecture.md` - Sibling: [architecture.md](architecture.md), [tree-model.md](tree-model.md), [platform-adapters.md](platform-adapters.md) diff --git a/docs/prior-art/accesskit/architecture.md b/docs/prior-art/accesskit/architecture.md index 3ecc447..309dab9 100644 --- a/docs/prior-art/accesskit/architecture.md +++ b/docs/prior-art/accesskit/architecture.md @@ -97,7 +97,7 @@ Multi-window apps allocate one adapter per window, keyed by winit `WindowId`. `N - `common/src/lib.rs` (TreeUpdate, Tree, NodeId, Role, Action): https://github.com/AccessKit/accesskit/tree/main/common/src - `consumer/README.md` (adapter-side library, "not meant for direct application integration"): https://github.com/AccessKit/accesskit/blob/main/consumer/README.md - `accesskit_winit` 0.33.0 docs: https://docs.rs/accesskit_winit/0.33.0/accesskit_winit/ -- Buiy foundation spec — accessibility: `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md` -- Buiy foundation spec — architecture §2.6: `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md` -- Buiy cross-cutting §3.18: `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/cross-cutting.md` +- Buiy foundation spec — accessibility: `docs/specs/2026-05-07-buiy-foundation/accessibility.md` +- Buiy foundation spec — architecture §2.6: `docs/specs/2026-05-07-buiy-foundation/architecture.md` +- Buiy cross-cutting §3.18: `docs/specs/2026-05-07-buiy-foundation/cross-cutting.md` - Sibling: [tree-model.md](tree-model.md), [platform-adapters.md](platform-adapters.md), [api.md](api.md) diff --git a/docs/prior-art/accesskit/capabilities.md b/docs/prior-art/accesskit/capabilities.md index 2df51dc..54a8e74 100644 --- a/docs/prior-art/accesskit/capabilities.md +++ b/docs/prior-art/accesskit/capabilities.md @@ -139,4 +139,4 @@ Out of scope by design. AccessKit models the tree, not the rendered pixels. Buiy - https://docs.rs/accesskit/latest/accesskit/enum.Action.html - https://docs.rs/accesskit/latest/accesskit/struct.Node.html - https://www.w3.org/TR/accname-1.2/ -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md +- docs/specs/2026-05-07-buiy-foundation/accessibility.md diff --git a/docs/prior-art/accesskit/critiques.md b/docs/prior-art/accesskit/critiques.md index 8b715c8..ab7579a 100644 --- a/docs/prior-art/accesskit/critiques.md +++ b/docs/prior-art/accesskit/critiques.md @@ -160,7 +160,7 @@ When AccessKit bumps a major version, the data schema (`Node`, `Role`, `Action` - https://github.com/AccessKit/accesskit/releases - https://crates.io/crates/accesskit - https://github.com/bevyengine/bevy/issues/17644 -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/cross-cutting.md -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/verification.md +- docs/specs/2026-05-07-buiy-foundation/accessibility.md +- docs/specs/2026-05-07-buiy-foundation/architecture.md +- docs/specs/2026-05-07-buiy-foundation/cross-cutting.md +- docs/specs/2026-05-07-buiy-foundation/verification.md diff --git a/docs/prior-art/accesskit/ecosystem.md b/docs/prior-art/accesskit/ecosystem.md index c30943a..5442c9a 100644 --- a/docs/prior-art/accesskit/ecosystem.md +++ b/docs/prior-art/accesskit/ecosystem.md @@ -110,5 +110,5 @@ The fact that AccessKit *deliberately doesn't ship an ACCNAME 1.2 implementation - https://github.com/zed-industries/zed - https://crates.io/crates/accesskit - https://www.w3.org/TR/accname-1.2/ -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/verification.md +- docs/specs/2026-05-07-buiy-foundation/accessibility.md +- docs/specs/2026-05-07-buiy-foundation/verification.md diff --git a/docs/prior-art/accesskit/governance.md b/docs/prior-art/accesskit/governance.md index fc935b6..48f8dc7 100644 --- a/docs/prior-art/accesskit/governance.md +++ b/docs/prior-art/accesskit/governance.md @@ -108,5 +108,5 @@ The contributor concentration is uncomfortable: per AUTHORS + observed commit vo - https://pneumasolutions.com/about/ - https://nvaccess.org/about-nv-access/ - https://www.w3.org/TR/accname-1.2/ -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md +- docs/specs/2026-05-07-buiy-foundation/architecture.md +- docs/specs/2026-05-07-buiy-foundation/accessibility.md diff --git a/docs/prior-art/accesskit/history.md b/docs/prior-art/accesskit/history.md index 73b1ac9..8d71a36 100644 --- a/docs/prior-art/accesskit/history.md +++ b/docs/prior-art/accesskit/history.md @@ -104,4 +104,4 @@ Hedge: a comprehensive talk inventory was not assembled for this folder. AccessK - https://github.com/linebender/druid - https://pneumasolutions.com/about/ - https://nvaccess.org/about-nv-access/ -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md +- docs/specs/2026-05-07-buiy-foundation/architecture.md diff --git a/docs/prior-art/accesskit/integration.md b/docs/prior-art/accesskit/integration.md index 8e1c0a0..6bb7bdf 100644 --- a/docs/prior-art/accesskit/integration.md +++ b/docs/prior-art/accesskit/integration.md @@ -88,6 +88,6 @@ The Buiy spec states: "AccessKit allows exactly one tree per `accesskit_winit::A - https://github.com/iced-rs/iced/pulls?q=accesskit - https://github.com/iced-rs/iced/blob/master/CHANGELOG.md - https://raw.githubusercontent.com/marc2332/freya/main/Cargo.toml -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md -- /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/cross-cutting.md +- docs/specs/2026-05-07-buiy-foundation/accessibility.md +- docs/specs/2026-05-07-buiy-foundation/architecture.md +- docs/specs/2026-05-07-buiy-foundation/cross-cutting.md diff --git a/docs/prior-art/accesskit/platform-adapters.md b/docs/prior-art/accesskit/platform-adapters.md index f24279d..3f087da 100644 --- a/docs/prior-art/accesskit/platform-adapters.md +++ b/docs/prior-art/accesskit/platform-adapters.md @@ -144,5 +144,5 @@ All constructors **panic if the window is already visible** — this is the Acce - macOS adapter issue #520 (ListBox selected state): https://github.com/AccessKit/accesskit/issues/520 - `accesskit_winit` 0.33.0 docs and release notes: https://docs.rs/accesskit_winit/0.33.0/accesskit_winit/ - NLnet NGI0 Commons Fund acknowledgement (iOS adapter and AT-SPI funding): https://nlnet.nl/project/ -- Buiy spec — platform-staged v1 commitment: `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md` §2.9 +- Buiy spec — platform-staged v1 commitment: `docs/specs/2026-05-07-buiy-foundation/architecture.md` §2.9 - Sibling: [architecture.md](architecture.md), [tree-model.md](tree-model.md), [api.md](api.md) diff --git a/docs/prior-art/accesskit/tree-model.md b/docs/prior-art/accesskit/tree-model.md index 9ea21e1..5ab40e6 100644 --- a/docs/prior-art/accesskit/tree-model.md +++ b/docs/prior-art/accesskit/tree-model.md @@ -140,5 +140,5 @@ For Buiy specifically: - `accesskit` 0.24.0 docs.rs top-level item list (structs + enums + traits): https://docs.rs/accesskit/0.24.0/accesskit/ - `accesskit_consumer` 0.36.0 release notes (LocalNodeId / TreeId lookup; iOS adapter support): https://github.com/AccessKit/accesskit/releases - AccessKit README "single-line and multi-line text input controls … but not rich text or hypertext" limitation: https://github.com/AccessKit/accesskit/blob/main/README.md -- Buiy ARIA-1.2 taxonomy: `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md` +- Buiy ARIA-1.2 taxonomy: `docs/specs/2026-05-07-buiy-foundation/accessibility.md` - Sibling: [architecture.md](architecture.md), [platform-adapters.md](platform-adapters.md), [api.md](api.md) diff --git a/docs/prior-art/bevy-a11y/README.md b/docs/prior-art/bevy-a11y/README.md new file mode 100644 index 0000000..4b93614 --- /dev/null +++ b/docs/prior-art/bevy-a11y/README.md @@ -0,0 +1,80 @@ +**Date:** 2026-05-22 +**Status:** active +**Subject:** bevy_a11y — Bevy's producer-side accessibility plugin surface; the `AccessibilityNode` megacomponent case study that anchors Buiy's "no megacomponents" rule + +# bevy_a11y + +`bevy_a11y` is the official accessibility crate in the Bevy engine workspace (`bevyengine/bevy`). Structurally it is a **single-file glue crate**: it installs an activation gate (`AccessibilityRequested`), a management flag (`ManageAccessibilityUpdates`), a one-variant system set (`AccessibilitySystems::Update`), the `ActionRequest` event newtype, and the `AccessibilityNode(pub accesskit::Node)` megacomponent — and almost no logic. The real work lives in two sibling crates: per-window adapter ownership, tree-build, and `ActionRequest` plumbing in [`bevy_winit/src/accessibility.rs`](https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/accessibility.rs), and the producer-side per-widget role/label/value logic in [`bevy_ui/src/accessibility.rs`](https://github.com/bevyengine/bevy/blob/main/crates/bevy_ui/src/accessibility.rs). When this folder says "bevy_a11y" architecturally, it means the producer-side accessibility plugin surface owned across those three crates, of which `bevy_a11y` is the smallest member but the API anchor. The corpus exists because **Buiy replaces bevy_a11y for its own windows** — Buiy is its own AccessKit producer, talking to `accesskit_winit` directly per window, with a fully decomposed component vocabulary — and bevy_a11y is the upstream design that decision is measured against (see foundation [`architecture.md` § 2.4 / § 2.6](../../specs/2026-05-07-buiy-foundation/architecture.md)). + +**Honest assessment.** bevy_a11y has been a default sub-plugin in `DefaultPlugins` since Bevy 0.10 (March 2023, PR #6874) and provides real, durable AccessKit integration with a sound activation-gating pattern (skip tree-build until an assistive technology attaches) that Buiy borrows. But its central component, `AccessibilityNode(pub accesskit::Node)`, is the prototypical BSN-hostile megacomponent: ~200 properties reachable only through `set_()` / `clear_()` method calls, no per-property change-detection, no compositional patching — issue [#17644](https://github.com/bevyengine/bevy/issues/17644) (viridia, 2025-02-02) named it directly. The "fix," PR [#24308](https://github.com/bevyengine/bevy/pull/24308) (merged 2026-05-21, milestone 0.19), decomposed exactly **one** field — `AccessibleLabel` mirrors into `AccessibilityNode` via component hooks — and the PR author called it `"not a 100% fix, but ... good enough to close the ticket."` The megacomponent still exists in its original shape on main HEAD as of 2026-05-22. The upstream decomposition trajectory is "split one field per release as the pain is hit"; Buiy's foundation spec commits to full decomposition from day one, which is why the two component vocabularies share zero names and will not converge. + +## Key facts (verified 2026-05-22) + +| Fact | Value | +|---|---| +| Crate | `bevy_a11y` (workspace crate inside `bevyengine/bevy`) | +| Shape | Single-file crate (`src/lib.rs`); resources + one system set + one megacomponent + one event newtype, no systems of its own | +| License | MIT OR Apache-2.0 | +| Latest stable | 0.18.1 | +| Pre-release | 0.19.0-rc.2 (2026-05-22) | +| Workspace HEAD | 0.19.0-dev | +| Default-plugin posture | Sub-plugin of `DefaultPlugins` since Bevy 0.10 (disable via `disable::()`) | +| AccessKit integration landed | Bevy 0.10, 2023-03-01, PR #6874 (Nolan Darilek / `ndarilek`) | +| Central component | `AccessibilityNode(pub accesskit::Node)` — the megacomponent (~200 method-gated properties) | +| BSN-hostility issue | [#17644](https://github.com/bevyengine/bevy/issues/17644) "Design of bevy_a11y is BSN-unfriendly" (viridia, 2025-02-02) | +| Partial fix | [#24308](https://github.com/bevyengine/bevy/pull/24308) `AccessibleLabel` (merged 2026-05-21, milestone 0.19) — decomposes the label field only; `AccessibilityNode` unchanged | +| `accesskit` pin | 0.21 (v0.18.1) → 0.24 (HEAD); verify per release | +| Adapter ownership | `accesskit_winit::Adapter` stored thread-local in `bevy_winit`, keyed by window `Entity` (the adapter is `!Send`) | +| Multi-window | Real and structural — one adapter / activation handler / action queue per window | +| Foundation stewardship | Bevy Foundation (Washington 501(c)(3)); a11y SME contributors + AccessKit / Pneuma Solutions relationship | + +## Strengths + +- **Sound activation gate.** `AccessibilityRequested` (atomic bool) short-circuits tree-build until an AT actually attaches, with `adapter.update_if_active(|| tree_update)` skipping the build closure entirely otherwise. This is the cost-amortisation lever Buiy borrows (see [`docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md)). +- **Real per-window multi-adapter support.** Each window gets its own adapter, activation handler, and action queue, keyed by entity — the structural pattern Buiy adopts (keyed by platform `WindowId` instead, to survive entity respawn). +- **Shipped, default-on, durable.** AccessKit has been wired since 0.10; the integration is not experimental. + +## Weaknesses + +- **The `AccessibilityNode` megacomponent.** One component holds every a11y property; properties are method-gated (`set_*` / `clear_*`), not public fields; change-detection is coarse (any setter dirties the whole node); BSN cannot author or patch per-property. The plugin even calls `allow_ambiguous_component::()` to silence Bevy's own ambiguity detector because multiple systems mutate the one component per frame. +- **Decomposition is incremental and lazy.** PR #24308 split out a single field (`AccessibleLabel`) and locked it into the megacomponent's lifecycle via `#[require(AccessibilityNode)]`. Role, value, description, bounds, all state flags, and all relations still flow through the megacomponent. +- **Single-occupant adapter slot.** `accesskit_winit::Adapter` accepts exactly one tree per window with no merge protocol — two producers structurally cannot share a window, forcing per-window coexistence (the only design AccessKit's shape allows; see [`coexistence.md`](coexistence.md)). +- **Owns almost nothing for focus.** Focus tracking lives in `bevy_input_focus`, not `bevy_a11y` (see [`focus-model.md`](focus-model.md)). + +## Lessons for Buiy + +There is no `lessons.md` in this folder; the consult-this-when-designing material lives in **[`component-model-incident.md`](component-model-incident.md)** (the #17644 / #24308 case study in depth), with the cross-folder borrow/avoid tables in [`docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) and [`docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) (Avoid row "Megacomponents that are BSN-hostile"). All Buiy-side statements below are **sourced to the foundation spec as target state, not decided here**: + +- **Validates** — the activation-gate + per-window-adapter pattern. Buiy keeps both shapes (foundation [`architecture.md` § 2.6](../../specs/2026-05-07-buiy-foundation/architecture.md)); #17644 is the load-bearing validation of the "small, public-fielded, observable, decomposed component" rule (foundation [`architecture.md` § 2.4](../../specs/2026-05-07-buiy-foundation/architecture.md)). +- **Avoid** — the megacomponent shape (private-fielded, method-gated, bundle-everything) and the layer-over-bevy_a11y integration path (three indirection hops, two component vocabularies, a per-frame translation tax that earns nothing over talking to `accesskit_winit` directly). +- **Borrow** — the activation gate, the closure-form `update_if_active` build skip, and per-window adapter ownership. Buiy's target component set (`A11yRole` / `A11yLabel` / `A11yDescription` / `A11yStates` / `A11yRelations`, per foundation [`accessibility.md`](../../specs/2026-05-07-buiy-foundation/accessibility.md)) shares zero names with bevy_a11y's; the divergence is structural, not a reaction to #17644 being incompletely fixed. + +## Reading order + +| File | Subject | +|---|---| +| [`README.md`](README.md) | This file — overview, key facts, strengths/weaknesses, lessons pointer, reading order. | +| [`component-model-incident.md`](component-model-incident.md) | **The consult-this-when-designing case study.** Issue #17644, PR #24308, and why Buiy still replaces bevy_a11y after the partial fix. | +| [`architecture.md`](architecture.md) | Structural shape: the single-file crate, the plugin, the system set, the activation gate, the megacomponent, per-window adapter ownership, tree-update push. | +| [`api.md`](api.md) | Public API surface (resources, components, events, system set, plugin) as of v0.18.1 + main HEAD. | +| [`focus-model.md`](focus-model.md) | Focus in the Bevy stack — what `bevy_a11y` owns (almost nothing), what `bevy_input_focus` owns, what `bevy_feathers` styles, where Buiy diverges. | +| [`coexistence.md`](coexistence.md) | bevy_a11y / Buiy per-window coexistence — adapter-slot single-occupancy, the suppression rule, no shared-window coordinator. | +| [`distribution.md`](distribution.md) | Distribution shape: crate features, default-plugin posture, MSRV, platform support. | +| [`ecosystem.md`](ecosystem.md) | Who actually depends on it, the download-vs-deployment disconnect, adjacent Bevy crates, other game-engine a11y stacks. | +| [`governance.md`](governance.md) | Stewardship within the Bevy Foundation, SME contributors, AccessKit / Pneuma Solutions relationship, future-direction signals. | +| [`history.md`](history.md) | Release history from Bevy 0.10 (March 2023) through 0.19.0-rc.2, with the #17644 → #24308 episode in focus. | +| [`comparisons.md`](comparisons.md) | Side-by-side with Buiy's planned model, peer AccessKit producers (egui, Slint, Freya, Xilem/Masonry, Godot), and non-AccessKit game-engine stacks (Unity, Unreal). | +| [`critiques.md`](critiques.md) | Honest critiques: the megacomponent legacy, post-#24308 reality, coverage gaps, multi-window concerns, performance unknowns, Wayland/X11 divergence, the deployment gap. | +| [`open-problems.md`](open-problems.md) | Unresolved questions the integration leaves on the floor, organized by the area each touches in the Buiy foundation spec. | + +## Sources + +- `bevy_a11y` lib.rs (main HEAD, 0.19.0-dev) — https://github.com/bevyengine/bevy/blob/main/crates/bevy_a11y/src/lib.rs +- `bevy_winit/src/accessibility.rs` (main HEAD) — https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/accessibility.rs +- `bevy_ui/src/accessibility.rs` (main HEAD) — https://github.com/bevyengine/bevy/blob/main/crates/bevy_ui/src/accessibility.rs +- PR #6874 (AccessKit integration, Bevy 0.10, 2023-03) — https://github.com/bevyengine/bevy/pull/6874 +- Issue #17644 (BSN-unfriendly, viridia, 2025-02-02) — https://github.com/bevyengine/bevy/issues/17644 +- PR #24308 (Introduce AccessibleLabel, merged 2026-05-21, milestone 0.19) — https://github.com/bevyengine/bevy/pull/24308 +- AccessKit project — https://accesskit.dev +- Buiy foundation — architecture §2.4, §2.6: [`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) +- Buiy foundation — accessibility: [`../../specs/2026-05-07-buiy-foundation/accessibility.md`](../../specs/2026-05-07-buiy-foundation/accessibility.md) diff --git a/docs/prior-art/bevy-a11y/api.md b/docs/prior-art/bevy-a11y/api.md index e3a9099..5d3710b 100644 --- a/docs/prior-art/bevy-a11y/api.md +++ b/docs/prior-art/bevy-a11y/api.md @@ -2,7 +2,7 @@ **Status:** active **Subject:** bevy_a11y — public API surface (resources, components, events, system set, plugin) as of v0.18.1 stable + main HEAD (0.19.0-dev) -This file inventories what an app can reach when it depends on `bevy_a11y`. For architectural context see [`architecture.md`](architecture.md); for the BSN-unfriendliness story see [`component-model-incident.md`](component-model-incident.md); for how Buiy bypasses this API see [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.6. +This file inventories what an app can reach when it depends on `bevy_a11y`. For architectural context see [`architecture.md`](architecture.md); for the BSN-unfriendliness story see [`component-model-incident.md`](component-model-incident.md); for how Buiy bypasses this API see [`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.6. ## Crate item inventory @@ -98,7 +98,7 @@ fn toggle_disabled(mut q: Query<&mut AccessibilityNode, With>) { } ``` -The `Deref` + `DerefMut` impl is why this works — the component is a thin wrapper. The setter-zoo lives on `accesskit::Node`, not on `AccessibilityNode`. See [`/home/user/buiy/docs/prior-art/accesskit/api.md`](../accesskit/api.md) for the full setter inventory. +The `Deref` + `DerefMut` impl is why this works — the component is a thin wrapper. The setter-zoo lives on `accesskit::Node`, not on `AccessibilityNode`. See [`../accesskit/api.md`](../accesskit/api.md) for the full setter inventory. Change detection is on the `AccessibilityNode` component, so any method-call mutation flags the entire wrapper as changed. Per-field change-detection is not available. @@ -146,10 +146,10 @@ fn handle_actions(mut events: MessageReader) { } ``` -Lookup from `NodeId` → `Entity` is the app's responsibility. Bevy uses `Entity::to_bits()` as the producer's NodeId convention, so `Entity::from_bits(node_id.0)` is the typical inverse (though the producer can choose any NodeId scheme). The brittleness — no canonical lookup map, no resolver — is one reason Buiy routes `ActionRequest` directly to Buiy entities via its own action plumbing, bypassing this event bus (see [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.6). +Lookup from `NodeId` → `Entity` is the app's responsibility. Bevy uses `Entity::to_bits()` as the producer's NodeId convention, so `Entity::from_bits(node_id.0)` is the typical inverse (though the producer can choose any NodeId scheme). The brittleness — no canonical lookup map, no resolver — is one reason Buiy routes `ActionRequest` directly to Buiy entities via its own action plumbing, bypassing this event bus (see [`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.6). `accesskit::ActionRequest` carries: -- `action: accesskit::Action` (22-variant enum; see [`/home/user/buiy/docs/prior-art/accesskit/tree-model.md`](../accesskit/tree-model.md)) +- `action: accesskit::Action` (22-variant enum; see [`../accesskit/tree-model.md`](../accesskit/tree-model.md)) - `target: accesskit::NodeId` - `data: Option` (carries `SetTextSelection` `TextSelection`, `SetValue` value, scroll target, custom action data, etc.) @@ -189,7 +189,7 @@ There's no built-in action-dispatch layer; per-widget plumbing is what `bevy_ui/ | 0.18.1 (2026-03) | 0.21 | Same shape. | | 0.19.0-dev (main) | 0.24 | Same `bevy_a11y` shape. PR #24308 adds `AccessibleLabel` to `bevy_ui` (not `bevy_a11y`). | -The `bevy_a11y`-crate itself has been stable in shape for the last several releases; the underlying `accesskit` API changes drove the upgrade churn (NodeBuilder → Node was the 0.14/0.15 migration upstream; the recent 0.21 → 0.24 jump tracks AccessKit's faster cadence — see [`/home/user/buiy/docs/prior-art/accesskit/history.md`](../accesskit/history.md)). +The `bevy_a11y`-crate itself has been stable in shape for the last several releases; the underlying `accesskit` API changes drove the upgrade churn (NodeBuilder → Node was the 0.14/0.15 migration upstream; the recent 0.21 → 0.24 jump tracks AccessKit's faster cadence — see [`../accesskit/history.md`](../accesskit/history.md)). ## Cross-references @@ -197,8 +197,8 @@ The `bevy_a11y`-crate itself has been stable in shape for the last several relea - [`component-model-incident.md`](component-model-incident.md) — why the API has the inconsistent-setter shape - [`focus-model.md`](focus-model.md) — `bevy_input_focus` exposes `InputFocus` / `InputFocusVisible` separately (not via `bevy_a11y`) - [`coexistence.md`](coexistence.md) — `disable::()` vs `ManageAccessibilityUpdates = false` tradeoff -- [`/home/user/buiy/docs/prior-art/accesskit/api.md`](../accesskit/api.md) — the underlying AccessKit setter inventory the megacomponent wraps -- [`/home/user/buiy/docs/prior-art/accesskit/tree-model.md`](../accesskit/tree-model.md) — `Role`, `Action`, `ActionData`, tri-state enums +- [`../accesskit/api.md`](../accesskit/api.md) — the underlying AccessKit setter inventory the megacomponent wraps +- [`../accesskit/tree-model.md`](../accesskit/tree-model.md) — `Role`, `Action`, `ActionData`, tri-state enums ## Sources diff --git a/docs/prior-art/bevy-a11y/architecture.md b/docs/prior-art/bevy-a11y/architecture.md index 257df33..9d7a2c2 100644 --- a/docs/prior-art/bevy-a11y/architecture.md +++ b/docs/prior-art/bevy-a11y/architecture.md @@ -42,7 +42,7 @@ A one-variant enum. All accessibility systems hang off `AccessibilitySystems::Up - `poll_receivers` — drains the `WinitActionRequestHandlers` queues, converts `accesskit::ActionRequest` → Bevy `ActionRequest` message - `update_accessibility_nodes` — rebuilds the tree from `AccessibilityNode` components and pushes to the adapter via `update_if_active` -Order is roughly `window_closed` then `poll_receivers` then `update_accessibility_nodes`, all conditional on activation flags. This is *the* system set Buiy's `BuiySet::A11yUpdate` parallels; the activation-gating pattern is sound and Buiy borrows it (see [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — "AccessibilityRequested activation gate"). +Order is roughly `window_closed` then `poll_receivers` then `update_accessibility_nodes`, all conditional on activation flags. This is *the* system set Buiy's `BuiySet::A11yUpdate` parallels; the activation-gating pattern is sound and Buiy borrows it (see [`../accesskit/lessons.md`](../accesskit/lessons.md) — "AccessibilityRequested activation gate"). ## The activation gate — `AccessibilityRequested` @@ -74,7 +74,7 @@ The `allow_ambiguous_component::()` call in the plugin is a w /// `ActionRequest` as a Bevy `Event`. ``` -A thin newtype around `accesskit::ActionRequest`. Required because Bevy's `Event` (now `Message`) trait can't be derived on a foreign type. The newtype is created in `bevy_winit`'s `poll_receivers` system from queued action requests (see "Action handler routing" below) and surfaced as a Bevy event for apps to read. Buiy bypasses this newtype — Buiy's own action plumbing routes `accesskit::ActionRequest` directly to Buiy entities by `NodeId` (= `Entity::to_bits()`), no event-bus indirection (see [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.6). +A thin newtype around `accesskit::ActionRequest`. Required because Bevy's `Event` (now `Message`) trait can't be derived on a foreign type. The newtype is created in `bevy_winit`'s `poll_receivers` system from queued action requests (see "Action handler routing" below) and surfaced as a Bevy event for apps to read. Buiy bypasses this newtype — Buiy's own action plumbing routes `accesskit::ActionRequest` directly to Buiy entities by `NodeId` (= `Entity::to_bits()`), no event-bus indirection (see [`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.6). ## Per-window adapter ownership (lives in `bevy_winit`) @@ -146,8 +146,8 @@ This matters for Buiy: the upstream decomposition trajectory is "split one field - [`api.md`](api.md) — public API surface - [`coexistence.md`](coexistence.md) — per-window coexistence with Buiy - [`focus-model.md`](focus-model.md) — focus tracking (which mostly lives in `bevy_input_focus`, not `bevy_a11y`) -- [`/home/user/buiy/docs/prior-art/accesskit/architecture.md`](../accesskit/architecture.md) — the underlying AccessKit protocol -- [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — Buiy's borrow / avoid table for the AccessKit shape +- [`../accesskit/architecture.md`](../accesskit/architecture.md) — the underlying AccessKit protocol +- [`../accesskit/lessons.md`](../accesskit/lessons.md) — Buiy's borrow / avoid table for the AccessKit shape ## Sources diff --git a/docs/prior-art/bevy-a11y/coexistence.md b/docs/prior-art/bevy-a11y/coexistence.md index 1dcccbc..159d6c0 100644 --- a/docs/prior-art/bevy-a11y/coexistence.md +++ b/docs/prior-art/bevy-a11y/coexistence.md @@ -4,12 +4,12 @@ ## The structural constraint -AccessKit allows **exactly one tree per `accesskit_winit::Adapter` per window**. The adapter slot is single-occupant by design — there is no upstream merge protocol where two producers push subtrees that get glued together. See [`/home/user/buiy/docs/prior-art/accesskit/platform-adapters.md`](../accesskit/platform-adapters.md) for the long form on the AccessKit side; the relevant constraint for this file is: **two producers cannot share an adapter**. +AccessKit allows **exactly one tree per `accesskit_winit::Adapter` per window**. The adapter slot is single-occupant by design — there is no upstream merge protocol where two producers push subtrees that get glued together. See [`../accesskit/platform-adapters.md`](../accesskit/platform-adapters.md) for the long form on the AccessKit side; the relevant constraint for this file is: **two producers cannot share an adapter**. Two consequences: 1. On any given window, exactly one stack (bevy_a11y or Buiy) owns the adapter. -2. There is no "Buiy and bevy_a11y coexist on the same window with some coordinator" mode in v1. Buiy's spec ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/cross-cutting.md` § 3.18](../../specs/2026-05-07-buiy-foundation/cross-cutting.md)) commits to per-window-only coexistence; a coordinator is a deferred follow-up sub-spec (`buiy-coexistence-design`) if demand arises. +2. There is no "Buiy and bevy_a11y coexist on the same window with some coordinator" mode in v1. Buiy's spec ([`../../specs/2026-05-07-buiy-foundation/cross-cutting.md` § 3.18](../../specs/2026-05-07-buiy-foundation/cross-cutting.md)) commits to per-window-only coexistence; a coordinator is a deferred follow-up sub-spec (`buiy-coexistence-design`) if demand arises. ## The supported model @@ -95,7 +95,7 @@ The window's winit handle is preserved. The adapter is recreated. The AT may bri ## Open question -[`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/README.md` § 5](../../specs/2026-05-07-buiy-foundation/README.md) names two related open questions: +[`../../specs/2026-05-07-buiy-foundation/README.md` § 5](../../specs/2026-05-07-buiy-foundation/README.md) names two related open questions: - **AccessKit-adapter ownership when both stacks coexist same-window.** Currently the spec rules this out. If demand arises, `buiy-coexistence-design` defines the coordinator. - **Coexistence policy with `bevy_feathers` / `bevy_ui_widgets`.** Coexistence at the app level is committed; whether Buiy ships migration adapters from bevy_ui widgets is open. This applies symmetrically to bevy_a11y — Buiy ships no migration adapter from `AccessibilityNode` to Buiy's decomposed components. @@ -107,10 +107,10 @@ Both remain open. The committed rule is per-window single-stack. Coordinator-mer - [`architecture.md`](architecture.md) — bevy_a11y's per-window adapter mechanics (via `bevy_winit`) - [`component-model-incident.md`](component-model-incident.md) — why Buiy replaces rather than layers - [`api.md`](api.md) — `disable::()` and `ManageAccessibilityUpdates` API surface -- [`/home/user/buiy/docs/prior-art/accesskit/platform-adapters.md`](../accesskit/platform-adapters.md) — the single-occupant adapter constraint -- [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — "Per-window adapter ownership keyed by winit WindowId" -- [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md` § 2.6](../../specs/2026-05-07-buiy-foundation/architecture.md) — Buiy's committed rule -- [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/cross-cutting.md` § 3.18](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) — coexistence rules including the per-window-keyed state list +- [`../accesskit/platform-adapters.md`](../accesskit/platform-adapters.md) — the single-occupant adapter constraint +- [`../accesskit/lessons.md`](../accesskit/lessons.md) — "Per-window adapter ownership keyed by winit WindowId" +- [`../../specs/2026-05-07-buiy-foundation/architecture.md` § 2.6](../../specs/2026-05-07-buiy-foundation/architecture.md) — Buiy's committed rule +- [`../../specs/2026-05-07-buiy-foundation/cross-cutting.md` § 3.18](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) — coexistence rules including the per-window-keyed state list ## Sources diff --git a/docs/prior-art/bevy-a11y/comparisons.md b/docs/prior-art/bevy-a11y/comparisons.md index 3b6a3dc..90dc61b 100644 --- a/docs/prior-art/bevy-a11y/comparisons.md +++ b/docs/prior-art/bevy-a11y/comparisons.md @@ -6,7 +6,7 @@ This file does direct side-by-sides. Each row identifies how the other toolkit / engine wires accessibility, the key design difference vs `bevy_a11y`, and (where relevant) what Buiy borrows or rejects from that comparison. The honest finding: `bevy_a11y` is on the AccessKit-producer side of the divide with several Rust peers, and its main differentiator within that group is **the megacomponent surface** — the design choice that issue [#17644](https://github.com/bevyengine/bevy/issues/17644) named as the BSN-incompatibility. -For the AccessKit-side comparison-matrix detail, see [`prior-art/accesskit/ecosystem.md`](../accesskit/ecosystem.md) and [`prior-art/accesskit/comparisons.md`](../accesskit/comparisons.md). This file adds the producer-side ergonomics layer. +For the AccessKit-side comparison-matrix detail, see [`prior-art/accesskit/ecosystem.md`](../accesskit/ecosystem.md). This file adds the producer-side ergonomics layer. ## vs Buiy's planned a11y model @@ -121,6 +121,6 @@ Godot 4.5 (2025-09) added AccessKit-based screen-reader support via PR [#76829]( - Unity Accessibility module: https://docs.unity3d.com/Manual/com.unity.modules.accessibility.html, https://unity.com/blog/engine-platform/mobile-screen-reader-support-in-unity, Unity 6.3 native desktop screen reader: https://discussions.unity.com/t/native-desktop-screen-reader-support-now-available-in-unity-6-3/1681788. - Unreal Slate Screen Reader: https://dev.epicgames.com/documentation/en-us/unreal-engine/supporting-screen-readers-in-unreal-engine. - Godot AccessKit PR #76829: https://github.com/godotengine/godot/pull/76829, Godot 4.5 release: https://godotengine.org/releases/4.5/. -- AccessKit folder ecosystem + comparisons: [`prior-art/accesskit/ecosystem.md`](../accesskit/ecosystem.md), [`prior-art/accesskit/comparisons.md`](../accesskit/comparisons.md). +- AccessKit folder ecosystem + comparisons: [`prior-art/accesskit/ecosystem.md`](../accesskit/ecosystem.md). - Buiy foundation: [`accessibility.md`](../../specs/2026-05-07-buiy-foundation/accessibility.md), [`architecture.md § 2.6`](../../specs/2026-05-07-buiy-foundation/architecture.md), [`cross-cutting.md § 3.18`](../../specs/2026-05-07-buiy-foundation/cross-cutting.md). - Sibling files: [`distribution.md`](distribution.md), [`history.md`](history.md), [`component-model-incident.md`](component-model-incident.md), [`api.md`](api.md), [`coexistence.md`](coexistence.md), [`focus-model.md`](focus-model.md), [`ecosystem.md`](ecosystem.md), [`critiques.md`](critiques.md), [`open-problems.md`](open-problems.md). diff --git a/docs/prior-art/bevy-a11y/component-model-incident.md b/docs/prior-art/bevy-a11y/component-model-incident.md index 94aa151..6c3ae04 100644 --- a/docs/prior-art/bevy-a11y/component-model-incident.md +++ b/docs/prior-art/bevy-a11y/component-model-incident.md @@ -2,7 +2,7 @@ **Status:** active **Subject:** The bevy_a11y BSN-unfriendliness incident — issue #17644, PR #24308, and why Buiy still replaces bevy_a11y after the partial fix -This file is the canonical case study for Buiy's "no megacomponents" rule ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.4 "BSN-friendly components"). The incident has three acts: the original megacomponent design (2023-03), the BSN community recognising it as hostile (2025-02), and the partial fix (2026-05). Buiy still replaces bevy_a11y for its windows after the fix because the upstream decomposition trajectory is fundamentally different from Buiy's needed shape. +This file is the canonical case study for Buiy's "no megacomponents" rule ([`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.4 "BSN-friendly components"). The incident has three acts: the original megacomponent design (2023-03), the BSN community recognising it as hostile (2025-02), and the partial fix (2026-05). Buiy still replaces bevy_a11y for its windows after the fix because the upstream decomposition trajectory is fundamentally different from Buiy's needed shape. ## Act 1: the original megacomponent (Bevy 0.10, March 2023) @@ -37,7 +37,7 @@ On 2025-02-02, viridia opened issue [#17644](https://github.com/bevyengine/bevy/ The combination is the BSN-hostility complaint. Components with private fields, inconsistent setters, and bundled-everything-into-one are exactly the shape BSN cannot author or patch by composition. -cart's BSN philosophy ([discussion #14437](https://github.com/bevyengine/bevy/discussions/14437)) explicitly calls for "ordinary properties which can be merged and patched" — `AccessibilityNode` is the prototypical violation in the Bevy codebase, which is why it's the named target. See [`/home/user/buiy/docs/prior-art/bevy-ui/component-model.md`](../bevy-ui/component-model.md) for the parallel decomposition story on bevy_ui's own components (`BackgroundColor`, `BorderColor`, `Outline`, `BoxShadow` all separate; `BorderRadius` reverted from separate-component to field-on-`Node` in 0.18, the non-monotonic decomposition pitfall). +cart's BSN philosophy ([discussion #14437](https://github.com/bevyengine/bevy/discussions/14437)) explicitly calls for "ordinary properties which can be merged and patched" — `AccessibilityNode` is the prototypical violation in the Bevy codebase, which is why it's the named target. See [`../bevy-ui/component-model.md`](../bevy-ui/component-model.md) for the parallel decomposition story on bevy_ui's own components (`BackgroundColor`, `BorderColor`, `Outline`, `BoxShadow` all separate; `BorderRadius` reverted from separate-component to field-on-`Node` in 0.18, the non-monotonic decomposition pitfall). ## Act 3: the partial fix (PR #24308, merged 2026-05-21, milestone 0.19) @@ -86,7 +86,7 @@ What the fix gives: What the fix does not give: - Role, value, description, bounds, transform, all state flags (checked, disabled, expanded, selected, busy, hidden, invalid, …), all relations (labelled_by, described_by, controls, owns, flow_to, …), live-region politeness, sort direction, autocomplete, popup-target — every other field still lives inside `AccessibilityNode` as method-call-mutated state. - A BSN template that wants to "make this widget disabled" still cannot do so by composition; it still has to either reach into `AccessibilityNode` via a system or rely on per-widget systems in `bevy_ui/src/accessibility.rs` to set the field. -- The non-monotonic-decomposition risk (see [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) Avoid row) — if more `Accessible` components get split out over time, each is a breaking change for downstream consumers and another opportunity for reversal. +- The non-monotonic-decomposition risk (see [`../bevy-ui/lessons.md`](../bevy-ui/lessons.md) Avoid row) — if more `Accessible` components get split out over time, each is a breaking change for downstream consumers and another opportunity for reversal. The trajectory is "decompose lazily, one field per release as someone hits the pain." Three years from now, bevy_a11y may have `AccessibleLabel`, `AccessibleRole`, `AccessibleDescription`, `AccessibleStates`, … — or it may have stopped at `AccessibleLabel` because the per-widget systems in `bevy_ui` handle the rest "well enough." Either trajectory is incompatible with Buiy's day-one decomposition. @@ -103,7 +103,7 @@ Buiy's foundation spec ([`accessibility.md`](../../specs/2026-05-07-buiy-foundat - `A11yRole` — `accesskit::Role` selector, foundation-tier. - `A11yLabel` — accessible name input (per ACCNAME 1.2 source priority). - `A11yDescription` — accessible description input. -- `A11yStates` — tri-state flags for checked / expanded / selected / busy / invalid / disabled / hidden, encoded with the `Toggled` / `Option` / `Invalid` enums per AccessKit's tri-state model (see [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) Avoid rows). +- `A11yStates` — tri-state flags for checked / expanded / selected / busy / invalid / disabled / hidden, encoded with the `Toggled` / `Option` / `Invalid` enums per AccessKit's tri-state model (see [`../accesskit/lessons.md`](../accesskit/lessons.md) Avoid rows). - `A11yRelations` — `labelled_by`, `described_by`, `controls`, `owns`, `flow_to`, `active_descendant`, `error_message`, `details`, `popup_for`, etc. - Live-region politeness as a separate component on the announcer entity, not on every node. @@ -117,22 +117,22 @@ The AccessKit producer-protocol shape is the actual integration target. AccessKi - A bridge system reflects Buiy components into bevy_a11y's `AccessibilityNode` (or, per the partial-decomposition trajectory, into `AccessibleLabel` + future siblings + remaining `AccessibilityNode` fields). - bevy_winit's `update_accessibility_nodes` reads `AccessibilityNode`s and builds the `TreeUpdate`. -Three indirection hops, two component vocabularies, and a per-frame translation tax. None of this earns anything over Buiy talking to `accesskit_winit` directly. See [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — "AccessKit-first, talk-to-accesskit_winit-directly." +Three indirection hops, two component vocabularies, and a per-frame translation tax. None of this earns anything over Buiy talking to `accesskit_winit` directly. See [`../accesskit/lessons.md`](../accesskit/lessons.md) — "AccessKit-first, talk-to-accesskit_winit-directly." ### 3. The adapter slot is structurally single-occupant -`accesskit_winit::Adapter` accepts exactly one tree per window. Two producers cannot push to the same adapter — there's no merge protocol. So even if Buiy *wanted* to layer over bevy_a11y on a shared window, AccessKit's structural shape forbids it. Per-window coexistence (one stack per window, no shared windows) is the only design AccessKit's shape allows. See [`coexistence.md`](coexistence.md) for the long form and [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/cross-cutting.md` § 3.18](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) for the committed Buiy rule. +`accesskit_winit::Adapter` accepts exactly one tree per window. Two producers cannot push to the same adapter — there's no merge protocol. So even if Buiy *wanted* to layer over bevy_a11y on a shared window, AccessKit's structural shape forbids it. Per-window coexistence (one stack per window, no shared windows) is the only design AccessKit's shape allows. See [`coexistence.md`](coexistence.md) for the long form and [`../../specs/2026-05-07-buiy-foundation/cross-cutting.md` § 3.18](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) for the committed Buiy rule. ## The Buiy "no megacomponents" rule, restated -From [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.4: every Buiy component is **small, public-fielded, observable, decomposed**. The #17644 / #24308 incident is the case study cited every time this rule comes up. Concretely it means: +From [`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.4: every Buiy component is **small, public-fielded, observable, decomposed**. The #17644 / #24308 incident is the case study cited every time this rule comes up. Concretely it means: - **Small.** A component owns one concept (a label, a role, a set of related state flags). Not "all of accessibility." - **Public-fielded.** Fields are `pub`, not method-gated. BSN, reflection, and direct ECS access all see the same thing. - **Observable.** Per-component change-detection is meaningful — touching one property doesn't dirty unrelated properties. - **Decomposed.** Independent properties live in independent components. Required-components and on-insert/on-remove hooks compose them when needed. -The constraint applies regardless of BSN's status (see [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) — top of file, on BSN-not-yet-landed). #17644 demonstrates the cost of retrofitting; #24308 demonstrates the friction of retrofitting partially under release-cycle pressure. Buiy pays the small-decomposed-component tax in advance. +The constraint applies regardless of BSN's status (see [`../bevy-ui/lessons.md`](../bevy-ui/lessons.md) — top of file, on BSN-not-yet-landed). #17644 demonstrates the cost of retrofitting; #24308 demonstrates the friction of retrofitting partially under release-cycle pressure. Buiy pays the small-decomposed-component tax in advance. ## Cross-references @@ -141,9 +141,9 @@ The constraint applies regardless of BSN's status (see [`/home/user/buiy/docs/pr - [`coexistence.md`](coexistence.md) — why "layer over" is structurally impossible - [`focus-model.md`](focus-model.md) — focus mostly lives in `bevy_input_focus`, not `bevy_a11y` - Sibling [`critiques.md`](critiques.md) — Agent B's longer pushback synthesis -- [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — the AccessKit-side lessons that say "decomposed is the only shape that maps cleanly onto AccessKit's setter-rich Node API" -- [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) — Avoid row "Megacomponents that are BSN-hostile" -- [`/home/user/buiy/docs/prior-art/bevy-ui/component-model.md`](../bevy-ui/component-model.md) — bevy_ui's own decomposition history (BackgroundColor, BorderColor, BorderRadius reversal) +- [`../accesskit/lessons.md`](../accesskit/lessons.md) — the AccessKit-side lessons that say "decomposed is the only shape that maps cleanly onto AccessKit's setter-rich Node API" +- [`../bevy-ui/lessons.md`](../bevy-ui/lessons.md) — Avoid row "Megacomponents that are BSN-hostile" +- [`../bevy-ui/component-model.md`](../bevy-ui/component-model.md) — bevy_ui's own decomposition history (BackgroundColor, BorderColor, BorderRadius reversal) ## Sources diff --git a/docs/prior-art/bevy-a11y/focus-model.md b/docs/prior-art/bevy-a11y/focus-model.md index f1b639a..9fc7dc6 100644 --- a/docs/prior-art/bevy-a11y/focus-model.md +++ b/docs/prior-art/bevy-a11y/focus-model.md @@ -58,7 +58,7 @@ This is what gamepad users / arrow-key users get for spatial movement. It runs i `bevy_feathers` is Bevy's first-party styled-widget catalog (post-0.18). Its `:focus-visible` styling reads `InputFocusVisible` (the `bevy_input_focus` resource) and `IsFocused` (the trait) to decide whether to render the focus ring. The styling is per-widget; there is no unified focus-ring primitive. -Per [`/home/user/buiy/docs/prior-art/bevy-feathers/`](../bevy-feathers/) (sibling folder), bevy_feathers' focus visualization is intentionally minimal — a default outline color, no positioning rules, no contrast-checking against background. Per the foundation spec ([`accessibility.md`](../../specs/2026-05-07-buiy-foundation/accessibility.md)), Buiy commits to ≥2 px perimeter, ≥3:1 contrast vs unfocused (WCAG 2.4.11); bevy_feathers does not. +Per [`../bevy-feathers/`](../bevy-feathers/) (sibling folder), bevy_feathers' focus visualization is intentionally minimal — a default outline color, no positioning rules, no contrast-checking against background. Per the foundation spec ([`accessibility.md`](../../specs/2026-05-07-buiy-foundation/accessibility.md)), Buiy commits to ≥2 px perimeter, ≥3:1 contrast vs unfocused (WCAG 2.4.11); bevy_feathers does not. ## What's missing from the Bevy focus stack (relative to web / APG / Buiy needs) @@ -80,7 +80,7 @@ Each of these is **foundation-tier in Buiy** ([`accessibility.md`](../../specs/2 ## Buiy's focus model — what it owns -Per [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.3 and [`accessibility.md`](../../specs/2026-05-07-buiy-foundation/accessibility.md) "Focus management": +Per [`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.3 and [`accessibility.md`](../../specs/2026-05-07-buiy-foundation/accessibility.md) "Focus management": - **Single focus tree per Buiy window**, derived from the Buiy hierarchy, with `:focus-visible` semantics derived from input-source tracking (last input was keyboard or programmatic → `focus-visible`; last input was pointer → focus but not `focus-visible`). - **Focus traps** automatic for `Dialog` / `AlertDialog`. Inert subtrees excluded. @@ -93,7 +93,7 @@ Per [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](.. - **Focus ring** ≥2 px perimeter, ≥3:1 contrast vs unfocused (WCAG 2.4.11), with per-theme tokens. - **Skip-link primitive** as a Buiy widget (visible on focus, jumps to main / a region). -The `TreeUpdate.focus: NodeId` field in AccessKit is set every frame from Buiy's focus state (Buiy's `Entity::to_bits()` is the NodeId). Whether the focus *changed* or not, the field is set on every update — AccessKit treats the focus field as authoritative-per-update, not as a transition signal (see [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — "Treating `is_focused` as a node-state field" pitfall, mitigation: focus is `TreeUpdate.focus`, not a per-node bool). +The `TreeUpdate.focus: NodeId` field in AccessKit is set every frame from Buiy's focus state (Buiy's `Entity::to_bits()` is the NodeId). Whether the focus *changed* or not, the field is set on every update — AccessKit treats the focus field as authoritative-per-update, not as a transition signal (see [`../accesskit/lessons.md`](../accesskit/lessons.md) — "Treating `is_focused` as a node-state field" pitfall, mitigation: focus is `TreeUpdate.focus`, not a per-node bool). ## Why Buiy can't borrow `bevy_input_focus` @@ -113,10 +113,10 @@ Net: Buiy owns its focus tree. `bevy_input_focus` continues to exist for bevy_ui - [`api.md`](api.md) — bevy_a11y has no focus API - [`coexistence.md`](coexistence.md) — Buiy windows don't use `bevy_input_focus` either - [`component-model-incident.md`](component-model-incident.md) — separate but related case study (the megacomponent problem) -- [`/home/user/buiy/docs/prior-art/accesskit/tree-model.md`](../accesskit/tree-model.md) — `Tree.focus: NodeId` semantics -- [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — focus-as-`TreeUpdate.focus` pitfall row -- [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md` § 2.3](../../specs/2026-05-07-buiy-foundation/architecture.md) — Buiy focus model -- [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md`](../../specs/2026-05-07-buiy-foundation/accessibility.md) — focus-management feature list +- [`../accesskit/tree-model.md`](../accesskit/tree-model.md) — `Tree.focus: NodeId` semantics +- [`../accesskit/lessons.md`](../accesskit/lessons.md) — focus-as-`TreeUpdate.focus` pitfall row +- [`../../specs/2026-05-07-buiy-foundation/architecture.md` § 2.3](../../specs/2026-05-07-buiy-foundation/architecture.md) — Buiy focus model +- [`../../specs/2026-05-07-buiy-foundation/accessibility.md`](../../specs/2026-05-07-buiy-foundation/accessibility.md) — focus-management feature list ## Sources diff --git a/docs/prior-art/bevy-egui/critiques.md b/docs/prior-art/bevy-egui/critiques.md index 598e993..2ef6ccf 100644 --- a/docs/prior-art/bevy-egui/critiques.md +++ b/docs/prior-art/bevy-egui/critiques.md @@ -99,7 +99,7 @@ No published WCAG 2.2 conformance audit exists for bevy_egui (or for egui upstre - **WCAG 4.1.2 Name, Role, Value** — partial via AccessKit; depends on the role mapping completeness. - **WCAG 4.1.3 Status Messages** — live-region semantics are awkward in immediate-mode (see § "Accessibility"). -Buiy commits to WCAG 2.2 AA per-widget mapping in [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md`](../../specs/2026-05-07-buiy-foundation/); bevy_egui has no comparable artifact. +Buiy commits to WCAG 2.2 AA per-widget mapping in [`../../specs/2026-05-07-buiy-foundation/`](../../specs/2026-05-07-buiy-foundation/); bevy_egui has no comparable artifact. ## Animation / transition primitives are weak @@ -131,7 +131,7 @@ For dev tools and debug overlays this simplicity is a feature — egui-the-parad Aggregating the above: bevy_egui's strengths (immediate-mode ergonomics, fast iteration, low API surface) cluster on the **developer-facing UI** axis. Its weaknesses (styling rigidity, a11y rough edges, layout simplicity, animation gaps, performance at scale, no flagship game using it) cluster on the **player-facing production UI** axis. The community has internalized this: bevy_egui dominates as a dev-tool substrate (bevy-inspector-egui, editor experiments, debug overlays) and remains rare as a shipped-game-UI substrate. -For Buiy this informs scope: Buiy's "Game and app, both" goal ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/README.md`](../../specs/2026-05-07-buiy-foundation/README.md) goal 6) explicitly targets the production-UI axis that bevy_egui struggles with. See [`comparisons.md`](comparisons.md) § "vs Buiy" and [`open-problems.md`](open-problems.md) § "The production game UI gap." +For Buiy this informs scope: Buiy's "Game and app, both" goal ([`../../specs/2026-05-07-buiy-foundation/README.md`](../../specs/2026-05-07-buiy-foundation/README.md) goal 6) explicitly targets the production-UI axis that bevy_egui struggles with. See [`comparisons.md`](comparisons.md) § "vs Buiy" and [`open-problems.md`](open-problems.md) § "The production game UI gap." ## Sources diff --git a/docs/prior-art/bevy-egui/immediate-mode-paradigm.md b/docs/prior-art/bevy-egui/immediate-mode-paradigm.md index 164ccf1..19f7fdc 100644 --- a/docs/prior-art/bevy-egui/immediate-mode-paradigm.md +++ b/docs/prior-art/bevy-egui/immediate-mode-paradigm.md @@ -111,7 +111,7 @@ The lineage is clear: every immediate-mode UI library since 2005 inherits the Ca ## Why Buiy is retained-mode (the foundation spec's reasoning) -Buiy's foundation spec ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.3) commits to a retained component model — `buiy::Node`, `buiy::Style`, focus components, a11y components, animation components — and ECS + BSN authoring (§ 2.4). The reasoning, restated through the immediate-mode lens: +Buiy's foundation spec ([`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.3) commits to a retained component model — `buiy::Node`, `buiy::Style`, focus components, a11y components, animation components — and ECS + BSN authoring (§ 2.4). The reasoning, restated through the immediate-mode lens: 1. **Web-platform parity** ([README.md § 1.1](../../specs/2026-05-07-buiy-foundation/README.md)). The web platform is retained-mode — the DOM is a persistent tree, CSS cascades on stable nodes, layout invalidation is on dirty subtrees, accessibility surfaces a persistent role tree. Parity requires a persistent surface to mirror. 2. **Accessibility tree shape.** AccessKit nodes survive frames; ATs are happier with stable IDs. Buiy's `A11yRole` / `A11yLabel` / `A11yStates` components are entity-backed and survive frames by construction ([architecture.md § 2.6](../../specs/2026-05-07-buiy-foundation/architecture.md)). diff --git a/docs/prior-art/bevy-egui/lessons.md b/docs/prior-art/bevy-egui/lessons.md index 28d07a4..38c9b67 100644 --- a/docs/prior-art/bevy-egui/lessons.md +++ b/docs/prior-art/bevy-egui/lessons.md @@ -14,7 +14,7 @@ bevy_egui validates **immediate-mode as the right paradigm for dev tools** — d bevy_egui *also* validates **retained-mode as the right paradigm for production game UI** — by absence. **No flagship commercial Bevy game ships its production player-facing UI on bevy_egui.** Tiny Glade wrote its own UI renderer. Foresight Spar wrote its own. The Bevy editor experiments are shifting toward `bevy_feathers` (in-tree retained-mode) and away from bevy_egui. The cluster of weaknesses — flat `Visuals` (no token system), animation primitives that stop at `animate_bool`, layout simpler than Flexbox/Grid, opt-in AccessKit with structural per-frame-rebuild limits, hit-target sizes tuned for mouse precision, "looks like egui" homogeneity — is the production-UI-grade-polish gap. See [`critiques.md`](critiques.md), [`open-problems.md`](open-problems.md) § "The production game UI gap," [`ecosystem.md`](ecosystem.md) § "Commercial Bevy releases." -**Buiy's retained-mode bet does not compete with bevy_egui; the two coexist.** Most real Bevy projects will use both — bevy_egui for dev overlays / inspectors / editor panels, Buiy (or `bevy_ui` today) for shipped player-facing UI. See [`use-cases.md`](use-cases.md) § "The dev mode + ship mode pattern" and [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/cross-cutting.md`](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) § 3.18 (the Buiy / bevy_ui no-mixing-in-one-window rule explicitly does *not* apply to bevy_egui — bevy_egui's no-default-AccessKit + flat-tessellated-output composes cleanly with anything else on screen). +**Buiy's retained-mode bet does not compete with bevy_egui; the two coexist.** Most real Bevy projects will use both — bevy_egui for dev overlays / inspectors / editor panels, Buiy (or `bevy_ui` today) for shipped player-facing UI. See [`use-cases.md`](use-cases.md) § "The dev mode + ship mode pattern" and [`../../specs/2026-05-07-buiy-foundation/cross-cutting.md`](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) § 3.18 (the Buiy / bevy_ui no-mixing-in-one-window rule explicitly does *not* apply to bevy_egui — bevy_egui's no-default-AccessKit + flat-tessellated-output composes cleanly with anything else on screen). The follow-on for every Buiy spec: **stop asking "should Buiy do X better than bevy_egui?" and start asking "does X belong on the production-UI axis Buiy targets, or on the dev-tool axis bevy_egui already owns?"** Most dev tooling answers "ship it on bevy_egui" — even Buiy's own inspector / focus visualizer / theme editor / contrast checker are candidates for bevy_egui hosting (with dogfooding on Buiy as a separable choice). See [`use-cases.md`](use-cases.md) § "What this means for the prior-art corpus." diff --git a/docs/prior-art/bevy-egui/open-problems.md b/docs/prior-art/bevy-egui/open-problems.md index 22b851f..ab49390 100644 --- a/docs/prior-art/bevy-egui/open-problems.md +++ b/docs/prior-art/bevy-egui/open-problems.md @@ -134,7 +134,7 @@ The gap is structural, not incidental. The cluster of weaknesses ([`critiques.md The path of least resistance is (3): the production-UI niche gets served by retained-mode UIs (bevy_ui, bevy_feathers, bevy_lunex, Buiy), while immediate-mode bevy_egui continues to dominate the dev-tool niche. This is the implicit ecosystem trajectory; no public decision has been published but the editor-roadmap signaling (see [`ecosystem.md`](ecosystem.md) § "Bevy editor experiments") points this way. -For Buiy: the production-game-UI gap is exactly the slot Buiy targets. The Buiy spec's "Game and app, both" goal ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/README.md`](../../specs/2026-05-07-buiy-foundation/README.md) goal 6) and the parallel-stack web-platform-parity stance are the design response to this gap. +For Buiy: the production-game-UI gap is exactly the slot Buiy targets. The Buiy spec's "Game and app, both" goal ([`../../specs/2026-05-07-buiy-foundation/README.md`](../../specs/2026-05-07-buiy-foundation/README.md) goal 6) and the parallel-stack web-platform-parity stance are the design response to this gap. ## Sources @@ -151,4 +151,4 @@ For Buiy: the production-game-UI gap is exactly the slot Buiy targets. The Buiy - `bevy_egui_kbgp` (gamepad nav for egui) — `https://crates.io/crates/bevy_egui_kbgp`. - Sibling files: [`distribution.md`](distribution.md), [`history.md`](history.md), [`governance.md`](governance.md), [`ecosystem.md`](ecosystem.md), [`critiques.md`](critiques.md), [`comparisons.md`](comparisons.md). - [`../bevy-ui/lessons.md`](../bevy-ui/lessons.md) "No flagship game = no UX battle-testing." -- Buiy foundation spec — [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/`](../../specs/2026-05-07-buiy-foundation/). +- Buiy foundation spec — [`../../specs/2026-05-07-buiy-foundation/`](../../specs/2026-05-07-buiy-foundation/). diff --git a/docs/prior-art/bevy-feathers/README.md b/docs/prior-art/bevy-feathers/README.md new file mode 100644 index 0000000..05a2522 --- /dev/null +++ b/docs/prior-art/bevy-feathers/README.md @@ -0,0 +1,87 @@ +**Date:** 2026-05-22 +**Status:** active +**Subject:** bevy_feathers — Bevy's official styled widget kit for editors and utilities, layered over bevy_ui_widgets; the color-only/dark-only theming reference for Buiy's token system + +# bevy_feathers + +`bevy_feathers` is the official styled widget kit in the Bevy engine workspace (`bevyengine/bevy`, `crates/bevy_feathers/`). It is a **styled layer over `bevy_ui_widgets`** (Bevy's headless widget primitives) running on `bevy_ui` (the substrate): its job is to bind theme tokens to `BackgroundColor` / `BorderColor` / `TextColor`, ship a default dark theme, and ship a fixed set of widget scenes (button, checkbox, slider, menu, text input, …) that wire the headless primitives + tokens + `RoundedCorners` + `FocusIndicator` into a coherent visual. The crate's own `Cargo.toml` describes it as `"A collection of UI widgets for building editors and utilities in Bevy"` — the framing is load-bearing: feathers is opinionated tooling-focused styling, explicitly **not** a general game-UI kit, and per the 0.17 release notes, "Feathers _can_ be used in games, but that is not its motivating use case." The corpus exists because feathers occupies the slot Buiy's own `buiy_widgets` crate parallels (a styled kit over a headless behavior layer), and because its theming model is the closest upstream reference point for the design choices in Buiy's foundation theming spec ([`architecture.md` § 2.5](../../specs/2026-05-07-buiy-foundation/architecture.md), [`cross-cutting.md` § 3.14](../../specs/2026-05-07-buiy-foundation/cross-cutting.md)). + +**Honest assessment.** feathers validates the headless/styled split (`bevy_ui_widgets` ↔ `bevy_feathers`) that Buiy adopts, and its token-as-string-key + observer-driven-reaction shape is clean and change-detection-friendly. But it is young (debuted Bevy 0.17, 2025-09-30, ~8 months old) and narrow by design, and three structural facts make it a reference-not-a-template for Buiy: (1) its `UiTheme` token map is **color-only** — no spacing, radius, motion, or typography scales (those are hardcoded `f32` constants in `src/constants.rs`); (2) it ships **dark-theme-only**, with no light, high-contrast, or OS-preference (`prefers-color-scheme` / `prefers-contrast` / `forced-colors` / `prefers-reduced-motion`) binding; and (3) its dimensions are not audited against WCAG 2.2 AA — `CHECKBOX_SIZE = 18.0` px sits **below the SC 2.5.8 target-size minimum of 24×24** with no documented enlarged hit target. Accessibility is partial-by-construction: most widgets do not set their AccessKit role on the styled entity (the toggle switch is the only one verified to wire `Role::Switch` directly), deferring to whatever `bevy_ui_widgets` sets upstream or shipping with no explicit wiring at all. Each of these is a deliberate Buiy point of departure documented in the children. + +## Key facts (verified 2026-05-22) + +| Fact | Value | +|---|---| +| Crate | `bevy_feathers` (workspace crate inside `bevyengine/bevy`, `crates/bevy_feathers/`) | +| Role | Styled widget kit layered over `bevy_ui_widgets` (headless) on `bevy_ui` (substrate) | +| Scope framing | "Widgets for building editors and utilities" — explicitly not game-UI-first | +| License | MIT OR Apache-2.0 | +| Latest stable | 0.18.1 (published 2026-03-04) | +| Pre-release | 0.19.0-rc.2 (2026-05-22) | +| Lifetime downloads | 191,700 (fetched 2026-05-22) | +| First release | Bevy 0.17, 2025-09-30 (introduction PR #19730, merged 2025-06-28, viridia) | +| Active maintainer | ickshonpe (per recent commits) | +| Top-level export | `FeathersPlugins` (PluginGroup) bundling `TabNavigationPlugin` + `FeathersCorePlugin` | +| Theme resource | `UiTheme(ThemeProps { color: HashMap })` — **color tokens only** (~100+) | +| Theme variants shipped | **Dark only** (`src/dark_theme.rs`); no light or high-contrast theme in source | +| Non-color dimensions | Hardcoded `f32` in `src/constants.rs` (`ROW_HEIGHT=24`, `CHECKBOX_SIZE=18`, `MEDIUM_FONT=14`, …) — not customizable through `UiTheme` | +| OS-preference binding | None (`prefers-color-scheme` / `prefers-contrast` / `forced-colors` / `prefers-reduced-motion` not consulted) | +| WCAG SC 2.5.8 (target size) | `CHECKBOX_SIZE=18` is below the 24×24 minimum; not audited per-widget | +| A11y role wiring | Partial — only the toggle switch sets `AccessibilityNode(Role::Switch)` directly; most widgets defer upstream or are unwired | +| Controls shipped | ~14 (button, checkbox, toggle switch, radio, slider, color slider/plane/swatch, disclosure toggle, menu, text input, number input, virtual keyboard) + pane/subpane/group/spacer containers + icon/label display | +| Governance | Bevy Foundation (Washington 501(c)(3)); inherits the workspace RFC / SME / release apparatus | + +## Strengths + +- **Clean headless/styled split.** `bevy_ui_widgets` owns behavior; `bevy_feathers` owns presentation. This validates Buiy's intent to keep behavior + presentation cleanly split inside `buiy_widgets`. +- **Simple, reactive theming.** Token-as-string-key lookup with observer-driven application (`ThemeBackgroundColor(token)` etc.); `update_theme` rewrites all colors in one pass on `UiTheme` change. The component-per-styled-property decomposition maps directly onto Buiy's decomposed-component philosophy. +- **Coherent, opinionated editor look** with focus indicators, rounded corners, and a consistent button/slider/menu vocabulary suitable for tooling. + +## Weaknesses + +- **Color-only token scope.** No `space`, `radius`, `motion`, or `typography` scales — those are hardcoded constants, so a denser/sparser variant requires forking the widget scenes, not retheming. +- **Dark-only, no OS-preference binding.** No light or high-contrast theme ships; `prefers-*` queries are not consulted; missing tokens fall through to a silent default. +- **Dimensions below WCAG 2.2 AA.** `CHECKBOX_SIZE=18` < the SC 2.5.8 24×24 target-size minimum; the token set is not designed against the AA criteria. +- **Partial accessibility.** Most controls don't set their AccessKit role on the styled entity; no tri-state checkbox (`aria-checked="mixed"`), no `Role::Heading`, disclosure toggle inherits checkbox semantics rather than `button` + `aria-expanded`. +- **Narrow catalog.** No dialog/modal, tooltip, tabs, tree, listbox/combobox, table, progress, toast, or multi-line editor — consistent with the editor-utilities scope but not a WCAG 2.2 AA APG widget set. +- **Single global theme resource.** No subtree-scoped theme, no theme hot-reload (it's a runtime resource, not an asset). + +## Lessons for Buiy + +There is no `lessons.md` in this folder; the consult-this-when-designing material is distributed across the per-file **"Implications for Buiy"** sections — principally [`theming.md`](theming.md) (the load-bearing theming comparison + borrow/avoid list) and [`widgets.md`](widgets.md) (catalog gaps and the a11y-wiring gap) — with the cross-folder BSN-friendliness lesson in [`docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md). All Buiy-side statements are **sourced to the foundation spec as target state, not decided here**: + +- **Validates** — the headless/styled split and the per-window coexistence policy (a feathers editor pane and a Buiy game UI live on separate windows; foundation [`cross-cutting.md` § 3.18](../../specs/2026-05-07-buiy-foundation/cross-cutting.md)). Feathers's partial a11y wiring validates Buiy's AccessKit-first model (role + name + states explicit on every widget; foundation [`architecture.md` § 2.6](../../specs/2026-05-07-buiy-foundation/architecture.md)). +- **Avoid** — color-only token scope, dark-only default with no variants, flat string namespace with no type guard, global-resource-only theming, no hot-reload / contrast linter / OS-preference binding, and dimensions not audited to WCAG 2.2 AA. +- **Borrow** — token-as-string-key lookup with observer-driven reaction and the component-as-binding pattern, but with hierarchical tokens, a typed-token API, and the multi-scale token set (`color.*` + `space.*` + `radius.*` + `motion.*` + `typography.*`) Buiy's foundation commits to ([`architecture.md` § 2.5](../../specs/2026-05-07-buiy-foundation/architecture.md), [`cross-cutting.md` § 3.14](../../specs/2026-05-07-buiy-foundation/cross-cutting.md)). + +## Reading order + +| File | Subject | +|---|---| +| [`README.md`](README.md) | This file — overview, key facts, strengths/weaknesses, lessons pointer, reading order. | +| [`architecture.md`](architecture.md) | Plugin shape, module layout, the layer cake over `bevy_ui_widgets` + `bevy_ui`. | +| [`widgets.md`](widgets.md) | Widget catalog: shipped controls, spawn/keyboard/role contracts, gaps relative to WAI-ARIA APG. | +| [`theming.md`](theming.md) | **The load-bearing theming file.** `UiTheme` resource, token taxonomy, color-only scope, dark-only default, OS-preference status, the Buiy comparison table. | +| [`accessibility.md`](accessibility.md) | bevy_a11y integration, per-widget wiring, focus model, WCAG 2.2 gap analysis (incl. the SC 2.5.8 `CHECKBOX_SIZE` gap). | +| [`integration.md`](integration.md) | Adding the plugin, the dependency contract, spawning, per-window coexistence with custom UI and with Buiy. | +| [`comparisons.md`](comparisons.md) | Row-by-row vs `bevy_ui_widgets`, bevy_egui, bevy_lunex, sickle_ui, woodpecker_ui, kayak_ui, and Buiy. | +| [`distribution.md`](distribution.md) | Cargo features, dependencies, platform matrix, MSRV, release cadence, assets. | +| [`ecosystem.md`](ecosystem.md) | Consumers, ecosystem position, relationship to third-party widget kits and to Buiy. | +| [`governance.md`](governance.md) | Stewardship, SMEs, inclusion-decision rationale, direction signals. | +| [`history.md`](history.md) | Chronological history (pre-history → Bevy 0.19-rc), per-release additions. | +| [`critiques.md`](critiques.md) | Third-party critiques, structural gaps, honest limitations. | +| [`open-problems.md`](open-problems.md) | What the crate structurally does not solve as of 2026-05-22. | + +## Sources + +- `bevy_feathers` on crates.io — https://crates.io/crates/bevy_feathers +- `bevy_feathers` source (main HEAD) — https://github.com/bevyengine/bevy/tree/main/crates/bevy_feathers +- `theme.rs` / `tokens.rs` / `dark_theme.rs` / `constants.rs` (main HEAD) — https://github.com/bevyengine/bevy/tree/main/crates/bevy_feathers/src +- PR #19730 (bevy_feathers introduction, Bevy 0.17, merged 2025-06-28) — https://github.com/bevyengine/bevy/pull/19730 +- Issue #17644 (bevy_a11y BSN-unfriendly) — https://github.com/bevyengine/bevy/issues/17644 +- PR #24308 (AccessibleLabel, merged 2026-05-21 for 0.19) — https://github.com/bevyengine/bevy/pull/24308 +- WAI-ARIA APG — https://www.w3.org/WAI/ARIA/apg/ +- Bevy 0.17 release notes — https://bevy.org/news/bevy-0-17/ +- Buiy foundation — theming/architecture §2.5: [`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) +- Buiy foundation — cross-cutting §3.14 (theming + user preferences), §3.18 (per-window coexistence): [`../../specs/2026-05-07-buiy-foundation/cross-cutting.md`](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) +- Buiy foundation — widget catalog: [`../../specs/2026-05-07-buiy-foundation/media-and-widgets.md`](../../specs/2026-05-07-buiy-foundation/media-and-widgets.md) diff --git a/docs/prior-art/bevy-flair/architecture.md b/docs/prior-art/bevy-flair/architecture.md index 41ad8c9..0239db9 100644 --- a/docs/prior-art/bevy-flair/architecture.md +++ b/docs/prior-art/bevy-flair/architecture.md @@ -122,7 +122,7 @@ In practice (per README + community discussion): hot-reload is one of the headli ## 8. Cross-references - The cascade-engine choice (Servo `selectors` 0.32) parallels bevy_ui's own choice to lean on Taffy for layout: lease a real-spec implementation rather than reinvent it. Same lesson as [`bevy-ui/architecture.md`](../bevy-ui/architecture.md) § Taffy integration. -- The eleven-stage `PostUpdate` pipeline is a parallel to bevy_ui's `BuiySet::Layout → Style → Input → Animate → Picking → A11yUpdate → Render` ordering ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.8). bevy_flair runs in `PostUpdate`; Buiy's would run in its own `BuiySet::Style` stage. +- The eleven-stage `PostUpdate` pipeline is a parallel to bevy_ui's `BuiySet::Layout → Style → Input → Animate → Picking → A11yUpdate → Render` ordering ([`docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.8). bevy_flair runs in `PostUpdate`; Buiy's would run in its own `BuiySet::Style` stage. - Reflection-driven property mapping aligns with Buiy's BSN-friendly reflection requirement ([architecture.md § 2.4](../../specs/2026-05-07-buiy-foundation/architecture.md#24-authoring-ecs-native-and-bsn-both-first-class)) — `bevy_flair_core::ComponentProperty` is essentially what a stylesheet layer over BSN-friendly Buiy components would need. ## Sources diff --git a/docs/prior-art/bevy-ui/README.md b/docs/prior-art/bevy-ui/README.md index e9aa3a1..1bc1e8a 100644 --- a/docs/prior-art/bevy-ui/README.md +++ b/docs/prior-art/bevy-ui/README.md @@ -4,7 +4,7 @@ # bevy_ui -`bevy_ui` is the official UI crate in the Bevy engine workspace (`bevyengine/bevy`). It is a CSS-flavoured retained-mode UI library built on Bevy's ECS: a hierarchy of `Node` entities that drive Taffy for layout, parley + swash (post-0.19) / cosmic-text (≤ 0.18) for text, AccessKit for accessibility, `bevy_picking` for hit-testing, and a render-graph node for visuals. It is the default UI library Bevy users reach for, the substrate that the official `bevy_feathers` widget kit + `bevy_ui_widgets` headless primitives sit on, and the architectural anchor against which **every Buiy design decision is taken** — Buiy is intentionally parallel to bevy_ui, integrating the same Taffy / cosmic-text / AccessKit / bevy_picking / wgpu primitives directly with its own component model and render pipeline (see [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.1–2.3). bevy_ui therefore deserves the largest, most version-pinned prior-art folder in this corpus: every Buiy spec author will consult it for "what does upstream do here, and why are we doing it differently?" +`bevy_ui` is the official UI crate in the Bevy engine workspace (`bevyengine/bevy`). It is a CSS-flavoured retained-mode UI library built on Bevy's ECS: a hierarchy of `Node` entities that drive Taffy for layout, parley + swash (post-0.19) / cosmic-text (≤ 0.18) for text, AccessKit for accessibility, `bevy_picking` for hit-testing, and a render-graph node for visuals. It is the default UI library Bevy users reach for, the substrate that the official `bevy_feathers` widget kit + `bevy_ui_widgets` headless primitives sit on, and the architectural anchor against which **every Buiy design decision is taken** — Buiy is intentionally parallel to bevy_ui, integrating the same Taffy / cosmic-text / AccessKit / bevy_picking / wgpu primitives directly with its own component model and render pipeline (see [`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.1–2.3). bevy_ui therefore deserves the largest, most version-pinned prior-art folder in this corpus: every Buiy spec author will consult it for "what does upstream do here, and why are we doing it differently?" **Honest assessment.** bevy_ui ships in every Bevy app by default and has had AccessKit integration since 0.10 (March 2023, PR #6874) and Taffy as the layout substrate since 0.8 (July 2022, PR #4716) — these are real, durable assets. But it has **no flagship commercial game shipping with bevy_ui as the UI layer** (the most-cited Bevy production title, Tiny Glade, wrote its own UI renderer); it has no published bench data at productivity-app node counts (1000s of nodes — performance issues #677 / #276 / #2451 are old but never closed with bench data); and its renderer caps several capabilities (non-rectangular clipping, `backdrop-filter`, `mix-blend-mode`, isolation, true CSS top layer) that web-platform parity requires. Issue [#22345](https://github.com/bevyengine/bevy/issues/22345) (viridia, 2026-01-02) documents this as upstream's own diagnosis: `"We currently only support rectangular clipping regions ... which are inadequate for the kinds of UIs we want to build"`; the proposed fix is labeled "`require substantial architectural redesign`." This corpus reports those gaps verbatim — they are the load-bearing rationale for Buiy's parallel-stack decision and the most concrete validation of it. diff --git a/docs/prior-art/bevy-ui/architecture.md b/docs/prior-art/bevy-ui/architecture.md index 7c2914b..8afb75d 100644 --- a/docs/prior-art/bevy-ui/architecture.md +++ b/docs/prior-art/bevy-ui/architecture.md @@ -81,7 +81,7 @@ Verified as of 0.18.1 / 0.19-rc.1 against current source and a January 2026 issu These limitations are not bugs — they are the result of bevy_ui being a CSS-flavoured rectangular-stacking renderer optimised for the game-HUD case. Issue #22345 is the upstream proposal to lift several of them, but its status (as of 2026-05) is `S-Needs-Design-Doc` and the listed scope (clipping in particular) is described as "`require substantial architectural redesign`." See [open-problems.md](open-problems.md) (Agent B) for the current Bevy-side issue status. -For Buiy, the chosen response is parallel rather than patch: own the render-graph node, own the clip-path primitive, own backdrop-filter, own top-layer compositing. See `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md` § 2.3. +For Buiy, the chosen response is parallel rather than patch: own the render-graph node, own the clip-path primitive, own backdrop-filter, own top-layer compositing. See `docs/specs/2026-05-07-buiy-foundation/architecture.md` § 2.3. ## Sources diff --git a/docs/prior-art/bevy-ui/component-model.md b/docs/prior-art/bevy-ui/component-model.md index ecb6cfb..c4306fc 100644 --- a/docs/prior-art/bevy-ui/component-model.md +++ b/docs/prior-art/bevy-ui/component-model.md @@ -65,7 +65,7 @@ The mechanical consequence: BSN patches/templates can't merge into private-sette The recommendation in #17644 is to keep an idiomatic decomposed Bevy-side API and *transform* it into AccessKit's structure at the boundary, rather than exposing AccessKit's tree shape as the component model. -This is the single most-cited lesson in the Buiy foundation spec — see `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md` § 2.4 and § 2.6. Every Buiy component is therefore mandated small, public-fielded, observable, decomposed; AccessKit is reached via Buiy's own decomposed `A11yRole` / `A11yLabel` / `A11yDescription` / `A11yStates` / `A11yRelations` components. +This is the single most-cited lesson in the Buiy foundation spec — see `docs/specs/2026-05-07-buiy-foundation/architecture.md` § 2.4 and § 2.6. Every Buiy component is therefore mandated small, public-fielded, observable, decomposed; AccessKit is reached via Buiy's own decomposed `A11yRole` / `A11yLabel` / `A11yDescription` / `A11yStates` / `A11yRelations` components. bevy_ui's own components are *closer* to the BSN-friendly shape than `AccessibilityNode` is — `Node` has public fields, `BackgroundColor` is decomposed, `Text` is a newtype — but the residual coupling inside `Node` (layout fields + `border_radius` + position-type all bundled together) is the same pattern at smaller scale. A BSN patch that wants to change only `border_radius` still pulls the whole `Node` into the patch. diff --git a/docs/prior-art/bevy-ui/lessons.md b/docs/prior-art/bevy-ui/lessons.md index 9fae29e..590d1f3 100644 --- a/docs/prior-art/bevy-ui/lessons.md +++ b/docs/prior-art/bevy-ui/lessons.md @@ -14,7 +14,7 @@ Before everything else: two findings reshape several existing Buiy assumptions. PR [#20158](https://github.com/bevyengine/bevy/pull/20158) (BSN) is **still draft / unmerged as of 2026-05-22**. cart explicitly wrote it is `"not intended to be merged in current form."` The 0.18 release notes make **no mention** of BSN landing. See [`history.md`](history.md) § "BSN (PR #20158) — NOT yet merged" and [`open-problems.md`](open-problems.md) § "BSN ergonomics maturity." -This reframes the Buiy foundation spec's section 2.4 ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md)) which currently treats BSN as available on Bevy 0.18+. **Restated rule:** Buiy components ship BSN-friendly *now* (small, public-fielded, decomposed, reflection-registered) so that when BSN lands, every Buiy component is already authorable in it without retrofit. The constraint is mandatory regardless of BSN's status — but the *justification* shifts from "BSN is here, use it" to "we are paying the small-decomposed-component tax in advance, because retrofitting later costs more (issue #17644 is the canonical demonstration)." +This reframes the Buiy foundation spec's section 2.4 ([`docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md)) which currently treats BSN as available on Bevy 0.18+. **Restated rule:** Buiy components ship BSN-friendly *now* (small, public-fielded, decomposed, reflection-registered) so that when BSN lands, every Buiy component is already authorable in it without retrofit. The constraint is mandatory regardless of BSN's status — but the *justification* shifts from "BSN is here, use it" to "we are paying the small-decomposed-component tax in advance, because retrofitting later costs more (issue #17644 is the canonical demonstration)." ### 2. Post-0.19, bevy_ui and Buiy diverge on text shaper. @@ -49,7 +49,7 @@ Pitfalls drawn from bevy_ui's experience, with Buiy's mitigation. | **Coupling text rendering to a single shaper** — Bevy switched from ab_glyph (≤0.14) → cosmic-text (0.15–0.18) → parley + swash (0.19-dev) in three releases. Each migration is breaking and large. | [`text-and-input.md`](text-and-input.md) § "Text rendering: a three-engine timeline"; issue [#21765](https://github.com/bevyengine/bevy/issues/21765). | Own the text pipeline end-to-end. Buiy commits to cosmic-text and integrates directly; if upstream Bevy migrates away, Buiy still owns its commitment. Text-shaper choice is decoupled from Bevy minor releases. Foundation architecture.md § 2.3. | | **Per-frame full layout rebuild** — bevy_ui's old performance issues (#677, #276, #2451) trace to insufficient layout caching. The situation has improved with Taffy 0.6+ but there is **no published bench at 1000+ nodes** and the cheat-book documents "a few hundred microseconds" per frame at moderate counts. | [`critiques.md`](critiques.md) § "Performance critiques"; [`open-problems.md`](open-problems.md) § "Verifiable behavior." | Change-detection + dirty-propagation through the layout pipeline; Taffy's own cache is the lower bound. The Buiy verification harness (foundation README § 1.7) explicitly enumerates productivity-app fixtures at 1000+ nodes. | | **Treating `bevy_a11y` as a coexistence partner** — even with PR #24308's partial `AccessibleLabel` sibling, bevy_a11y still ships the megacomponent; the partial decomposition serves bevy_ui's needs, not Buiy's. Layering over it would mean reflecting Buiy's a11y state through bevy_a11y's components. | [`critiques.md`](critiques.md) § "The megacomponent problem"; [`open-problems.md`](open-problems.md) § "Accessibility tree completeness." | Replace bevy_a11y for any window where Buiy is present. Buiy owns the AccessKit adapter directly; `ActionRequest` events route to Buiy entities via Buiy's own plumbing, not bevy_a11y's. Foundation architecture.md § 2.6. | -| **Non-monotonic decomposition** — `BorderRadius` was a separate component in 0.17, then demoted back to a field on `Node` in 0.18 because "the field was small enough that keeping it as a separate component cost more than it bought." Reversing decomposition is breaking and forces consumer churn. | [`architecture.md`](architecture.md) § "Node / Style / ComputedNode decomposition"; [`component-model.md`](component-model.md) § "The decomposition migration." | Commit to a target decomposition in [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) and don't reverse it without a spec update. "If a property might end up shared across many nodes or hot-reloaded independently, it gets its own component" is the heuristic. | +| **Non-monotonic decomposition** — `BorderRadius` was a separate component in 0.17, then demoted back to a field on `Node` in 0.18 because "the field was small enough that keeping it as a separate component cost more than it bought." Reversing decomposition is breaking and forces consumer churn. | [`architecture.md`](architecture.md) § "Node / Style / ComputedNode decomposition"; [`component-model.md`](component-model.md) § "The decomposition migration." | Commit to a target decomposition in [`docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) and don't reverse it without a spec update. "If a property might end up shared across many nodes or hot-reloaded independently, it gets its own component" is the heuristic. | | **No flagship game = no UX battle-testing** — bevy_ui has not yet been used at scale in a flagship commercial title. Tiny Glade (the most-cited Bevy commercial release) wrote its own UI renderer. Foresight Spar / Roboquest / other large titles do not verify as bevy_ui consumers. | [`ecosystem.md`](ecosystem.md) § "Game studios using bevy_ui"; [`critiques.md`](critiques.md) § "Performance critiques." | The Buiy verification harness (foundation verification.md) explicitly enumerates productivity-app fixtures *and* game scenarios, with named CI gates + manual release gates. Buiy commits to "Game and app, both" (foundation README goal 6) and doesn't outsource the proof to deployment. | | **"Comprehensive" rhetoric in lieu of feature claims** — bevy_ui marketing uses words like "comprehensive" without naming features. The 10 Challenges (TimJentzsch, [#11100](https://github.com/bevyengine/bevy/issues/11100), open since 2023-12) is the closest the Bevy community has to a UI capability benchmark, and as of late 2023 no Bevy UI framework had cleanly demonstrated all 10. | [`critiques.md`](critiques.md) § "The 10 Challenges." | The Buiy spec separates **F** (foundation) / **C** (core) / **E** (extended) / **O** (out, explicitly excluded) tiers per feature, verifiable per tier (foundation README § "Tier legend"). | | **AccessKit version pin drift** — `bevy_feathers` HEAD depends on accesskit 0.24; v0.17.3 stable depended on accesskit 0.21. Mid-release AccessKit majors break ABI for downstream consumers. | [`component-model.md`](component-model.md); [`ecosystem.md`](ecosystem.md). | Pin AccessKit explicitly per Buiy release. Foundation README § 5 lists "AccessKit cadence policy decoupled from Bevy" as an open question; treat it as live, not a footnote. Document the AccessKit version each Buiy release pins to in the release notes. | diff --git a/docs/prior-art/bevy-ui/styling.md b/docs/prior-art/bevy-ui/styling.md index 8a1c419..dd413ea 100644 --- a/docs/prior-art/bevy-ui/styling.md +++ b/docs/prior-art/bevy-ui/styling.md @@ -27,7 +27,7 @@ What is *not* present in bevy_ui core: bevy_ui ships *property-level components* but not a token vocabulary. There is no `Token` indirection, no theme registry that maps a semantic name to a `Color`. Every component carries a literal value. Sharing a color across a UI is on the application — typically by extracting the color into a `Resource` or const and referencing it at spawn time. -This is a deliberate "primitives first" stance and is the layer Buiy's foundation spec critiques: see `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md` § 2.5 (semantic-tokens-only authoring, OS-pref-bound variants, hot-reloadable theme assets). +This is a deliberate "primitives first" stance and is the layer Buiy's foundation spec critiques: see `docs/specs/2026-05-07-buiy-foundation/architecture.md` § 2.5 (semantic-tokens-only authoring, OS-pref-bound variants, hot-reloadable theme assets). ## bevy_feathers theming diff --git a/docs/prior-art/cosmic-text/README.md b/docs/prior-art/cosmic-text/README.md index 6ff2289..c1a3907 100644 --- a/docs/prior-art/cosmic-text/README.md +++ b/docs/prior-art/cosmic-text/README.md @@ -2,6 +2,8 @@ **Status:** active **Subject:** cosmic-text — pure-Rust text shaping, BiDi, layout, editing, and color-emoji rasterization +# cosmic-text + ## What it is [`cosmic-text`](https://github.com/pop-os/cosmic-text) is the pure-Rust text engine built and maintained by System76 for the COSMIC desktop and Pop!_OS. It composes a HarfBuzz-port shaper (`harfrust`), a font-format rasterizer (`swash`), Servo's UAX #9 BiDi (`unicode-bidi`), Google Fonts' `read-fonts` wrapper (`skrifa`), and `fontdb` font discovery into a single crate that does shape + layout + cursor + selection + glyph caching for multi-line, multi-script, BiDi-correct text. It is the substrate Iced has used since 0.10.0 (2023-07-28) and the substrate Bevy adopted in 0.15 (2024-11-29, PR #10193 merged 2024-07-04 during the 0.14 cycle), replacing the script-coverage-capped `ab_glyph` engine. @@ -30,7 +32,7 @@ Buiy's foundation spec ([`text.md`](../../specs/2026-05-07-buiy-foundation/text. | Recent downloads | 1,299,778 | | Steward | System76 (POP_OS / COSMIC desktop) | | Primary maintainer | Jeremy Soller (`jackpot51`) | -| Shaper | **`harfrust 0.5.0`** (HarfBuzz v13.0.0 port) — replaced `rustybuzz` in **0.15.0** (PR #417, 2025-09-09) | +| Shaper | **`harfrust 0.5.0`** (HarfBuzz v13.0.0 port) — replaced `rustybuzz` in **0.15.0** (PR #417, 2025-10-30) | | Rasterizer | `swash 0.2.6` (outlines, COLRv0/CPAL, sbix, CBDT/CBLC; **NOT** COLRv1). **Correction (text campaign T9, 2026-06-11):** `0.2.6` is the declared minimum; the 0.19.0 lock resolves **swash 0.2.8** | | Font data | `skrifa 0.40.0` (Google Fonts' `read-fonts` wrapper) | | Font discovery | `fontdb 0.23` | @@ -73,8 +75,8 @@ Internal contradictions surfaced during research have been fixed in a polish pas - cosmic-text repo and main-branch source — https://github.com/pop-os/cosmic-text - crates.io metadata — https://crates.io/crates/cosmic-text -- Buiy text spec — `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/text.md` -- Buiy foundation spec — `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/README.md` +- Buiy text spec — `docs/specs/2026-05-07-buiy-foundation/text.md` +- Buiy foundation spec — `docs/specs/2026-05-07-buiy-foundation/README.md` - Bevy PR #10193 (cosmic-text adoption) — https://github.com/bevyengine/bevy/pull/10193 - Bevy issue #21765 (cosmic-text → Parley migration) — https://github.com/bevyengine/bevy/issues/21765 - cosmic-text PR #417 (rustybuzz → harfrust) — https://github.com/pop-os/cosmic-text/pull/417 diff --git a/docs/prior-art/cosmic-text/capabilities.md b/docs/prior-art/cosmic-text/capabilities.md index 5d274dc..9793b43 100644 --- a/docs/prior-art/cosmic-text/capabilities.md +++ b/docs/prior-art/cosmic-text/capabilities.md @@ -155,4 +155,4 @@ The one row that should sting most is **vertical writing modes** — the layout - swash — https://github.com/dfrg/swash, https://crates.io/crates/swash - unicode-bidi — https://github.com/servo/unicode-bidi - unicode-linebreak — https://crates.io/crates/unicode-linebreak -- Buiy text spec — `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/text.md` +- Buiy text spec — `docs/specs/2026-05-07-buiy-foundation/text.md` diff --git a/docs/prior-art/cosmic-text/critiques.md b/docs/prior-art/cosmic-text/critiques.md index bf29623..e4b9f06 100644 --- a/docs/prior-art/cosmic-text/critiques.md +++ b/docs/prior-art/cosmic-text/critiques.md @@ -169,6 +169,6 @@ Not applicable — cosmic-text is not a web engine. Buiy's asset pipeline handle - Issue #493 (pixel font 1px offset) — https://github.com/pop-os/cosmic-text/issues/493 - Issue #499 (fontconfig aliases) — https://github.com/pop-os/cosmic-text/issues/499 - Issue #505 (FontSystem::new slow) — https://github.com/pop-os/cosmic-text/issues/505 -- Buiy text spec — `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/text.md` +- Buiy text spec — `docs/specs/2026-05-07-buiy-foundation/text.md` - swash COLRv1 status — https://github.com/dfrg/swash (4+-year-open issue noted in #446 reporter's analysis) - winit IME events — https://docs.rs/winit/latest/winit/event/enum.Ime.html diff --git a/docs/prior-art/cosmic-text/editing.md b/docs/prior-art/cosmic-text/editing.md index 9fcc234..aed992e 100644 --- a/docs/prior-art/cosmic-text/editing.md +++ b/docs/prior-art/cosmic-text/editing.md @@ -109,4 +109,4 @@ Explicitly out of scope. cosmic-text does not link any dictionary library, does - Issue #10 "IME support" — https://github.com/pop-os/cosmic-text/issues/10 - `cosmic_undo_2` crate — https://crates.io/crates/cosmic_undo_2 - `modit` crate (vi-keys parser) — https://crates.io/crates/modit -- Buiy foundation spec — `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/text.md` +- Buiy foundation spec — `docs/specs/2026-05-07-buiy-foundation/text.md` diff --git a/docs/prior-art/cosmic-text/integration.md b/docs/prior-art/cosmic-text/integration.md index 81b2324..3957281 100644 --- a/docs/prior-art/cosmic-text/integration.md +++ b/docs/prior-art/cosmic-text/integration.md @@ -124,5 +124,5 @@ Buiy's render pipeline (`buiy-render-pipeline-design` sub-spec, not yet written) - glyphon — https://github.com/grovesNL/glyphon - Floem Cargo.toml — https://github.com/lapce/floem/blob/main/Cargo.toml (uses Parley, not cosmic-text) - Freya Cargo.toml — https://github.com/marc2332/freya/blob/main/Cargo.toml (uses freya-skia-safe) -- Buiy foundation spec text.md — `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/text.md` +- Buiy foundation spec text.md — `docs/specs/2026-05-07-buiy-foundation/text.md` - winit `Ime` event — https://docs.rs/winit/latest/winit/event/enum.Ime.html diff --git a/docs/prior-art/cosmic-text/lessons.md b/docs/prior-art/cosmic-text/lessons.md index 9ab5d98..e53c6d1 100644 --- a/docs/prior-art/cosmic-text/lessons.md +++ b/docs/prior-art/cosmic-text/lessons.md @@ -67,7 +67,7 @@ When designing a Buiy text feature: (1) Find the row in **Avoid** that names a p ## Sources - All sibling files in this folder. -- Buiy foundation spec — `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/` +- Buiy foundation spec — `docs/specs/2026-05-07-buiy-foundation/` - cosmic-text repo — https://github.com/pop-os/cosmic-text - Bevy issue #21765 (bevy_text → Parley migration) — https://github.com/bevyengine/bevy/issues/21765 - cosmic-text PR #417 (rustybuzz → harfrust) — https://github.com/pop-os/cosmic-text/pull/417 diff --git a/docs/prior-art/egui/lessons.md b/docs/prior-art/egui/lessons.md index b74695a..f1a6af6 100644 --- a/docs/prior-art/egui/lessons.md +++ b/docs/prior-art/egui/lessons.md @@ -16,7 +16,7 @@ egui's success at dev-tooling scale **validates immediate-mode for that niche** egui's absence from production game UI **validates retained-mode for that niche** — *by absence*, not contradiction. Through 16.96M downloads and seven years of Emil's stewardship, **no AAA or notable indie game ships its in-game UI on egui.** Tiny Glade wrote a custom UI renderer. Foresight Spar wrote a custom UI renderer. Polished consumer apps where distinctiveness matters are not on egui. Accessibility-critical apps where APG widget contracts are non-negotiable are not on egui. Complex-script i18n-critical apps are not on egui. 10k+-widget data-grid apps are not on egui. The cluster of weaknesses — homogeneous "looks like egui" aesthetic, per-frame rebuild cost, structurally bolted-on AccessKit, animation primitives that stop at `animate_value`, layout simpler than Flexbox/Grid, ad-hoc `Id` hashing — is the production-UI-grade-polish gap retained-mode is built to close. See [`critiques.md`](critiques.md) § "The 'Production Game UI' gap" and [`open-problems.md`](open-problems.md) § "The 'Production Game UI' gap." -**Buiy's retained-mode bet does not compete with egui; the two coexist.** Most real Bevy projects will use both — egui (via `bevy_egui`) for dev overlays / inspectors / editor panels, Buiy (or `bevy_ui` today) for shipped player-facing UI. The dev/ship pattern is documented in [`immediate-mode-deep-dive.md`](immediate-mode-deep-dive.md) § "The dev/ship pattern" and reinforced in [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/cross-cutting.md`](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) § 3.18. +**Buiy's retained-mode bet does not compete with egui; the two coexist.** Most real Bevy projects will use both — egui (via `bevy_egui`) for dev overlays / inspectors / editor panels, Buiy (or `bevy_ui` today) for shipped player-facing UI. The dev/ship pattern is documented in [`immediate-mode-deep-dive.md`](immediate-mode-deep-dive.md) § "The dev/ship pattern" and reinforced in [`docs/specs/2026-05-07-buiy-foundation/cross-cutting.md`](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) § 3.18. The follow-on for every Buiy spec: **stop asking "should Buiy do X better than egui?" and start asking "does X belong on the production-UI axis Buiy targets, or on the dev-tool axis egui already owns?"** Most dev tooling answers "ship it on bevy_egui." Production UI answers "ship it on Buiy." The two are different problems, not different sizes of the same problem. diff --git a/docs/prior-art/egui/styling-and-theming.md b/docs/prior-art/egui/styling-and-theming.md index f87932c..417b99c 100644 --- a/docs/prior-art/egui/styling-and-theming.md +++ b/docs/prior-art/egui/styling-and-theming.md @@ -177,7 +177,7 @@ What this folder documents about egui's theming model translates directly to Bui - [`architecture.md`](architecture.md) — how `Style` and `Visuals` live on `Context`. - [`api-surface.md`](api-surface.md) — which widgets consume which Style/Visuals fields. - [`text-rendering.md`](text-rendering.md) — `TextStyle` and `FontDefinitions` in depth. -- [`../bevy-egui/styling.md`](../bevy-egui/styling.md) — how Buiy adjacent stacks handle theming (cross-stack styling comparison). +- [`../bevy-egui/api-surface.md`](../bevy-egui/api-surface.md) — how Buiy adjacent stacks handle theming (cross-stack styling comparison; see § Styling: `Style`, `Visuals`, `Spacing`). ## Sources diff --git a/docs/prior-art/godot-control/README.md b/docs/prior-art/godot-control/README.md index 36ae7e8..a147f7a 100644 --- a/docs/prior-art/godot-control/README.md +++ b/docs/prior-art/godot-control/README.md @@ -61,11 +61,11 @@ These docs are written from Buiy's **parallel-to-bevy_ui, web-platform-parity, A ## Cross-links into the Buiy corpus -- [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) — the sister "game engine UI" corpus closest to Buiy. -- [`/home/user/buiy/docs/prior-art/accesskit/`](../accesskit/) — the a11y bridge Godot 4.5 adopted (validating AccessKit's reach into game engines). -- [`/home/user/buiy/docs/prior-art/cosmic-text/`](../cosmic-text/) — the text-shaper Buiy commits to; Godot uses HarfBuzz directly instead. -- [`/home/user/buiy/docs/prior-art/taffy/`](../taffy/) — the layout engine Buiy commits to; Godot does its own anchor+container model. -- _(Unity UGUI / UI Toolkit and Unreal Slate / UMG folders — pending; Godot is the open-source third leg of the game-engine UI trio.)_ +- [`../bevy-ui/lessons.md`](../bevy-ui/lessons.md) — the sister "game engine UI" corpus closest to Buiy. +- [`../accesskit/`](../accesskit/) — the a11y bridge Godot 4.5 adopted (validating AccessKit's reach into game engines). +- [`../cosmic-text/`](../cosmic-text/) — the text-shaper Buiy commits to; Godot uses HarfBuzz directly instead. +- [`../taffy/`](../taffy/) — the layout engine Buiy commits to; Godot does its own anchor+container model. +- [`../unity-ui/`](../unity-ui/) (UGUI / UI Toolkit) and [`../unreal-slate-umg/`](../unreal-slate-umg/) (Slate / UMG) — the other two legs of the game-engine UI trio; Godot is the open-source one. ## Sources diff --git a/docs/prior-art/godot-control/accessibility.md b/docs/prior-art/godot-control/accessibility.md index 6488fdc..c1267f5 100644 --- a/docs/prior-art/godot-control/accessibility.md +++ b/docs/prior-art/godot-control/accessibility.md @@ -58,7 +58,7 @@ What 4.5 ships: Buiy's foundation [`accessibility.md § 3.11`](../../specs/2026-05-07-buiy-foundation/accessibility.md) commits to: - **AccessKit-first from v1.** Buiy is v1 with AccessKit shipping; Godot waited 11 years and shipped it as "experimental" in 4.5. -- **Decomposed `A11yRole` / `A11yLabel` / `A11yDescription` / `A11yStates` / `A11yRelations` components.** Godot stuffs all a11y properties on the base Control class, including the editor's own widgets. This is BSN-hostile in the same shape as `bevy_a11y::AccessibilityNode` (issue [bevy/#17644](https://github.com/bevyengine/bevy/issues/17644)); see [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md). +- **Decomposed `A11yRole` / `A11yLabel` / `A11yDescription` / `A11yStates` / `A11yRelations` components.** Godot stuffs all a11y properties on the base Control class, including the editor's own widgets. This is BSN-hostile in the same shape as `bevy_a11y::AccessibilityNode` (issue [bevy/#17644](https://github.com/bevyengine/bevy/issues/17644)); see [`docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md). - **WCAG 2.2 AA as floor, full Level A + AA SC enumeration.** Buiy's spec enumerates every SC with an enforcement strategy (CI / RT / LR / DC). Godot's 4.5 work surfaces accessibility but doesn't claim WCAG-grade coverage. - **APG keyboard contract per interactive widget.** Buiy's `buiy-widget-catalog-design` will spec keyboard contracts per WAI-ARIA APG; Godot's keyboard handling is per-widget in `_gui_input()` with no central contract. - **ACCNAME 1.2 name computation.** Buiy commits to the full ACCNAME 1.2 algorithm in `buiy_core`. Godot consults `accessibility_name` but does not implement ACCNAME chains. @@ -72,7 +72,7 @@ Buiy's foundation [`accessibility.md § 3.11`](../../specs/2026-05-07-buiy-found - **Validate the AccessKit choice across game engines.** Both Buiy (via Bevy) and Godot now commit to AccessKit. This is a strong signal that AccessKit's producer model fits game-engine widget hierarchies — the substrate is the right bet even for ECS-shaped engines (Bevy/Buiy) and scene-tree-shaped engines (Godot). - **Borrow:** the `accessibility_*` property naming on Control is clean. Buiy's `A11yLabel` / `A11yDescription` / `A11yLive` components map directly onto Godot's `accessibility_name` / `accessibility_description` / `accessibility_live` — verify Buiy's component names against Godot's property names for consistency where it doesn't cost anything. - **Borrow:** the editor-eats-its-own-dog-food principle. Godot 4.5's biggest test of its a11y story is **the editor itself becoming usable to blind developers**. Buiy's verification harness (foundation [`verification.md`](../../specs/2026-05-07-buiy-foundation/verification.md)) should run the inspector / devtools against AccessKit too — if Buiy's own tooling isn't AT-accessible, the framework's a11y claim is hollow. -- **Avoid:** stuffing all a11y into the base Node class. Godot Control has `accessibility_*` properties on the base class; this is the same megacomponent shape Bevy fell into. Decomposed components per [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) "Avoid" row 1. +- **Avoid:** stuffing all a11y into the base Node class. Godot Control has `accessibility_*` properties on the base class; this is the same megacomponent shape Bevy fell into. Decomposed components per [`docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) "Avoid" row 1. - **Avoid:** shipping a11y as "experimental." Buiy's v1 commits to AccessKit-tested-in-CI; Godot's experimental status is a fair pre-1.0 marker for *their* a11y but Buiy is starting from green field and should commit to AA-from-v1, not "experimental-from-v1." ## Sources diff --git a/docs/prior-art/godot-control/distribution-and-governance.md b/docs/prior-art/godot-control/distribution-and-governance.md index 5ad9497..0302ccf 100644 --- a/docs/prior-art/godot-control/distribution-and-governance.md +++ b/docs/prior-art/godot-control/distribution-and-governance.md @@ -76,7 +76,7 @@ Coordination happens via: - **Godot Engine Contributors Conference** (GodotCon) — annual in-person event; talks are recorded. - **Discord, Reddit, forum** — informal community channels. -No formal RFC process — design state lives across godot-proposals discussions and core-developer PR review. This is similar to Bevy's lightweight design-state model (see [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) "Avoid" row 10) with the same upsides (low overhead, contributor-friendly) and the same downsides (design history is scattered). +No formal RFC process — design state lives across godot-proposals discussions and core-developer PR review. This is similar to Bevy's lightweight design-state model (see [`docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) "Avoid" row 10) with the same upsides (low overhead, contributor-friendly) and the same downsides (design history is scattered). ## Platform support diff --git a/docs/prior-art/godot-control/ecosystem-and-comparisons.md b/docs/prior-art/godot-control/ecosystem-and-comparisons.md index 1b8867b..239ef59 100644 --- a/docs/prior-art/godot-control/ecosystem-and-comparisons.md +++ b/docs/prior-art/godot-control/ecosystem-and-comparisons.md @@ -75,7 +75,7 @@ Net: Slate is the strongest "game engine UI for AAA shipping" precedent but the ## Comparison to Bevy UI -See [`/home/user/buiy/docs/prior-art/bevy-ui/`](../bevy-ui/) for the full deep-dive. Sketch of the differences from Godot Control: +See [`docs/prior-art/bevy-ui/`](../bevy-ui/) for the full deep-dive. Sketch of the differences from Godot Control: - Bevy UI is **ECS-shaped** (Node + Style + ComputedNode + decomposed visual components); Godot is **scene-tree-shaped** (Control with bundled visual properties). - Bevy uses **Taffy** for layout (CSS Flex + Grid + Block); Godot does its own anchor + per-Container-class layout. diff --git a/docs/prior-art/godot-control/lessons.md b/docs/prior-art/godot-control/lessons.md index e88ea68..0ec9968 100644 --- a/docs/prior-art/godot-control/lessons.md +++ b/docs/prior-art/godot-control/lessons.md @@ -52,7 +52,7 @@ Pitfalls drawn from Godot's experience, with Buiy's mitigation. | **No virtualization in ItemList / Tree.** Render all items eagerly; large lists (10,000+ rows) stutter; user-built virtualization is necessary. | [`critiques-and-open-problems.md`](critiques-and-open-problems.md) § "Performance at scale" | Virtualization is a first-class widget concern in [`buiy-widget-catalog-design`](../../specs/2026-05-07-buiy-foundation/media-and-widgets.md). Borrow from [GPUI's `UniformList` / `List`](../gpui/lessons.md) for the implementation shape. | | **Three-way scripting fragmentation (GDScript / C# / GDExtension).** Each has different ergonomics; library / addon authors choose one and lose two. | [`distribution-and-governance.md`](distribution-and-governance.md), [`critiques-and-open-problems.md`](critiques-and-open-problems.md) § "Three-way scripting fragmentation" | Buiy is Rust-only. Fragmentation removed. Plugins consume Buiy via Bevy's plugin trait + crates.io; no parallel script-language story. | | **GDExtension ABI churn.** Rust plugins (via `gdext`) recompile per Godot minor. C++ source API drifts within 4.x. | [`distribution-and-governance.md`](distribution-and-governance.md) | Bevy minor releases are migration events for Buiy already (foundation §2.9); same model. Rust crates.io stable API per Bevy minor, no parallel ABI. | -| **Lightweight RFC process.** Design state across `godot-proposals` + Discord + recorded GodotCon talks. Lossy. | [`distribution-and-governance.md`](distribution-and-governance.md) § "Contributor base" | `docs/specs/` + `docs/plans/` + `docs/reports/` + `docs/prior-art/` discipline. Per CLAUDE.md ([`/home/user/buiy/CLAUDE.md`](../../../CLAUDE.md)). | +| **Lightweight RFC process.** Design state across `godot-proposals` + Discord + recorded GodotCon talks. Lossy. | [`distribution-and-governance.md`](distribution-and-governance.md) § "Contributor base" | `docs/specs/` + `docs/plans/` + `docs/reports/` + `docs/prior-art/` discipline. Per CLAUDE.md ([`CLAUDE.md`](../../../CLAUDE.md)). | ## Borrow @@ -92,10 +92,10 @@ When designing a Buiy feature: ## Cross-corpus reading -- [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) — the sister "game-engine UI" lessons file Buiy is parallel to. Read alongside this file when designing render pipeline, component decomposition, layout integration, or focus model. -- [`/home/user/buiy/docs/prior-art/accesskit/`](../accesskit/) — the a11y bridge both Bevy and Godot adopt. Two-engine validation of the substrate. -- [`/home/user/buiy/docs/prior-art/taffy/`](../taffy/) — the layout engine Buiy commits to. Read alongside [`layout-anchors-margins.md`](layout-anchors-margins.md) for the contrast. -- [`/home/user/buiy/docs/prior-art/cosmic-text/`](../cosmic-text/) — the text shaper Buiy commits to. Read alongside [`text-and-input.md`](text-and-input.md). +- [`docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) — the sister "game-engine UI" lessons file Buiy is parallel to. Read alongside this file when designing render pipeline, component decomposition, layout integration, or focus model. +- [`docs/prior-art/accesskit/`](../accesskit/) — the a11y bridge both Bevy and Godot adopt. Two-engine validation of the substrate. +- [`docs/prior-art/taffy/`](../taffy/) — the layout engine Buiy commits to. Read alongside [`layout-anchors-margins.md`](layout-anchors-margins.md) for the contrast. +- [`docs/prior-art/cosmic-text/`](../cosmic-text/) — the text shaper Buiy commits to. Read alongside [`text-and-input.md`](text-and-input.md). ## Sources diff --git a/docs/prior-art/gpui/README.md b/docs/prior-art/gpui/README.md index 636efdd..d3ff108 100644 --- a/docs/prior-art/gpui/README.md +++ b/docs/prior-art/gpui/README.md @@ -70,11 +70,11 @@ Three slots in Buiy's foundation map directly onto questions GPUI has already an ## Cross-links into the Buiy corpus -- [`/home/user/buiy/docs/prior-art/bevy-egui/lessons.md`](../bevy-egui/lessons.md) — the "Zed uses GPUI, NOT egui" anti-conflation note. -- [`/home/user/buiy/docs/prior-art/egui/lessons.md`](../egui/lessons.md) — the immediate-mode-only counterpoint to GPUI's hybrid. -- [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — names GPUI as a verified-false AccessKit adopter. -- [`/home/user/buiy/docs/prior-art/iced/`](../iced/) — Iced ships on `iced_wgpu` end-to-end; useful as the wgpu-only counterpoint. -- [`/home/user/buiy/docs/prior-art/slint/`](../slint/), [`/home/user/buiy/docs/prior-art/dioxus/`](../dioxus/) — the DSL-driven and React-style alternatives GPUI explicitly rejects. +- [`docs/prior-art/bevy-egui/lessons.md`](../bevy-egui/lessons.md) — the "Zed uses GPUI, NOT egui" anti-conflation note. +- [`docs/prior-art/egui/lessons.md`](../egui/lessons.md) — the immediate-mode-only counterpoint to GPUI's hybrid. +- [`docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — names GPUI as a verified-false AccessKit adopter. +- [`docs/prior-art/iced/`](../iced/) — Iced ships on `iced_wgpu` end-to-end; useful as the wgpu-only counterpoint. +- [`docs/prior-art/slint/`](../slint/), [`docs/prior-art/dioxus/`](../dioxus/) — the DSL-driven and React-style alternatives GPUI explicitly rejects. ## Sources diff --git a/docs/prior-art/gpui/accessibility.md b/docs/prior-art/gpui/accessibility.md index 086c1b4..f137557 100644 --- a/docs/prior-art/gpui/accessibility.md +++ b/docs/prior-art/gpui/accessibility.md @@ -42,7 +42,7 @@ GPUI provides the **clearest production-scale data point** on the cost of deferr ## What an AccessKit retrofit would require -Reverse-engineering from Buiy's own AccessKit-first design (foundation §2.6, [`/home/user/buiy/docs/prior-art/accesskit/integration.md`](../accesskit/integration.md)), retrofitting AccessKit into GPUI would need: +Reverse-engineering from Buiy's own AccessKit-first design (foundation §2.6, [`docs/prior-art/accesskit/integration.md`](../accesskit/integration.md)), retrofitting AccessKit into GPUI would need: 1. **Per-window adapter ownership.** Each `Window` needs to own an `accesskit_winit::Adapter` (or platform-specific equivalent, since GPUI doesn't use winit — it would need its own `accesskit_macos::Adapter`, `accesskit_windows::Adapter`, `accesskit_unix::Adapter` wiring). 2. **Element-level semantic data.** Every `Element` would need to provide role, name, value, state. The cleanest path is decomposed accessibility components attached via the `Styled` trait — same shape as `.bg(color)` but `.aria_role(Role::Button).aria_label("Save")`. @@ -81,5 +81,5 @@ The right answer for Buiy is the answer foundation §2.6 already commits to: own - VoiceOver tracking #8146: https://github.com/zed-industries/zed/discussions/8146 - HN: Zed deprioritizing GPUI community work: https://news.ycombinator.com/item?id=47003569 - Zed on Windows (accessibility-gap admission context): https://zed.dev/windows -- Cross-link: AccessKit lessons file (names GPUI as verified-false AccessKit adopter): [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) +- Cross-link: AccessKit lessons file (names GPUI as verified-false AccessKit adopter): [`docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) - Cross-link: bevy_a11y BSN issue #17644 (the megacomponent problem Buiy is structured to avoid): https://github.com/bevyengine/bevy/issues/17644 diff --git a/docs/prior-art/gpui/critiques-and-open-problems.md b/docs/prior-art/gpui/critiques-and-open-problems.md index 62a43d4..ed0dbf0 100644 --- a/docs/prior-art/gpui/critiques-and-open-problems.md +++ b/docs/prior-art/gpui/critiques-and-open-problems.md @@ -140,4 +140,4 @@ GPUI's atlas + batched-instance model is GPU-memory-intensive. On integrated gra - NVIDIA PRIME PR #23438: https://github.com/zed-industries/zed/pull/23438 - HN: deprioritization announcement: https://news.ycombinator.com/item?id=47003569 - HN: gpui-ce founder reflection: https://news.ycombinator.com/item?id=47005761 -- Cross-link: Buiy foundation: [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/`](../../specs/2026-05-07-buiy-foundation/) +- Cross-link: Buiy foundation: [`docs/specs/2026-05-07-buiy-foundation/`](../../specs/2026-05-07-buiy-foundation/) diff --git a/docs/prior-art/gpui/ecosystem-and-comparisons.md b/docs/prior-art/gpui/ecosystem-and-comparisons.md index fcd3302..658f112 100644 --- a/docs/prior-art/gpui/ecosystem-and-comparisons.md +++ b/docs/prior-art/gpui/ecosystem-and-comparisons.md @@ -66,7 +66,7 @@ Per the HN founder comment ([47005761](https://news.ycombinator.com/item?id=4700 GPUI sits in a specific quadrant of the Rust UI design space: **GPU-accelerated, retained-mode (with immediate-mode escape hatch), custom paradigm, native-API-first**. The neighbors are different bets. -### vs egui ([`/home/user/buiy/docs/prior-art/egui/`](../egui/)) +### vs egui ([`docs/prior-art/egui/`](../egui/)) | | egui | GPUI | |---|---|---| @@ -83,7 +83,7 @@ GPUI sits in a specific quadrant of the Rust UI design space: **GPU-accelerated, GPUI wins on **idle cost** and **production-app polish**. egui wins on **simplicity** and **dev-tool fit**. They don't compete directly — egui is the dev-tool/debug/inspector default, GPUI is the production-app retained-mode bet. Buiy plans to **use bevy_egui for its own dev tooling** (foundation `cross-cutting.md` § 3.18 and bevy-egui lessons) while building production UI on its own retained-mode pipeline more analogous to GPUI's shape. -### vs Iced ([`/home/user/buiy/docs/prior-art/iced/`](../iced/)) +### vs Iced ([`docs/prior-art/iced/`](../iced/)) | | Iced | GPUI | |---|---|---| @@ -101,7 +101,7 @@ GPUI wins on **idle cost** and **production-app polish**. egui wins on **simplic GPUI vs Iced is the **mutability** debate played out at framework scale. Iced's Elm purity is intellectually satisfying and produces clean code; GPUI's mutability is pragmatic and produces fast code. Both ship production apps. Neither has shipped accessibility. The renderer-uniformity bet (Iced = wgpu everywhere; GPUI = native where possible) is the cleanest empirical comparison — both produce shippable cross-platform apps, but Iced has uniform behavior while GPUI has platform-native polish at the cost of three code paths. -### vs Slint ([`/home/user/buiy/docs/prior-art/slint/`](../slint/)) +### vs Slint ([`docs/prior-art/slint/`](../slint/)) | | Slint | GPUI | |---|---|---| @@ -116,7 +116,7 @@ GPUI vs Iced is the **mutability** debate played out at framework scale. Iced's Slint and GPUI represent **two different bets on where UI authoring lives**. Slint compiles a separate DSL into UI code; GPUI is "the UI is Rust." Slint's hot-reload at the DSL level is a Buiy-relevant feature (Buiy commits to hot-reloadable BSN); GPUI lacks any equivalent and likely never will because the UI _is_ Rust source. -### vs Dioxus ([`/home/user/buiy/docs/prior-art/dioxus/`](../dioxus/)) +### vs Dioxus ([`docs/prior-art/dioxus/`](../dioxus/)) | | Dioxus | GPUI | |---|---|---| @@ -163,6 +163,6 @@ The right summary: **Buiy is "GPUI with Bevy's ECS doing the ownership work, Acc - HN reference "almost no usage": https://news.ycombinator.com/item?id=45721667 - HN gpui-ce founder reflection: https://news.ycombinator.com/item?id=47005761 - Glass-HQ/gpui (unrelated namespace collision): https://github.com/Glass-HQ/gpui -- Cross-link prior-art folders: egui, Iced, Slint, Dioxus in [`/home/user/buiy/docs/prior-art/`](../) +- Cross-link prior-art folders: egui, Iced, Slint, Dioxus in [`docs/prior-art/`](../) - Xilem: https://github.com/linebender/xilem - Vello: https://github.com/linebender/vello diff --git a/docs/prior-art/gpui/element-tree.md b/docs/prior-art/gpui/element-tree.md index 0e88ac3..b635e7b 100644 --- a/docs/prior-art/gpui/element-tree.md +++ b/docs/prior-art/gpui/element-tree.md @@ -164,5 +164,5 @@ Three things Buiy can learn from GPUI's element model: - GPUI docs.rs (Render, Element, Div, Styled): https://docs.rs/gpui/latest/gpui/ - _Ownership and data flow in GPUI_: https://zed.dev/blog/gpui-ownership - GPUI README: https://github.com/zed-industries/zed/blob/main/crates/gpui/README.md -- Cross-link: bevy_egui lessons (Zed-vs-egui comparison): [`/home/user/buiy/docs/prior-art/bevy-egui/lessons.md`](../bevy-egui/lessons.md) -- Cross-link: Iced Elm-architecture: [`/home/user/buiy/docs/prior-art/iced/elm-architecture.md`](../iced/elm-architecture.md) +- Cross-link: bevy_egui lessons (Zed-vs-egui comparison): [`docs/prior-art/bevy-egui/lessons.md`](../bevy-egui/lessons.md) +- Cross-link: Iced Elm-architecture: [`docs/prior-art/iced/elm-architecture.md`](../iced/elm-architecture.md) diff --git a/docs/prior-art/gpui/lessons.md b/docs/prior-art/gpui/lessons.md index 2a1f975..d034a21 100644 --- a/docs/prior-art/gpui/lessons.md +++ b/docs/prior-art/gpui/lessons.md @@ -62,12 +62,12 @@ These GPUI design ideas are worth studying and clean-room reimplementing in Buiy ## Cross-link map -- [`/home/user/buiy/docs/prior-art/bevy-egui/lessons.md`](../bevy-egui/lessons.md) — corrects "Zed uses egui" conflation; names GPUI as the actual Zed UI stack. -- [`/home/user/buiy/docs/prior-art/egui/lessons.md`](../egui/lessons.md) — immediate-mode-only counterpoint to GPUI's hybrid. -- [`/home/user/buiy/docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — names GPUI as verified-false AccessKit adopter; reinforces a11y-first commitment. -- [`/home/user/buiy/docs/prior-art/iced/lessons.md`](../iced/lessons.md) — wgpu-uniform retained-mode counterpoint to GPUI's three-backend native-API strategy. -- [`/home/user/buiy/docs/prior-art/cosmic-text/`](../cosmic-text/) — text-stack alternative to GPUI's OS-native shaping. -- [`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) §§2.2-2.3 — the foundation sections this corpus most directly informs. +- [`docs/prior-art/bevy-egui/lessons.md`](../bevy-egui/lessons.md) — corrects "Zed uses egui" conflation; names GPUI as the actual Zed UI stack. +- [`docs/prior-art/egui/lessons.md`](../egui/lessons.md) — immediate-mode-only counterpoint to GPUI's hybrid. +- [`docs/prior-art/accesskit/lessons.md`](../accesskit/lessons.md) — names GPUI as verified-false AccessKit adopter; reinforces a11y-first commitment. +- [`docs/prior-art/iced/lessons.md`](../iced/lessons.md) — wgpu-uniform retained-mode counterpoint to GPUI's three-backend native-API strategy. +- [`docs/prior-art/cosmic-text/`](../cosmic-text/) — text-stack alternative to GPUI's OS-native shaping. +- [`docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) §§2.2-2.3 — the foundation sections this corpus most directly informs. ## Sources diff --git a/docs/prior-art/gpui/text-and-input.md b/docs/prior-art/gpui/text-and-input.md index 453d068..9542014 100644 --- a/docs/prior-art/gpui/text-and-input.md +++ b/docs/prior-art/gpui/text-and-input.md @@ -126,4 +126,4 @@ Buiy's foundation §3.7 commits to drag-and-drop with a **drag a11y replacement - DeepWiki GPUI section: https://deepwiki.com/zed-industries/zed/2.2-ui-framework-(gpui) - Zed on Windows (DirectWrite + DX11): https://zed.dev/windows - bevy#21765 (Bevy main migration to Parley): https://github.com/bevyengine/bevy/issues/21765 -- Cross-link: cosmic-text prior-art: [`/home/user/buiy/docs/prior-art/cosmic-text/`](../cosmic-text/) +- Cross-link: cosmic-text prior-art: [`docs/prior-art/cosmic-text/`](../cosmic-text/) diff --git a/docs/prior-art/iced/README.md b/docs/prior-art/iced/README.md index a4b7a6c..f46d5b4 100644 --- a/docs/prior-art/iced/README.md +++ b/docs/prior-art/iced/README.md @@ -93,7 +93,7 @@ A secondary disclosure: Iced is *not* an integration target — it is a peer in - cosmic-text — https://github.com/pop-os/cosmic-text - Iced issue #552 (accessibility) — https://github.com/iced-rs/iced/issues/552 - Bevy issue #21765 (cosmic-text → Parley migration) — https://github.com/bevyengine/bevy/issues/21765 -- Buiy foundation README — `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/README.md` -- Buiy foundation architecture — `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md` +- Buiy foundation README — `docs/specs/2026-05-07-buiy-foundation/README.md` +- Buiy foundation architecture — `docs/specs/2026-05-07-buiy-foundation/architecture.md` - cosmic-text prior-art folder — [`../cosmic-text/`](../cosmic-text/) - bevy-ui prior-art folder — [`../bevy-ui/`](../bevy-ui/) diff --git a/docs/prior-art/iced/critiques.md b/docs/prior-art/iced/critiques.md index 78bafba..8fc9535 100644 --- a/docs/prior-art/iced/critiques.md +++ b/docs/prior-art/iced/critiques.md @@ -159,5 +159,5 @@ The Kraken/Cryptowatch sponsorship gives Héctor financial runway; this does not - PR #2662 (reactive rendering) — https://github.com/iced-rs/iced/pull/2662 - PR #2757 (Animation API) — https://github.com/iced-rs/iced/pull/2757 - PR #1697 (text shaping overhaul / iced_wgpu refactor) — https://github.com/iced-rs/iced/pull/1697 -- Buiy foundation architecture — /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md -- Buiy bevy-ui lessons — /home/user/buiy/docs/prior-art/bevy-ui/lessons.md +- Buiy foundation architecture — docs/specs/2026-05-07-buiy-foundation/architecture.md +- Buiy bevy-ui lessons — docs/prior-art/bevy-ui/lessons.md diff --git a/docs/prior-art/iced/governance.md b/docs/prior-art/iced/governance.md index 103c45a..fe887f3 100644 --- a/docs/prior-art/iced/governance.md +++ b/docs/prior-art/iced/governance.md @@ -71,7 +71,7 @@ There is **no formal RFC process**. Major architectural decisions are discussed The 14-month gap between 0.13 and 0.14 is partly explained by the absence of an RFC discipline: there is no public "we will ship X next" milestone tracker tied to dates. The Whimsical roadmap is the closest analog and is informal. -**Lesson for Buiy:** the lightweight-process choice has cost iced legibility — feature requests sit unresolved for years (issue #552 since 2020), and outsiders cannot predict what lands when. Buiy's commitment to `docs/specs/` + `docs/plans/` (foundation [README § Code Conventions](../../specs/2026-05-07-buiy-foundation/README.md)) is informed by exactly this gap. See [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) Avoid row "Lightweight RFC process" for the matched pattern in Bevy. +**Lesson for Buiy:** the lightweight-process choice has cost iced legibility — feature requests sit unresolved for years (issue #552 since 2020), and outsiders cannot predict what lands when. Buiy's commitment to `docs/specs/` + `docs/plans/` (foundation [README § Code Conventions](../../specs/2026-05-07-buiy-foundation/README.md)) is informed by exactly this gap. See [`docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) Avoid row "Lightweight RFC process" for the matched pattern in Bevy. ## Sources diff --git a/docs/prior-art/iced/history.md b/docs/prior-art/iced/history.md index 0de0118..2ddb619 100644 --- a/docs/prior-art/iced/history.md +++ b/docs/prior-art/iced/history.md @@ -57,7 +57,7 @@ Concrete effects: - `iced_glow` and `iced_glutin` (OpenGL renderers) are deprecated in this same release. The renderer pair becomes `iced_wgpu` (GPU) + `iced_tiny_skia` (CPU software fallback). - The CHANGELOG also lists *"Software renderer, runtime renderer fallback, and core consolidation"* — `iced_tiny_skia` is introduced. -This is a load-bearing fact for Buiy: **iced's text stack is cosmic-text, not Parley**. The brief that produced this folder asserted "Parley text"; that is wrong as of 0.14. Buiy's own cosmic-text commitment (foundation [architecture.md § 2.2](../../specs/2026-05-07-buiy-foundation/architecture.md)) thus shares a substrate with iced, not a competing engine. See [Agent A's `text-and-cosmic.md`](text-and-cosmic.md) for the full text-rendering walkthrough and [`/home/user/buiy/docs/prior-art/cosmic-text/lessons.md`](../cosmic-text/lessons.md) for cosmic-text's own state. +This is a load-bearing fact for Buiy: **iced's text stack is cosmic-text, not Parley**. The brief that produced this folder asserted "Parley text"; that is wrong as of 0.14. Buiy's own cosmic-text commitment (foundation [architecture.md § 2.2](../../specs/2026-05-07-buiy-foundation/architecture.md)) thus shares a substrate with iced, not a competing engine. See [Agent A's `text-and-cosmic.md`](text-and-cosmic.md) for the full text-rendering walkthrough and [`docs/prior-art/cosmic-text/lessons.md`](../cosmic-text/lessons.md) for cosmic-text's own state. ## 0.11 — never released @@ -67,7 +67,7 @@ There is no `0.11.x` on crates.io. The 0.10 → 0.12 gap (~7 months) corresponds PR [#1964](https://github.com/iced-rs/iced/pull/1964) — *Multi-window support*. The single most-requested feature in the previous two years. The single `Application` trait becomes capable of managing multiple winit windows from one `Model` / `update` / `view` triad. Each window can have its own `view` projection. -This is the architectural decision that, for Buiy, makes iced's per-window approach legible: iced commits to *one process = one Model = many windows*, exactly the model bevy_ui adopted via its `Window` entity per winit `WindowId`. See [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) § Borrow #7 for the parallel. +This is the architectural decision that, for Buiy, makes iced's per-window approach legible: iced commits to *one process = one Model = many windows*, exactly the model bevy_ui adopted via its `Window` entity per winit `WindowId`. See [`docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) § Borrow #7 for the parallel. `0.12.1` (2024-02-22) followed with bug fixes. diff --git a/docs/prior-art/iced/lessons.md b/docs/prior-art/iced/lessons.md index 1815b92..cda74e6 100644 --- a/docs/prior-art/iced/lessons.md +++ b/docs/prior-art/iced/lessons.md @@ -70,7 +70,7 @@ When designing a Buiy feature: ## Sources - All sibling files in this folder. -- Buiy foundation spec — `/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/` +- Buiy foundation spec — `docs/specs/2026-05-07-buiy-foundation/` - Iced repository — https://github.com/iced-rs/iced - Iced 0.14.0 release notes — https://github.com/iced-rs/iced/releases/tag/0.14.0 - Iced book — https://book.iced.rs/ diff --git a/docs/prior-art/iced/open-problems.md b/docs/prior-art/iced/open-problems.md index 2551442..c1ede93 100644 --- a/docs/prior-art/iced/open-problems.md +++ b/docs/prior-art/iced/open-problems.md @@ -16,7 +16,7 @@ This file is the forward-looking complement to [`critiques.md`](critiques.md). C 3. The single-Model architecture has no built-in observer for "the visible widget tree changed." 4. Héctor has not personally championed the feature; the COSMIC team has built bespoke AccessKit wiring in `libcosmic` rather than upstream. -**Implications for Buiy:** Buiy's AccessKit-first commitment (foundation [accessibility.md](../../specs/2026-05-07-buiy-foundation/accessibility.md)) intentionally rejects iced's path. Buiy's decomposed-component model gives each widget a stable `Entity` identity; the AccessKit adapter consumes those entities directly. The Buiy foundation [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) Avoid row "Megacomponents that are BSN-hostile" applies in spirit here too — iced's `Theme` + `Widget` pair is the equivalent of a megacomponent for a11y purposes. +**Implications for Buiy:** Buiy's AccessKit-first commitment (foundation [accessibility.md](../../specs/2026-05-07-buiy-foundation/accessibility.md)) intentionally rejects iced's path. Buiy's decomposed-component model gives each widget a stable `Entity` identity; the AccessKit adapter consumes those entities directly. The Buiy foundation [`docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) Avoid row "Megacomponents that are BSN-hostile" applies in spirit here too — iced's `Theme` + `Widget` pair is the equivalent of a megacomponent for a11y purposes. ## Mobile target maturity @@ -51,7 +51,7 @@ This file is the forward-looking complement to [`critiques.md`](critiques.md). C 2. Adding Grid support directly to iced's layout would duplicate Taffy's work. 3. There is no public roadmap commitment to Grid layout. -**Implications for Buiy:** Buiy commits to Taffy directly (foundation [architecture.md § 2.2](../../specs/2026-05-07-buiy-foundation/architecture.md)) and inherits Grid, block layout, float, named-line grid, etc. for free. This is a Validates row in [`/home/user/buiy/docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) — bevy_ui's 3.5 years on Taffy confirms the choice. +**Implications for Buiy:** Buiy commits to Taffy directly (foundation [architecture.md § 2.2](../../specs/2026-05-07-buiy-foundation/architecture.md)) and inherits Grid, block layout, float, named-line grid, etc. for free. This is a Validates row in [`docs/prior-art/bevy-ui/lessons.md`](../bevy-ui/lessons.md) — bevy_ui's 3.5 years on Taffy confirms the choice. ## Animation / transition primitives @@ -117,7 +117,7 @@ Considerations: - COSMIC is also cosmic-text-based (System76 is the cosmic-text steward). - Bevy migrated `bevy_text` from cosmic-text → Parley + swash (issue [#21765](https://github.com/bevyengine/bevy/issues/21765)). Iced is not following. -**Implications for Buiy:** Buiy commits to cosmic-text (foundation [text.md](../../specs/2026-05-07-buiy-foundation/text.md), informed by [`/home/user/buiy/docs/prior-art/cosmic-text/lessons.md`](../cosmic-text/lessons.md)). Buiy and iced share this substrate even as bevy_ui moves away. The cosmic-text constituency is shrinking from bevy_ui's exit but staying stable from iced + COSMIC. See [`history.md`](history.md) § "0.10 — text-engine switch." +**Implications for Buiy:** Buiy commits to cosmic-text (foundation [text.md](../../specs/2026-05-07-buiy-foundation/text.md), informed by [`docs/prior-art/cosmic-text/lessons.md`](../cosmic-text/lessons.md)). Buiy and iced share this substrate even as bevy_ui moves away. The cosmic-text constituency is shrinking from bevy_ui's exit but staying stable from iced + COSMIC. See [`history.md`](history.md) § "0.10 — text-engine switch." ## Theme tokenization @@ -141,5 +141,5 @@ Considerations: - cryoglyph (iced's glyphon fork) — https://github.com/iced-rs/cryoglyph - cosmic-text — https://github.com/pop-os/cosmic-text - Linebender Parley — https://github.com/linebender/parley -- Buiy foundation accessibility — /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/accessibility.md -- Buiy foundation verification — /home/user/buiy/docs/specs/2026-05-07-buiy-foundation/verification.md +- Buiy foundation accessibility — docs/specs/2026-05-07-buiy-foundation/accessibility.md +- Buiy foundation verification — docs/specs/2026-05-07-buiy-foundation/verification.md diff --git a/docs/prior-art/kayak-ui/README.md b/docs/prior-art/kayak-ui/README.md index dfab5b5..3828822 100644 --- a/docs/prior-art/kayak-ui/README.md +++ b/docs/prior-art/kayak-ui/README.md @@ -67,7 +67,7 @@ When designing a Buiy feature: start at [`lessons.md`](lessons.md); read [`why-a - [`docs/prior-art/bevy-cosmic-edit/`](../bevy-cosmic-edit/) — sister archived case study (deliberate archive, bridge-crate failure mode). Read [`bevy-cosmic-edit/lessons.md`](../bevy-cosmic-edit/lessons.md) for the deliberate-archive counterpart pattern. - [`docs/prior-art/bevy-ui/`](../bevy-ui/) — the host ecosystem. Read [`bevy-ui/lessons.md`](../bevy-ui/lessons.md) § Top-of-file finding 1 ("BSN has not landed; design for it") — kayak_ui's `rsx!` macro is exactly the *wrong shape* for the BSN-friendly-by-construction stance. - [`docs/prior-art/taffy/`](../taffy/) — the layout engine bevy_ui + Buiy use. kayak_ui chose **morphorm** instead; see [`architecture.md` § Layout](architecture.md#layout). -- (future) `docs/prior-art/woodpecker-ui/` — kayak_ui's successor by the same maintainer. Not yet documented; cross-link when that folder lands. +- [`docs/prior-art/woodpecker-ui/`](../woodpecker-ui/) — kayak_ui's successor by the same maintainer. - [`docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) — the Buiy architecture spec this folder informs (parallel-stack rationale, ECS-native authoring, no-custom-DSL stance). ## Glossary stub diff --git a/docs/prior-art/sickle-ui/distribution.md b/docs/prior-art/sickle-ui/distribution.md index f38a099..0174123 100644 --- a/docs/prior-art/sickle-ui/distribution.md +++ b/docs/prior-art/sickle-ui/distribution.md @@ -74,4 +74,4 @@ The effect: an integrator can install sickle_ui via `cargo add`, but the upstrea - Deleted upstream (404) — https://github.com/UmbraLuminosa/sickle_ui - UmbraLuminosa org — https://github.com/UmbraLuminosa - bevy-assets UI listing (no sickle entry) — https://github.com/bevyengine/bevy-assets/tree/main/Assets/UI -- Buiy CLAUDE.md (dev guidelines) — `/home/user/buiy/CLAUDE.md` +- Buiy CLAUDE.md (dev guidelines) — `CLAUDE.md` diff --git a/docs/prior-art/slint/accessibility.md b/docs/prior-art/slint/accessibility.md index 5ad7623..520d716 100644 --- a/docs/prior-art/slint/accessibility.md +++ b/docs/prior-art/slint/accessibility.md @@ -50,7 +50,7 @@ The author writes declarative accessibility properties; the runtime stitches the The Slint standard widgets (`Button`, `CheckBox`, `LineEdit`, `Slider`, `TabWidget`, `ListView`, …) already set their `accessible-role` and route their public properties (`text`, `checked`, `value`) to the corresponding `accessible-*` fields. App authors get accessibility "for free" for the standard widget set; custom widgets carry the burden explicitly. -This is the same posture as Buiy's "every Buiy widget ships with its APG keyboard contract, accessible name/role/value, focus management, AccessKit tree wiring" ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/README.md`](../../specs/2026-05-07-buiy-foundation/README.md) goal 2). Slint validates the choice — pre-wired widgets work; the burden lands when authors build custom controls. +This is the same posture as Buiy's "every Buiy widget ships with its APG keyboard contract, accessible name/role/value, focus management, AccessKit tree wiring" ([`docs/specs/2026-05-07-buiy-foundation/README.md`](../../specs/2026-05-07-buiy-foundation/README.md) goal 2). Slint validates the choice — pre-wired widgets work; the burden lands when authors build custom controls. ## Known gaps @@ -62,10 +62,10 @@ This is the same posture as Buiy's "every Buiy widget ships with its APG keyboar ## Implications for Buiy -- **Slint is real-world evidence that AccessKit producer integration ships.** Three years of production AccessKit integration in safety-critical industrial UIs (OTIV rail automation). The pattern works; the bugs are scoped (popup panics, list-view virtualization gap, version-pin lag). Buiy's AccessKit-first commitment ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.6) is validated. +- **Slint is real-world evidence that AccessKit producer integration ships.** Three years of production AccessKit integration in safety-critical industrial UIs (OTIV rail automation). The pattern works; the bugs are scoped (popup panics, list-view virtualization gap, version-pin lag). Buiy's AccessKit-first commitment ([`docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.6) is validated. - **Property-level a11y attributes work — and translate cleanly to decomposed-components.** Slint's `accessible-*` item properties are the DSL form of Buiy's `A11yRole` / `A11yLabel` / `A11yDescription` / `A11yStates` / `A11yRelations` ECS components. Same separation of concerns, different authoring surface. Both designs avoid the `bevy_a11y::AccessibilityNode` megacomponent pitfall (see [`../bevy-ui/lessons.md`](../bevy-ui/lessons.md) row 1). - **Version-pin lag is the real ongoing cost.** Slint pins AccessKit and accumulates lag — currently 4 minor releases behind `accesskit_winit` 0.33.0 (Slint stuck around 0.16-era; upstream at 0.33.0). Buiy's "AccessKit major release between Bevy minors triggers a Buiy patch release" policy ([`../../specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.9, foundation README § 5 open question) needs to be lived in practice. Slint's experience suggests upgrade-blocked windows of 6–12 months happen; Buiy should plan for that. -- **Standard widgets must pre-wire a11y.** Slint's stdlib widgets pre-wire `accessible-role` and route public properties to a11y fields; custom widgets carry the burden explicitly. Buiy's widget-catalog sub-spec ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/media-and-widgets.md`](../../specs/2026-05-07-buiy-foundation/media-and-widgets.md)) commits to this — every APG-shaped Buiy widget ships with its AccessKit wiring. Slint validates that this is the right scope; the cost of NOT pre-wiring is "third-party widgets are inaccessible by default," which is how the broader Rust UI ecosystem looks today. +- **Standard widgets must pre-wire a11y.** Slint's stdlib widgets pre-wire `accessible-role` and route public properties to a11y fields; custom widgets carry the burden explicitly. Buiy's widget-catalog sub-spec ([`docs/specs/2026-05-07-buiy-foundation/media-and-widgets.md`](../../specs/2026-05-07-buiy-foundation/media-and-widgets.md)) commits to this — every APG-shaped Buiy widget ships with its AccessKit wiring. Slint validates that this is the right scope; the cost of NOT pre-wiring is "third-party widgets are inaccessible by default," which is how the broader Rust UI ecosystem looks today. - **Slint does NOT compute ACCNAME 1.2.** Buiy's "ACCNAME 1.2 in `buiy_core`" decision ([`../accesskit/lessons.md`](../accesskit/lessons.md) Validates §5) is genuinely a Buiy-specific commitment, not industry-standard. Don't expect AccessKit consumers (Slint, egui, Freya, Xilem) to provide a reference implementation; Buiy is on its own here. ## Sources diff --git a/docs/prior-art/slint/architecture.md b/docs/prior-art/slint/architecture.md index 401520a..485f9fa 100644 --- a/docs/prior-art/slint/architecture.md +++ b/docs/prior-art/slint/architecture.md @@ -6,7 +6,7 @@ Slint's load-bearing architectural choice is that the **`.slint` DSL is the source of truth**, not the host language. A `.slint` file is parsed by the Slint compiler at build time (Rust: macro `slint!` or `slint_build` in `build.rs`; C++: CMake invocation; JS / Python: `npm install` / `pip install` ships the compiler as a native binary), and the compiler emits host-language code that constructs and mutates a tree of native UI objects at runtime. The runtime is **retained-mode** — the object tree persists across frames; property bindings re-evaluate when their inputs change; the renderer redraws only dirty regions. -This shape is the *opposite* of Bevy's ECS-first model. In Bevy, the host language (Rust) constructs entities and components; UI is one consumer of the ECS. In Slint, the DSL constructs the UI; the host language is glue. Buiy commits to the Bevy shape ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.4, BSN-native goal 3); Slint is the comparison case. +This shape is the *opposite* of Bevy's ECS-first model. In Bevy, the host language (Rust) constructs entities and components; UI is one consumer of the ECS. In Slint, the DSL constructs the UI; the host language is glue. Buiy commits to the Bevy shape ([`docs/specs/2026-05-07-buiy-foundation/architecture.md`](../../specs/2026-05-07-buiy-foundation/architecture.md) § 2.4, BSN-native goal 3); Slint is the comparison case. ## The compiler pipeline @@ -57,7 +57,7 @@ The renderer choice is orthogonal to the platform backend (winit, Qt, ESP-IDF, e The single most-studied piece of Slint's runtime is the property binding evaluator. Properties form a directed dependency graph; binding expressions are pure (compiler-enforced); evaluation is lazy and memoized; updates propagate via dirty marking. This is the "reactive" core that lets the DSL look declarative without paying for per-frame full re-evaluation. -The property binding model is what Buiy's foundation spec ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/cross-cutting.md`](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) § state/data/reactivity, currently observers+change-detection-only-in-v1) explicitly *defers* — Bevy's observers + change-detection are Buiy's primitive instead. But "should a signal/computed/effect layer ship as a follow-up sub-spec?" is open (foundation README § 5), and Slint's binding evaluator is the canonical Rust-ecosystem reference for what that would look like. +The property binding model is what Buiy's foundation spec ([`docs/specs/2026-05-07-buiy-foundation/cross-cutting.md`](../../specs/2026-05-07-buiy-foundation/cross-cutting.md) § state/data/reactivity, currently observers+change-detection-only-in-v1) explicitly *defers* — Bevy's observers + change-detection are Buiy's primitive instead. But "should a signal/computed/effect layer ship as a follow-up sub-spec?" is open (foundation README § 5), and Slint's binding evaluator is the canonical Rust-ecosystem reference for what that would look like. ## Implications for Buiy diff --git a/docs/prior-art/slint/dsl-language.md b/docs/prior-art/slint/dsl-language.md index 2089f4c..74d645a 100644 --- a/docs/prior-art/slint/dsl-language.md +++ b/docs/prior-art/slint/dsl-language.md @@ -163,7 +163,7 @@ The tooling story is a clear strength relative to the rest of the Rust UI ecosys ## Implications for Buiy -- **The `in` / `out` / `in-out` qualifiers are a clean property-visibility design Buiy could borrow at the component level.** BSN-friendly Buiy components already commit to "small, public-fielded, observable, decomposed"; Slint's qualifiers are the same idea expressed as a property-direction taxonomy. Borrowable for component-API conventions in the widget catalog ([`/home/user/buiy/docs/specs/2026-05-07-buiy-foundation/media-and-widgets.md`](../../specs/2026-05-07-buiy-foundation/media-and-widgets.md)). +- **The `in` / `out` / `in-out` qualifiers are a clean property-visibility design Buiy could borrow at the component level.** BSN-friendly Buiy components already commit to "small, public-fielded, observable, decomposed"; Slint's qualifiers are the same idea expressed as a property-direction taxonomy. Borrowable for component-API conventions in the widget catalog ([`docs/specs/2026-05-07-buiy-foundation/media-and-widgets.md`](../../specs/2026-05-07-buiy-foundation/media-and-widgets.md)). - **Purity-enforced binding expressions are a useful primitive if Buiy ever adds a reactivity layer.** Slint enforces purity at compile time; a Bevy-side equivalent would enforce purity in the type system of any signal/computed primitive. Open question in foundation README § 5. - **Two-way binding (`<=>`) is the canonical form-state primitive.** Buiy's `buiy-forms-design` sub-spec will need an equivalent; Slint's two-way binding (with cycle detection) is the most directly borrowable shape. - **Live Preview is a tooling target.** Buiy's `buiy-devtools-design` sub-spec lists inspector / overlay / contrast checker / focus visualizer / theme editor; adding a "hot-reload a `.bsn` file with WASM-rendered preview" is the moral equivalent of Slint's Live Preview, and it would be a clear competitive differentiator. The Figma plugin is also worth studying — exporting tokens from Figma into Buiy's semantic-tokens system would be a 1.x feature, not a v1 commitment, but Slint's plugin is the prior art. diff --git a/docs/prior-art/unity-ui/README.md b/docs/prior-art/unity-ui/README.md index fcfec98..7cff11b 100644 --- a/docs/prior-art/unity-ui/README.md +++ b/docs/prior-art/unity-ui/README.md @@ -71,7 +71,7 @@ Throughout this corpus, **"UGUI"** and **"UI Toolkit"** are kept distinct. Where 1. **If you are designing a Buiy feature** that has a web-platform analog — start at [`lessons.md`](lessons.md), then dive into [`uxml-uss-web-parallels.md`](uxml-uss-web-parallels.md) and [`ui-toolkit-architecture.md`](ui-toolkit-architecture.md). UI Toolkit is the worked example for what shipping web-flavored UI inside a game engine looks like at scale. 2. **If you are designing BSN authoring** (foundation §2.4) — start at [`editor-ui-migration.md`](editor-ui-migration.md). The IMGUI→UI Toolkit migration is a 7-year cautionary tale Buiy must learn from. 3. **If you are auditing accessibility** — start at [`accessibility.md`](accessibility.md), then [`critiques-and-open-problems.md`](critiques-and-open-problems.md) § "Accessibility lag." Unity's a11y module is recent (2023.2), partial, and has no ARIA model. -4. **If you are scoping the USS / stylesheet open question** (foundation README §5) — [`uxml-uss-web-parallels.md`](uxml-uss-web-parallels.md) catalogs exactly which CSS features Unity ships, which it deviates on, and which it does not have. Pair with [`/home/user/buiy/docs/prior-art/bevy-flair/`](../bevy-flair/). +4. **If you are scoping the USS / stylesheet open question** (foundation README §5) — [`uxml-uss-web-parallels.md`](uxml-uss-web-parallels.md) catalogs exactly which CSS features Unity ships, which it deviates on, and which it does not have. Pair with [`../bevy-flair/`](../bevy-flair/). 5. **If you are evaluating proprietary-substrate governance risk** — [`distribution-and-governance.md`](distribution-and-governance.md) covers the Runtime Fee 2023 saga. ## Framing disclosure diff --git a/docs/prior-art/unity-ui/critiques-and-open-problems.md b/docs/prior-art/unity-ui/critiques-and-open-problems.md index a9b5399..79ef831 100644 --- a/docs/prior-art/unity-ui/critiques-and-open-problems.md +++ b/docs/prior-art/unity-ui/critiques-and-open-problems.md @@ -29,7 +29,7 @@ This file collects the critiques Unity UI has accumulated across twelve years (U 7. **Accessibility integration is parallel, not unified.** The 2023.2+ Accessibility module is **a separate API stack**, not integrated into UXML authoring. There is no `aria-*` attribute on `