Adopt settled-reach's Q&D record convention. Confirmed decisions live under decisions/<domain>.md as D-NNN; open questions under questions-<domain>.md as Q-NNN; rejected alternatives in rejected.md as R-NNN. Markdown is source of truth; .pql/pql.db (added later) is a query index. Backlog captured from the Tier-0 Flutter planning sessions: bare WidgetsApp, theme pipeline, kernel admission rule, feature-first layout, a11y + i18n as Tier-0 contracts, test pyramid, kanban over Scrum, pql-owns-planning, Python stopgap sunset clause. ADR migration (D-001, D-003-D-006 confirmed, R-002 rejected) is staged for the next commit so the diff stays readable. Co-Authored-By: Claude <noreply@anthropic.com>
6.4 KiB
6.4 KiB
Architecture Decisions
Core, rendering, IPC, kernel, panel manager.
D-007: App root is bare WidgetsApp
- Date: 2026-04-21
- Decision: The Flutter app root is
WidgetsApp, notMaterialApporCupertinoApp. Clide's look is fully custom; the Material/Cupertino shells would drag in opinionated theming, default icons, and platform chrome we'd then have to fight. - Rationale: Clide is a Linux-primary desktop IDE with a custom theme pipeline and custom primitives (panels, tabs, panes, canvas). Material's implicit theming collides with D-009; Cupertino is iOS-flavoured.
WidgetsAppgives us routing, locale, focus traversal, semantics, and Directionality without aesthetic baggage. - Cost: We build and own every primitive; no
ElevatedButtonfallback. See R-003 and R-007. - Raised by: 2026-04-21 planning.
D-008: Feature-first folder layout
- Date: 2026-04-21
- Decision: Under
app/lib/, organise by feature (kernel/,extension/,widgets/,builtin/<name>/) rather than by layer (models/,views/,controllers/). Private implementation lives under each feature'ssrc/; the feature's public surface is a barrel file at the feature root (e.g.app/lib/kernel/kernel.dart). - Rationale: Features grow and get deleted as units; layer-first layouts fragment a feature across three directories and make deletions risky. Matches extensions-as-features (every extension already has its own folder).
- Cost: Imports cross features only via the barrel — enforce by review, no automated check yet.
- Raised by: 2026-04-21 planning.
D-009: Three-tier theme pipeline
- Date: 2026-04-21
- Decision: Themes resolve through three layers: (1) palette — raw named colours per theme YAML; (2) semantic — roles like
surface.background,text.primary,accent.focus; (3) surface — component-scoped tokens derived from semantic roles (button bg/fg/border hover/pressed/disabled states). - Rationale: Direct palette-to-component binding collapses under multi-theme work; VS Code's 600-token surface map is the proof. The semantic layer is where a11y contrast gates apply; the surface layer is where components bind.
- Cost: Three layers to keep coherent per theme. Contrast gate (D-022) enforces the semantic layer on every bundled theme.
- Raised by: 2026-04-21 planning.
D-010: State management — ChangeNotifier + ListenableBuilder
- Date: 2026-04-21
- Decision: Per-feature state uses
ChangeNotifierexposed through a feature facade (singleton-per-kernel); widgets subscribe viaListenableBuilder. No Riverpod, Provider, BLoC, or Redux. - Rationale: SDK-shipped, zero deps, trivial to fake in tests (hand-rolled fakes in D-025). Violates D-031 prefer-zero-deps otherwise. See R-008.
- Cost: No codegen ergonomics; manual
notifyListeners()discipline. TheListenableBuilder.listenablecontract rejects rebuilds outside the subscribed notifier — intentional. - Raised by: 2026-04-21 planning.
D-011: Panel manager is kernel; layout is data; three-column is a preset
- Date: 2026-04-21
- Decision: The kernel owns a panel manager that treats layout as declarative data (tree of splits + leaves). The default "three-column IDE" (sidebar / editor / assistant) is one preset; alternative presets (writer-focus single-column, debugger four-pane) ship as data, not code forks.
- Rationale: Hard-coded three-column layouts paint us into corners when future tiers add canvas, graph, terminal-grid. Data-driven layout also lets extensions contribute presets without patching the panel manager.
- Cost: More kernel surface up-front; pays back at Tier 5 (canvas) and Tier 6 (extension-contributed layouts).
- Raised by: 2026-04-21 planning.
D-012: Kernel admission rule — mandatory shared singletons only
- Date: 2026-04-21
- Decision: A service joins the kernel only if it is (a) mandatory for app boot and (b) a shared singleton across features. Everything else is an extension or a feature-local service.
- Rationale: Keeps the kernel auditable. Previous drafts piled "useful globals" into the kernel; result was a 40-service god-object. The admission rule forced 18 services out of 31 candidates.
- Cost: Some legitimate cross-cutting concerns (telemetry, crash reporter when they land) must pass the test; we expect a few more admissions as Tiers 3-6 land.
- Raised by: 2026-04-21 planning.
D-013: Git hardcoded in kernel project-loader
- Date: 2026-04-21
- Decision: The kernel's project loader treats "repo root" as a
gitconcept — runsgit rev-parse --show-toplevelto find workspace root, subscribes to filesystem events, and shells out togitfor status/diff/stage. No VCS abstraction layer. - Rationale: Option B (VCS abstraction) is premature generalisation — we have one VCS today, Mercurial/Fossil/Sapling users are a rounding error on the Linux desktop IDE market, and the abstraction adds a seam that has to be tested against nothing. When a second VCS shows up we refactor.
- Cost: Adding Mercurial support later costs a real refactor, not just a plugin. Acceptable.
- Raised by: 2026-04-21 planning.
D-014: Two-tier disable — kernel locked, everything else extension-shaped
- Date: 2026-04-21
- Decision: Kernel services cannot be disabled at runtime. Extensions (including every bundled built-in) can be toggled via the extension manager. This creates exactly two disable tiers: kernel (always on) and extension (toggleable).
- Rationale: A three-tier system (kernel / bundled-cannot-disable / user-can-disable) is dishonest — if a "bundled built-in" can't be disabled, it's kernel and belongs in kernel admission review. Forcing every bundled feature to pass the extension contract is also the best test we have that the contract is actually usable.
- Cost: Disabling
builtin.default_layoutby mistake produces an empty window. Mitigated by the kernel's first-boot defaults and a "reset extensions" action. - Raised by: 2026-04-21 planning.
Architectural backlog from the claudian lineage lives below; ADR migrations (D-001, D-003, D-004, D-005, D-006) follow when commit #2 runs.