# Extension Decisions Extension contract, Lua runtime, grain, contribution points. --- ### D-015: Extension grain — container-level, multi-contribution - **Date:** 2026-04-21 - **Decision:** An extension is a shipping unit that contributes one or more named contributions (panel, command, theme, keybinding, language, layout, provider, view). Grain is container-sized — a single `builtin.git` extension contributes panel + commands + keybindings + status-bar items; we do not ship one extension per contribution. - **Rationale:** Finer grain (one extension per contribution) multiplies manifest files with no win and fragments ownership. Coarser grain (one mega-extension per domain) hides which parts a user might reasonably disable. - **Cost:** Extension authors make a taste call about grouping; disagreements go to review. - **Raised by:** 2026-04-21 planning. ### D-016: Built-ins in Dart, third-party in sandboxed Lua - **Date:** 2026-04-21 - **Decision:** Bundled extensions (every `app/lib/builtin/`) are Dart — they link into the app binary. Third-party extensions (Tier 6) run in sandboxed Lua via the `ptyc`-peer Lua runtime (see [D-019](#d-019-lua-runtime-as-ptyc-peer-supporter-tool)). The contribution contract is language-agnostic — same contribution shapes, same manifest schema. - **Rationale:** Dart built-ins get full SDK power (custom painters, isolates, FFI); third-party Lua gets a narrow capability API, no arbitrary syscalls, no deps on pub.dev. VS Code's Node-runs-with-full-power model is a supply-chain nightmare we're explicitly rejecting. - **Cost:** Two implementation paths for the same contract; we pay in API design to keep them equivalent at the seams. - **Raised by:** 2026-04-21 planning. ### D-017: Panels are extension-shaped from day one - **Date:** 2026-04-21 - **Decision:** Every bundled panel (file tree, git, problems, pql query, terminal, etc.) is a contribution on the extension contract, not a hardcoded widget tree in the panel manager. First party contributes via Dart; third party contributes via Lua; same contract. - **Rationale:** Forces the contract to be real on day one. The alternative ("extensions can contribute panels *later*") always becomes "the contract doesn't quite fit our bundled panels, so built-ins get a shortcut" — and the shortcut becomes permanent. - **Cost:** Every panel goes through the manifest/registration path even when it's trivial. Price paid once. - **Raised by:** 2026-04-21 planning. ### D-018: YAML for themes + manifests; JSON for i18n catalogs - **Date:** 2026-04-21 - **Decision:** Themes and extension manifests are YAML; i18n catalogues are JSON (fframe parity — see [D-021](accessibility.md#d-021-i18n-is-a-tier-0-contract)). - **Rationale:** YAML for human-edited config files (themes, manifests) — comments, multi-line strings, less noise. JSON for machine-written / machine-read files (i18n catalogs get generated by translation tooling eventually). Mixing is fine; each format is where it's best. - **Cost:** Two parsers in the tree. `yaml: 3.1.3` is exact-pinned. - **Raised by:** 2026-04-21 planning. ### D-019: Lua runtime as `ptyc`-peer supporter tool - **Date:** 2026-04-21 - **Decision:** Third-party extensions run Lua inside a sandboxed runtime (working name TBD; same peer-status as `ptyc` and `pql`). The runtime vendors liblua, links from Dart via `dart:ffi`, exposes a narrow capability API, and takes contributions as a declarative render-intent DSL (widget shapes, not arbitrary widget code). - **Rationale:** Lua is small, embeddable, battle-tested (Neovim, World of Warcraft, Redis). Native sandboxing at the VM level is cheap. A declarative render-intent DSL keeps "run arbitrary Flutter widgets from Lua" off the table — the runtime interprets the DSL into Dart widgets, which keeps Tier 6 supply-chain risk bounded. - **Cost:** Runtime is a separate supporter tool to build; ffi is tricky. Deferred to Tier 6; only the slot is reserved now. - **Raised by:** 2026-04-21 planning. --- *See also the existing `builtin.grammars_core` stub for tree-sitter questions ([Q-015](questions-process.md#q-015-editor-tab-full-lsp-vs-tree-sitter-only), [Q-016](questions-process.md#q-016-tree-sitter-dart-grammar-maintenance)).*