diff --git a/docs/decisions/adrs/ADR-0004-upstream-dependencies.md b/docs/decisions/adrs/ADR-0004-upstream-dependencies.md index a897658..adc6030 100644 --- a/docs/decisions/adrs/ADR-0004-upstream-dependencies.md +++ b/docs/decisions/adrs/ADR-0004-upstream-dependencies.md @@ -99,7 +99,9 @@ Advisory-ignore policy (mirrors the same CI job): - `RUSTSEC-2026-0192` (`ttf-parser`, unmaintained, winit/Metal paths) and `RUSTSEC-2024-0436` (`paste`, unmaintained) are enumerated as ignores in both `deny.toml` (`[advisories].ignore`) and the `cargo audit --ignore` - step until upstream replacements land, composing with rule 4. + step until upstream replacements land, composing with rule 4. Note that + `fontdb 0.24` (Issue [#1692](https://github.com/bitty-terminal/bitty/issues/1692), CTX-0993) vendors its query parser and drops the fontdb edge + to `ttf-parser`; the ignore remains scoped to winit/sctk/ab_glyph paths. - Ignore entries are visible enumerations, not standing waivers: they are re-checked as part of rule-4 maintenance and removed when a replacement lands. @@ -110,13 +112,13 @@ the implemented supply-chain gate today. ### Decisions per candidate -| Candidate | Decision | License check | Rationale | -| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| VT parsing: `vte` vs `alacritty_terminal` vs `wezterm-term` | **Adopt `vte`** (alacritty/vte, ~0.15.x) inside `bitty-vt` behind the crate's own API; reject `alacritty_terminal` and `wezterm-term` wholesale | Apache-2.0 — compatible | Terminal state machines are Core semantics (strategy table: own directly). `vte` provides only a state-machine table + `Perform` trait, which maps exactly onto the parser→`TerminalAction` split in the Architecture Overview. `alacritty_terminal` and `wezterm-term` bundle grid/state/replay opinions that would contaminate Terminal Truth ownership and are hard to partially adopt. If `vte` proves insufficient, escalate to a narrow synchronizable fork of its tables only. | -| PTY: `portable-pty` | **Wrap** (wezterm/wezterm `portable-pty`, ~0.9.x) behind `bitty-pty`; do not expose its types | MIT — compatible | Cross-platform Unix/ConPTY handling is domain infrastructure where upstream reuse beats reimplementation, but process lifecycle, backpressure, and security limits are Bitty-owned invariants, hence wrapper not raw adoption. Fallback if unmaintained: extract to owned fork under rule 3. | -| Windowing/input: `winit`, `crossterm` | **Adopt `winit`** (~0.30.x) inside `bitty-platform`; **do not adopt `crossterm`** as a runtime input path | Apache-2.0 — both compatible | `winit` is the maintained cross-platform window/event-loop baseline matching GPU rendering. `crossterm`'s alternate-screen model conflicts with owning a full renderer and terminal emulation; it may be used in dev tooling/tests only, never in shipped binaries. | -| Rendering/fonts: `wgpu` vs `skia-safe` vs `crossfont` | **Adopt `wgpu`** (~25.x line) in `bitty-render`; **wrap `crossfont`** for rasterization behind the glyph cache; **reject `skia-safe`** | wgpu Apache-2.0/MIT dual; skia-safe MIT but binds Skia (BSD-style with ICU components); crossfont Apache-2.0/MIT — all license-compatible; rejection is architectural | `wgpu` gives Vulkan/Metal/DX12/GL abstraction without a C++ monolith; Skia adds a large C++ supply chain and text-stack opinions Bitty does not need. `crossfont` stays wrapped because font discovery/rasterization policy (fallback, shaping hooks) is Core presentation semantics. Shaping (HarfBuzz binding) is deferred to the text RFC and enters only behind the same wrapper. | -| Lua: `mlua` vs `piccolo` | **Wrap `mlua`** (LuaJIT disabled; stock Lua 5.4 backend initially) inside `bitty-plugin-host`; **track `piccolo`** (~0.3.x) as a watch-list candidate | mlua MIT — compatible; piccolo MIT — compatible | Config and plugin VMs need mature bindings plus sandboxing primitives now; `piccolo`'s pure-Rust stackless VM is attractive for memory accounting/gc-arena isolation but still experimental, so it cannot be the P0 runtime. Re-evaluate piccolo at the plugin-isolation RFC (OQ-014); migration cost is contained because Lua enters only behind the host wrapper. Refined 2026-09-20: the plugin-VM successor path is now Phodopus, a sandbox-first fork of `piccolo`, per [ADR 0012](ADR-0012-phodopus-runtime.md); the accepted `mlua` wrap decision above is unchanged. | +| Candidate | Decision | License check | Rationale | +| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| VT parsing: `vte` vs `alacritty_terminal` vs `wezterm-term` | **Adopt `vte`** (alacritty/vte, ~0.15.x) inside `bitty-vt` behind the crate's own API; reject `alacritty_terminal` and `wezterm-term` wholesale | Apache-2.0 — compatible | Terminal state machines are Core semantics (strategy table: own directly). `vte` provides only a state-machine table + `Perform` trait, which maps exactly onto the parser→`TerminalAction` split in the Architecture Overview. `alacritty_terminal` and `wezterm-term` bundle grid/state/replay opinions that would contaminate Terminal Truth ownership and are hard to partially adopt. If `vte` proves insufficient, escalate to a narrow synchronizable fork of its tables only. | +| PTY: `portable-pty` | **Wrap** (wezterm/wezterm `portable-pty`, ~0.9.x) behind `bitty-pty`; do not expose its types | MIT — compatible | Cross-platform Unix/ConPTY handling is domain infrastructure where upstream reuse beats reimplementation, but process lifecycle, backpressure, and security limits are Bitty-owned invariants, hence wrapper not raw adoption. Fallback if unmaintained: extract to owned fork under rule 3. | +| Windowing/input: `winit`, `crossterm` | **Adopt `winit`** (~0.30.x) inside `bitty-platform`; **do not adopt `crossterm`** as a runtime input path | Apache-2.0 — both compatible | `winit` is the maintained cross-platform window/event-loop baseline matching GPU rendering. `crossterm`'s alternate-screen model conflicts with owning a full renderer and terminal emulation; it may be used in dev tooling/tests only, never in shipped binaries. | +| Rendering/fonts: `wgpu` vs `skia-safe` vs `crossfont` vs `harfrust` | **Adopt `wgpu`** (~26.x line) in `bitty-render`; **wrap `crossfont`** for default rasterization behind the glyph cache; **wrap `harfrust` + `swash` + `fontdb`** for complex text shaping and ligatures; **reject `skia-safe`** | wgpu Apache-2.0/MIT dual; skia-safe MIT but binds Skia; crossfont Apache-2.0/MIT; harfrust Apache-2.0/MIT; swash Apache-2.0/MIT; fontdb MIT — all license-compatible; rejection is architectural | `wgpu` gives Vulkan/Metal/DX12/GL abstraction without a C++ monolith; Skia adds a large C++ supply chain and text-stack opinions Bitty does not need. `crossfont` stays wrapped as the production default rasterizer. Pure-Rust HarfBuzz text shaping stack (`harfrust` 0.14 + `swash` 0.2 + `fontdb` 0.24) is adopted behind `bitty-render::shaped` under Issue [#1666](https://github.com/bitty-terminal/bitty/issues/1666) / CTX-0952, closing OQ-073 per the accepted [Ligature Decision](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/ligature-decision.md); `fontdb 0.24` (#1692, CTX-0993) vendors its query-time parser and drops external `ttf-parser`. | +| Lua: `mlua` vs `piccolo` | **Wrap `mlua`** (LuaJIT disabled; stock Lua 5.4 backend initially) inside `bitty-plugin-host`; **track `piccolo`** (~0.3.x) as a watch-list candidate | mlua MIT — compatible; piccolo MIT — compatible | Config and plugin VMs need mature bindings plus sandboxing primitives now; `piccolo`'s pure-Rust stackless VM is attractive for memory accounting/gc-arena isolation but still experimental, so it cannot be the P0 runtime. Re-evaluate piccolo at the plugin-isolation RFC (OQ-014); migration cost is contained because Lua enters only behind the host wrapper. Refined 2026-09-20: the plugin-VM successor path is now Phodopus, a sandbox-first fork of `piccolo`, per [ADR 0012](ADR-0012-phodopus-runtime.md); the accepted `mlua` wrap decision above is unchanged. | All versions above were verified against crates.io/GitHub at authoring time; the implementing task re-verifies and pins exact versions. diff --git a/docs/decisions/open-questions.md b/docs/decisions/open-questions.md index 96f5f20..9ce85f8 100644 --- a/docs/decisions/open-questions.md +++ b/docs/decisions/open-questions.md @@ -97,7 +97,7 @@ other evidence. Update the topic document and the | OQ-045 | What is the focus/idle outline-width contract - defaults, `0..=16` bounds, per-View override resolution, DPI scaling, safe-mode values, and the non-color cue it supplies to AC-2? | [Appearance Configuration RFC](rfcs/RFC-0001-appearance-configuration.md) | Acceptance decision (ADR, RFC revision, or specification update) | Accepted: [RFC-0001](rfcs/RFC-0001-appearance-configuration.md) (closed OQ-045 on 2026-09-12, docs CTX-0163; `decoration.border_width` / `_focused` / `_idle` logical px `0..=16`, inherit order border -> base -> pair, live reload whole-reload fail-closed, safe `1`/`1` with `#FFFFFF`/`#808080`, DPI scaling, per-field per-View override, `border_width_focused >= border_width_idle + 1` supplies the AC-2 non-color cue; no implementation claim) | | OQ-046 | Is a theme preset's dark/light category a selectable or queryable configuration surface (for example a `category` key or selector), or is it non-selectable documentation metadata only? | [Theme presets](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/configuration/themes.md) | Appearance/catalog contract update (RFC revision or specification) | Open: the shipped catalog records dark/light as documentation-only `ThemeCategory` metadata; `bitty` `CTX-0350` keeps selection by name; no selectable or queryable category key is accepted, no implementation claim | | OQ-047 | Are user-authored or third-party theme files supported, and if so what is the schema, load path, and trust model that keeps an unknown theme from becoming implicit code or path access? | [Theme presets](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/configuration/themes.md); [Lua and XDG](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/configuration/lua-and-xdg.md) | Appearance/catalog contract update (RFC revision or specification) | Open: custom and third-party themes are unsupported today; the reserved XDG `themes/` directory is inert and no theme-file schema or path-trust rule exists; the shipped 30-preset catalog is built-in only, no implementation claim for user themes | -| OQ-048 | Is automatic light/dark switching in scope (following OS appearance or a schedule), and which key or mechanism owns it and its reload class? | [Theme presets](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/configuration/themes.md) | Appearance/catalog contract update (RFC revision or specification) | Open: `appearance.theme` is a single name/alias scalar (reload class `Live` in the config layer) and no auto-switch mechanism exists; the catalog documents this as an open question rather than deciding a key | +| OQ-048 | Is automatic light/dark switching in scope (following OS appearance or a schedule), and which key or mechanism owns it and its reload class? | [Theme presets](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/configuration/themes.md) | Appearance/catalog contract update (RFC revision or specification) | Partially resolved (shipped in `bitty` CTX-0951, PR #1687 under Issue [#1669](https://github.com/bitty-terminal/bitty/issues/1669)): dual `light:,dark:` selection on `appearance.theme` and `theme` alias switches dynamically on OS appearance change events (winit `ThemeChanged`); remainder open: schedule-based switching and cold-path native OS appearance query | | OQ-049 | May a plugin supply a per-panel background image (or other image-backed appearance) for content it owns under a capability, and if so what capability, path policy, and eviction guarantee prevent it from escaping its own `View`s? | [Appearance Configuration RFC](rfcs/RFC-0001-appearance-configuration.md); [UI Extensibility Architecture](https://github.com/bitty-terminal/bitty-plugins-docs/blob/main/architecture/ui-extensibility-architecture.md) | Plugin-supplied appearance contract (ADR, RFC revision, or specification update) | Open: narrowed out of the accepted OQ-042 contract; the Core-owned user-configuration path is accepted, but the plugin image path stays denied and is not granted; must reuse `platform.image-file` and the accepted image bounds; no implementation claim | | OQ-050 | What is the stable scrollback-line identity for semantic command-block anchors, and where does per-view fold state live and persist across restarts? | [UI and Compositor Gap Analysis](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/ui-compositor-gap-analysis.md); [Semantic Terminal RFC](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/semantic-terminal-rfc.md) | Acceptance decision (ADR, RFC revision, or specification update) | Open (deferred per owner ruling 2026-09-23 adopting the packet recommendation): stable scrollback-line identity deferred; ordinal-anchored zones (`ordinal`/`kind`/`exit_code`) stay the M1 contract; row anchoring remains future work in the Semantic Terminal RFC OQ-S1/S2; bitty#984 moves to implementation; no implementation claim | | OQ-051 | Do non-terminal panels get a compositor sub-surface or Scene path instead of the per-leaf character-grid snapshot, and who owns it relative to Rich Presentation and the Panel Runtime? | [UI and Compositor Gap Analysis](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/ui-compositor-gap-analysis.md); [Rich Presentation RFC](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/rich-presentation-rfc.md) | Acceptance decision (ADR, RFC revision, or specification update) | Accepted (owner ruling 2026-09-23 adopting packet #2 recommendation): Scene-consumption contract owned by the Panel Runtime (Scene path consumed by the render pipeline); bitty#985 and #990 implement against the placed contract; implementation claim only on merge; the bounded `SceneNode` model stays unconsumed; bitty#985 and #990 implement against a placed contract once it lands; no implementation claim | @@ -116,7 +116,7 @@ other evidence. Update the topic document and the | OQ-069 | Are role, model, capability, tool, and context policy orthogonal in an agent composition, and what model-registry and within-agent model-routing contract follows? | [AI Architecture](https://github.com/bitty-terminal/bitty-ai-docs/blob/main/architecture/ai-architecture.md) | Acceptance decision (ADR, RFC revision, or specification update) | Open: candidate `Agent = Identity + Role + Policy + Capabilities + Model Routing + Memory + Workspace + Tools + Lifecycle` composition and per-phase routing recorded; routing is policy data and never grants capability; no model registry or routing mechanism exists; no implementation claim | | OQ-070 | What is the agent growth pipeline (observation, memory, recipe, skill, policy/profile proposal), and which approval, review, versioning, and storage rules keep growth from granting new authority? | [AI Architecture](https://github.com/bitty-terminal/bitty-ai-docs/blob/main/architecture/ai-architecture.md) | Acceptance decision (ADR, RFC revision, or specification update) | Open: candidate GR-1..GR-4 rules recorded (proposal instead of mutation, no capability gain through learning, reviewable artifacts, composition with the context planes); whether learned skills persist as project data or session state is undecided; no growth mechanism exists; no implementation claim | | OQ-071 | What is the tool-call batching contract (which independent calls share one assistant turn, how concurrent execution preserves call order, per-provider and per-API-mode parallel-tool-call support, interactive-tool serialization, and composition with the `TB-6` per-turn cap)? | [AI Architecture](https://github.com/bitty-terminal/bitty-ai-docs/blob/main/architecture/ai-architecture.md) | Acceptance decision (ADR, RFC revision, or specification update) | Open: candidate batching direction and round-trip cost model recorded as BTR-1..BTR-5; no batching policy, parallel executor, or provider-capability mapping exists; the `TB-6` draft `8`-call bound remains unchanged and whether it is the right batch bound is undecided; the single-harness Hermes observation is not a benchmark; no implementation claim | -| OQ-073 | Are ligatures adopted in Bitty, and if adopted through which shaping path (font feature tags, fallback interaction, bounds), or recorded as an explicit refusal like the Sixel decision? | [Terminal Feature Gap Analysis](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/terminal-feature-gap-analysis.md); [Text and Rendering RFC](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/text-rendering-rfc.md) | Acceptance decision (ADR, RFC revision, or specification update) | Open: no `ligature` handling exists under `bitty` `crates/` at `b377820`; the CTX-0251 register records that a refusal must be a recorded Bitty decision rather than inferred from absence; no implementation claim | +| OQ-073 | Are ligatures adopted in Bitty, and if adopted through which shaping path (font feature tags, fallback interaction, bounds), or recorded as an explicit refusal like the Sixel decision? | [Terminal Feature Gap Analysis](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/terminal-feature-gap-analysis.md); [Text and Rendering RFC](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/text-rendering-rfc.md) | Acceptance decision (ADR, RFC revision, or specification update) | Accepted (shipped in `bitty` Issue [#1666](https://github.com/bitty-terminal/bitty/issues/1666), CTX-0952, PRs [#1685](https://github.com/bitty-terminal/bitty/pull/1685), [#1690](https://github.com/bitty-terminal/bitty/pull/1690), [#1706](https://github.com/bitty-terminal/bitty/pull/1706)): HarfBuzz text shaping stack adopted using pure-Rust `harfrust` + `swash` + `fontdb 0.24`; decision recorded in accepted [Ligature Decision](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/ligature-decision.md); supports programming ligatures, multi-cell glyph atlas rendering, `font.features`, and `font.disable_ligatures` policy (`always`, `never`, `cursor`) | | OQ-074 | What is the scrollback search UX contract (Core overlay versus plugin-owned surface, keybinding namespace, case/regex scope, and interaction with selection persistence) given the bounded headless search that already exists? | [Terminal Feature Gap Analysis](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/terminal-feature-gap-analysis.md); [Semantic Terminal RFC](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/semantic-terminal-rfc.md) | Acceptance decision (ADR, RFC revision, or specification update) | Open: bounded search exists at state/UI/runtime layers (`crates/bitty-term-state/src/search.rs`, `crates/bitty-ui/src/search.rs`, `crates/bitty-runtime/src/runtime/search.rs`) with headless tests, but no `ChromeAction` or `ctl` trigger reaches it; no implementation claim | | OQ-075 | What is the keyboard-selection (vi/copy mode) contract: ownership, keymap namespace, word/line/block semantics over the existing `Selection` model, clipboard interaction, and mouse-mode precedence? | [Terminal Feature Gap Analysis](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/terminal-feature-gap-analysis.md); [Input and Pointer Contract](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/input-pointer-rfc.md) | Acceptance decision (ADR, RFC revision, or specification update) | Open: `SelectionKind` `Word`/`Line`/`Block` exist in `crates/bitty-ui/src/selection.rs` but the runtime constructs only `SelectionKind::Simple`; no keyboard-selection action or module exists; the platform `MouseEvent` carries no click count; no implementation claim | | OQ-076 | What is the user-visible bell and desktop-notification policy (audible/visual bell, OSC 777 or Kitty notification protocol support, capability gating, and RC-8 rate limits), and how does it compose with plugin notifications? | [Terminal Feature Gap Analysis](https://github.com/bitty-terminal/bitty-terminal-docs/blob/main/specifications/terminal-feature-gap-analysis.md); [Isolation Resource RFC](https://github.com/bitty-terminal/bitty-plugins-docs/blob/main/runtime/isolation-resource-rfc.md) | Acceptance decision (ADR, RFC revision, or specification update) | Open: BEL becomes `ColdEvent::Bell` with `terminal.bell` (`off`/`visual`/`audible`/`both`, default `visual`) and the plugin notification queue is bounded; Implemented-only parsers for OSC 777, OSC 99 (Kitty, `bitty#1763` via `#1773` with RC-8 plus bridge cap) and the `bitty-platform-services` bridge API (`0.0.1`, fail-closed stubs) exist, but the acceptance decision is open; [ADR 0016](adrs/ADR-0016-execution-graphics-accessibility-storage-platform-boundaries.md) accepts the platform-service extraction direction (Core retains the permission gate, validated URL arguments, and notification redaction and rate bounds) and parks the notification, URL, and blur contract to `W-136` (`bitty-terminal-docs`); the question remains Open; no implementation claim |