Files
clide/governance/decisions/extensions.md
T
jpmschweitzerandClaude Opus 4.8 526daed237 sweep stale DQR anchor slugs to canonical (em-dash → double-hyphen, retitled records)
Fixes 11 distinct inline anchor slugs that drifted from the generated
canonical form: em-dash titles render `--` (single-hyphen links were stale),
plus several truncated/old slugs (D-5, D-10, D-21, D-39, D-40, D-43, D-68,
Q-1, Q-32, Q-33). pql resolves cross-refs by ID so these were never "broken"
to the tooling, but they'd fail GitHub markdown anchor navigation. Verified:
every inline anchor now matches the README index; pql decisions sync reports
0 broken refs.

Does NOT touch the separate stale-path class (flat `questions-*.md` /
`rejected.md` naming from before the DQR subdir split) — surfaced for a
follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 12:33:51 +02:00

6.6 KiB

Extension Decisions

Extension contract, Lua runtime, grain, contribution points.


D-15: 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-16: Built-ins in Dart, third-party in sandboxed Lua

  • Date: 2026-04-21
  • Decision: Bundled extensions (every lib/builtin/<name>) 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-19). 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-17: 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-18: 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-21).
  • 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-19: 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.

D-46: Core frame builtins vs shipped extensions boundary

  • Date: 2026-04-22

  • Decision: The lib/builtin/ directory is reserved for core frame infrastructure — components the shell cannot function without. Everything that renders content (editor surfaces, tool panels, integrations) is a shipped extension: still Dart, still bundled in the binary, but architecturally an extension that registers through the contribution contract and could in principle be disabled by the user.

    Core frame builtins (cannot be disabled; the frame breaks without them): default-layout, welcome, ipc-status, theme-picker, terminal, files, grammars-core, settings-ui, extensions-ui, keybindings-ui.

    Split components (core process in the frame, UI surfaces as shipped extensions): git — the daemon-side git process (branch, status, stage, commit, diff computation) is frame infrastructure that the status bar, file tree dirty markers, and other extensions depend on. The git panel, conflict UI, and diff tab are shipped extensions that consume it.

    Shipped extensions (bundled but removable; contribute content, not infrastructure): editor, claude, claude-control, markdown, diff, git-ui, pql, canvas, graph, decisions, tickets, todos, problems.

  • Rationale: The previous session bled several content extensions (jira, todos, decisions, tickets, canvas, graph) into builtin/ as stubs, treating "shipped with the app" as "part of the frame." This conflates two concerns: the frame's structural integrity and the bundled feature set. A user who disables the canvas extension should get a working IDE with no canvas panel; a user who disables the layout extension gets a broken window. The boundary is: can the frame render and function without it? If yes, it's a shipped extension, not a frame builtin.

  • Cost: Shipped extensions need a separate registration path (e.g. lib/extensions/ or equivalent) distinct from lib/builtin/. The extension contract must support "bundled Dart extension" as a first-class category alongside "builtin" and "third-party Lua." Migration is incremental — move one at a time, each behind a working build.

  • Supersedes: Removes builtin.jira (already deleted; should never have been a builtin — Jira integration is a third-party extension, not a shipped one).

  • Raised by: 2026-04-22 session review.


See also the existing builtin.grammars_core stub for tree-sitter questions (Q-15, Q-16).