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>
This commit is contained in:
2026-06-06 12:33:51 +02:00
co-authored by Claude Opus 4.8
parent b7f3731394
commit 526daed237
8 changed files with 25 additions and 25 deletions
+8 -8
View File
@@ -73,7 +73,7 @@ Core, rendering, IPC, kernel, panel manager.
### D-1: CLI-first, not MCP
- **Date:** 2026-04-20 (was ADR 0001; ported from the claudian lineage)
- **Amendment (2026-05-15):** D-1's intent — the CLI is the *primary* agent-facing surface, with the same contract as pql — stands. An additional `/ide`-compatible MCP surface is added per [D-68](#d-68-dual-integration-surface-bash-cli-primary-mcp-secondary); both wrap the same in-process dispatcher. The escape-hatch line in this record's Cost ("nothing here precludes adding [MCP] later that shells out to the same CLI") is realised — the MCP server does not bypass the CLI's surface, it offers a second transport to it.
- **Amendment (2026-05-15):** D-1's intent — the CLI is the *primary* agent-facing surface, with the same contract as pql — stands. An additional `/ide`-compatible MCP surface is added per [D-68](#d-68-dual-integration-surface--bash-cli-primary-mcp-secondary); both wrap the same in-process dispatcher. The escape-hatch line in this record's Cost ("nothing here precludes adding [MCP] later that shells out to the same CLI") is realised — the MCP server does not bypass the CLI's surface, it offers a second transport to it.
- **Decision:** Claude talks to clide exclusively via Bash (`clide …`). No MCP server. No protocol layer in Claude's face. The CLI uses the same exit-code + stderr-JSON contract as pql.
- **Context:** The two mainstream options for the agent-facing surface were an MCP server or a plain Bash CLI matching pql's contract.
- **Rationale:** Same mental model as pql for the agent — one tool-use pattern covers both. No MCP runtime to host, authenticate, or keep in sync with client versions. User/Claude parity is easier to enforce: every CLI subcommand must have a UI affordance in the Flutter app and vice versa ([D-6](#d-6-cli-and-event-surface-contract)). Claude Code's `Bash(clide *)` allow rule is the only configuration clide needs on the agent side.
@@ -86,7 +86,7 @@ Core, rendering, IPC, kernel, panel manager.
- **Context:** [`pql`](https://github.com/postmeridiem/pql) is a pre-existing Go CLI that indexes a markdown-bearing directory tree into SQLite and exposes frontmatter, wikilinks, tags, headings, and bases through a query surface. Clide needs those capabilities for its Query panel, canvas drivers, graph view, and any feature that needs to know structure.
- **Rationale:** One source of truth for markdown semantics. Any new query capability the UI wants goes through a pql upstream PR, not a local workaround. Users never have to learn pql's config file to get consistent behaviour — clide manages it. The arrow clide → pql is never inverted: pql stays ignorant of its wrapper.
- **Cost:** Clide's `lib/src/pql/` package is deliberately thin. pql is also the **only** query engine — Obsidian-style inline "bases" are explicitly not supported; queries live at the repo level. In repos without clide, pql works standalone unaffected.
- **Raised by:** Ported from the claudian lineage. Load-bearing for [D-39](process.md#d-39-planning-tooling-lives-in-pql).
- **Raised by:** Ported from the claudian lineage. Load-bearing for [D-39](process.md#d-39-planning-tooling-lives-in-pql-not-clide).
### D-4: Ignore file strategy
- **Date:** 2026-04-20 (was ADR 0004; ported from the claudian lineage)
@@ -112,7 +112,7 @@ Core, rendering, IPC, kernel, panel manager.
- **Decision:** The CLI is organised into **subsystems**. Each subsystem owns a noun, a set of verbs, and a set of events. The set is closed at any point in time (documented); growth is additive (new verbs, new events — never renaming existing ones without a version bump). Initial subsystems (by tier): `pane`, `tab`, `open`, `editor`, `panel`, `tree`, `git`, `pql`, `canvas`, `graph`, `theme`, `settings`, `project`. Two umbrella entry points sit outside any subsystem: `clide tail --events [--filter <subsystem>[:<id>]]` and `clide status`. Command shape: `clide <subsystem> <verb> [<positional>...] [--flag ...] [-- argv...]`. Exit codes parity with pql (`0/1/2/3/4` + `64-78` sysexits reserved); diagnostic JSON on **stderr** on non-zero exit; stdout stays machine-parseable on success. Events are JSON objects, one per line, with `v`, `ts`, `type` (`<subsystem>.<verb_past|noun_changed>`), `subsystem`, `id`, and `payload`; binary payloads base64. Every state-changing command emits at least one event; read-only commands emit nothing. Replay buffer per subsystem (default depth 16) so late subscribers still see recent effects. Parity rule: every UI affordance has a matching CLI verb (or a follow-up task naming the verb); every CLI verb surfaces in the UI (or documents why it's Claude-only).
- **Context:** [D-1](#d-1-cli-first-not-mcp) established that Claude drives clide via a Bash CLI. That decided the *channel* — it did not define the *surface*. CLAUDE.md stated the rule colloquially ("every CLI subcommand has a UI affordance … if you add one side without the other, the feature is incomplete"); this record restates it as an implementable contract that satisfies user/Claude parity, daemon-as-authoritative-state, and pql-style ergonomics at once.
- **Rationale:** Surface is enumerable — adding a subsystem means adding a row and specifying verbs + events. Wire schema is versioned (`v: 1` starting point; compatibility breaks bump the major and land alongside a `pubspec.yaml` `schema_version:` bump — see [Q-5](questions-architecture.md#q-5-ipc-wire-format-stability)). Events are the only UI→app state channel; the Flutter app does not poll. Extensions inherit this — a Dart extension publishes a subsystem; the same registration pipeline exposes it to Claude via the CLI.
- **Cost:** Replay-buffer memory per subsystem (cheap — most emit seldom). Back-pressure on firehose streams ([Q-2](questions-architecture.md#q-2-back-pressure-on-event-streams)), authorisation granularity ([Q-1](questions-architecture.md#q-1-authorisation-granularity)), and event persistence ([Q-3](questions-architecture.md#q-3-event-persistence-audit-undo)) are all deferred until Tier 1 is in real use.
- **Cost:** Replay-buffer memory per subsystem (cheap — most emit seldom). Back-pressure on firehose streams ([Q-2](questions-architecture.md#q-2-back-pressure-on-event-streams)), authorisation granularity ([Q-1](questions-architecture.md#q-1-authorisation-granularity-on-the-ipc-socket)), and event persistence ([Q-3](questions-architecture.md#q-3-event-persistence-audit-undo)) are all deferred until Tier 1 is in real use.
- **Raised by:** 2026-04-20 planning.
### D-43: Design handoff — adopt token palettes, reject Material wrapper
@@ -128,7 +128,7 @@ Core, rendering, IPC, kernel, panel manager.
- **Decision:** Ship four bundled themes replacing the single summer-night preset. `clide` (cool near-black + periwinkle, default), `midnight` (VS Code-adjacent muted dark), `paper` (drafting-sheet light), `terminal` (near-black + amber). All share the same semantic token names. Source palettes in `docs/claude-design/themes/`; runtime YAML under `lib/kernel/src/theme/themes/`.
- **Rationale:** Summer-night was a placeholder carried from the legacy TUI. The design system delivers a coherent set of four that covers dark, muted-dark, light, and monochrome workflows.
- **Cost:** Summer-night users lose their theme (acceptable — it was dev-only). Four YAML files to maintain.
- **Cross-reference:** [D-43](#d-43-design-handoff-adopt-token-palettes-reject-material-wrapper), [D-22](accessibility.md#d-22-wcag-aa-contrast-gate-on-bundled-themes).
- **Cross-reference:** [D-43](#d-43-design-handoff--adopt-token-palettes-reject-material-wrapper), [D-22](accessibility.md#d-22-wcag-aa-contrast-gate-on-bundled-themes).
- **Raised by:** 2026-04-22 design handoff review.
### D-45: Syntax highlighting tokens in the theme pipeline
@@ -250,11 +250,11 @@ Core, rendering, IPC, kernel, panel manager.
### D-68: Dual integration surface — Bash CLI primary, MCP secondary
- **Date:** 2026-05-15
- **Amendment (2026-05-19):** Both surfaces implemented in T-99. CLI lands as `IpcServer` over the unix socket (T-124, per D-70/71/72) with the C client at `native/clide-cli/clide.c` (T-126); the argv grammar lives in `lib/src/cli/argv_to_request.dart` (T-125). MCP lands as `McpServer` over HTTP+SSE (T-130, per D-73) — the transport choice closed Q-33. The two `/ide` minimum tools ship as stubs; real implementations follow as Q-32 resolves the broader tool-surface question.
- **Decision:** clide exposes two integration surfaces over the same in-process `DaemonDispatcher`. **(1) Bash CLI over Unix socket — primary.** Per [D-1](#d-1-cli-first-not-mcp) and [D-56](#d-56-dissolve-daemon-process-flutter-app-hosts-ipc-server), a thin C client (`clide …`) connects to a per-user Unix socket served in-process by the Flutter app, exchanges JSON-lines, and exits. This is the surface Claude-Code-in-a-pane uses; it is also the surface for human shell use, scripts, and external editor integrations. Full action surface — `pane.*`, `files.*`, `editor.*`, `git.*`, `pql.*`, …. **(2) `/ide`-compatible MCP server — secondary.** clide additionally serves an MCP endpoint compatible with Claude Code's `/ide` integration (the same protocol VS Code and JetBrains plugins serve). Minimum tools: `mcp__ide__getDiagnostics`, `mcp__ide__executeCode`. Optional `mcp__clide__*` namespace exposing high-leverage clide tools is deferred to [Q-32](../questions/architecture.md#q-32-mcp-tool-surface-minimum-slash-ide-or-extended-clide-tools). Transport closed by [D-73](#d-73-mcp-transport-for-ide-is-sse-over-http) — SSE over HTTP. The MCP server wraps the *same* `DaemonDispatcher`; there is no second source of truth.
- **Decision:** clide exposes two integration surfaces over the same in-process `DaemonDispatcher`. **(1) Bash CLI over Unix socket — primary.** Per [D-1](#d-1-cli-first-not-mcp) and [D-56](#d-56-dissolve-daemon-process-flutter-app-hosts-ipc-server), a thin C client (`clide …`) connects to a per-user Unix socket served in-process by the Flutter app, exchanges JSON-lines, and exits. This is the surface Claude-Code-in-a-pane uses; it is also the surface for human shell use, scripts, and external editor integrations. Full action surface — `pane.*`, `files.*`, `editor.*`, `git.*`, `pql.*`, …. **(2) `/ide`-compatible MCP server — secondary.** clide additionally serves an MCP endpoint compatible with Claude Code's `/ide` integration (the same protocol VS Code and JetBrains plugins serve). Minimum tools: `mcp__ide__getDiagnostics`, `mcp__ide__executeCode`. Optional `mcp__clide__*` namespace exposing high-leverage clide tools is deferred to [Q-32](../questions/architecture.md#q-32-mcp-tool-surface--minimum-slash-ide-or-extended-clide-tools). Transport closed by [D-73](#d-73-mcp-transport-for-ide-is-sse-over-http) — SSE over HTTP. The MCP server wraps the *same* `DaemonDispatcher`; there is no second source of truth.
- **Context:** [D-1](#d-1-cli-first-not-mcp) chose CLI-first over MCP-only because MCP alone doesn't cover the action surface clide needs — Claude Code's `/ide` MCP exposes only two narrow tools (`getDiagnostics`, `executeCode`), enough for Claude to read diagnostics and run Jupyter cells but not enough to *drive* an IDE. The CLI surface gives full reach. But for users who run Claude Code *outside* clide and connect via `/ide`, MCP is the only path Claude Code knows; not serving it means clide is invisible to that workflow. The two surfaces are complementary, not alternatives. Reinforced by the [2026-05-14 consultant review](../../consultants.md): the architect flagged the absent socket server as the most critical drift; user confirmed the socket server (D-56 path a) plus an MCP companion.
- **Rationale:** Both surfaces wrap the same dispatcher, so neither becomes a second source of truth. CLI remains the contract user/Claude parity ([D-6](#d-6-cli-and-event-surface-contract)) is enforced against. MCP is added because the `/ide` ecosystem is real and growing — VS Code, JetBrains, Cursor, Windsurf all serve compatible MCP — and clide should be a peer there. The implementation cost is a protocol adapter + tool definitions, not duplicate business logic.
- **Cost:** Two transports to maintain. Mitigated by both wrapping the same dispatcher: the MCP adapter is the only thing that has to track `/ide` protocol evolution. If `mcp__clide__*` tools are added (pending Q-32), surface bloat is the obvious risk — every CLI verb invites an MCP twin; resist by default, justify on user need.
- **Cross-reference:** [D-1](#d-1-cli-first-not-mcp) (amended — see amendment line there), [D-6](#d-6-cli-and-event-surface-contract), [D-56](#d-56-dissolve-daemon-process-flutter-app-hosts-ipc-server), [Q-32](../questions/architecture.md#q-32-mcp-tool-surface-minimum-slash-ide-or-extended-clide-tools), [Q-33](../questions/architecture.md#q-33-mcp-transport-sse-websocket-stdio-or-all).
- **Cross-reference:** [D-1](#d-1-cli-first-not-mcp) (amended — see amendment line there), [D-6](#d-6-cli-and-event-surface-contract), [D-56](#d-56-dissolve-daemon-process-flutter-app-hosts-ipc-server), [Q-32](../questions/architecture.md#q-32-mcp-tool-surface--minimum-slash-ide-or-extended-clide-tools), [Q-33](../questions/architecture.md#q-33-mcp-transport--sse-websocket-stdio-or-all).
- **Raised by:** 2026-05-15 — consultant review (`consultants.md`) flagged the absent socket server (D-56 unimplemented) as the highest architectural drift; user chose option (a) "implement the server" and asked for MCP coverage alongside.
### D-70: IPC socket path is per-workspace, deterministic
@@ -267,10 +267,10 @@ Core, rendering, IPC, kernel, panel manager.
### D-71: IPC socket access gated by chmod 0600 on socket + parent
- **Date:** 2026-05-18
- **Decision:** The IPC socket file and its parent directory ([D-70](#d-70-ipc-socket-path-is-per-workspace-deterministic)) are created with permissions `0600` (owner read/write only) and `0700` respectively. No token-based auth at the IPC layer; the Unix file-permission check is the only gate. Capability-scoped auth for third-party Lua/Dart extensions is a separate concern and remains tracked by [Q-1](../questions/architecture.md#q-1-authorisation-granularity) for when extensions actually need it.
- **Decision:** The IPC socket file and its parent directory ([D-70](#d-70-ipc-socket-path-is-per-workspace-deterministic)) are created with permissions `0600` (owner read/write only) and `0700` respectively. No token-based auth at the IPC layer; the Unix file-permission check is the only gate. Capability-scoped auth for third-party Lua/Dart extensions is a separate concern and remains tracked by [Q-1](../questions/architecture.md#q-1-authorisation-granularity-on-the-ipc-socket) for when extensions actually need it.
- **Rationale:** clide's threat model on a developer workstation is "another user on the same host should not be able to drive my IDE." File perms cover this exhaustively — the kernel enforces the check on every `connect(2)`, no userspace token comparison can match that. Adding a session token on top would be belt-and-suspenders without expanding the threat model. Capability tokens become useful when extensions can publish their own dispatcher routes and we want to gate which third-party code can reach which subsystem — but that's a Tier-6 concern.
- **Cost:** Doesn't defend against same-uid attacks (a malicious process running as the user can connect). Accepted — same-uid is outside this layer's threat model; that's a sandboxing / capability concern that lives further out. Doesn't work on shared multi-user dev hosts where one socket needs to be reachable by multiple uids — clide isn't targeted at that workflow today.
- **Cross-reference:** [D-70](#d-70-ipc-socket-path-is-per-workspace-deterministic), [Q-1](../questions/architecture.md#q-1-authorisation-granularity).
- **Cross-reference:** [D-70](#d-70-ipc-socket-path-is-per-workspace-deterministic), [Q-1](../questions/architecture.md#q-1-authorisation-granularity-on-the-ipc-socket).
- **Raised by:** 2026-05-18 — T-99 design pass.
### D-72: IPC server is multi-connection with serial dispatch on the main isolate
+1 -1
View File
@@ -27,7 +27,7 @@ Extension contract, Lua runtime, grain, contribution points.
### 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](accessibility.md#d-21-i18n-is-a-tier-0-contract)).
- **Decision:** Themes and extension manifests are YAML; i18n catalogues are JSON (fframe parity — see [D-21](accessibility.md#d-21-i18n-is-a-tier-0-contract-fframe-pattern--locale-fallback-chain)).
- **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.
+4 -4
View File
@@ -134,15 +134,15 @@ ticket persistence.
### Q-32: MCP tool surface — minimum slash-ide or extended clide tools?
- **Status:** Resolved → [D-86](../decisions/architecture.md#d-86-mcp-tool-surface--full-clide-namespace-generated-from-the-co-registered-command-registry)
- **Resolved (2026-06-06):** Full `mcp__clide__*` namespace, but **generated from the co-registered command registry** ([D-74](../decisions/architecture.md#d-74-ipc-command-schema-is-co-registered-with-the-handler-validated-at-dispatch)) that already feeds the CLI + palette — so breadth costs no hand-maintained second surface, and the extensions-first model needs registry-driven surfacing anyway. Per-command MCP opt-out for poor-fit verbs.
- **Question:** [D-68](../decisions/architecture.md#d-68-dual-integration-surface-bash-cli-primary-mcp-secondary) commits clide to an `/ide`-compatible MCP server. The minimum surface is the two tools Claude Code's `/ide` integration currently expects: `mcp__ide__getDiagnostics` (lint/diagnostics for a file) and `mcp__ide__executeCode` (run code in a Jupyter kernel). Do we stop there, or also expose a `mcp__clide__*` namespace with higher-leverage tools (`open_file`, `goto_symbol`, `pql_query`, `pane_spawn`, `git_status`, …) so MCP clients other than Claude Code (Cursor, Windsurf, VS Code Copilot) can drive clide as a real backend?
- **Question:** [D-68](../decisions/architecture.md#d-68-dual-integration-surface--bash-cli-primary-mcp-secondary) commits clide to an `/ide`-compatible MCP server. The minimum surface is the two tools Claude Code's `/ide` integration currently expects: `mcp__ide__getDiagnostics` (lint/diagnostics for a file) and `mcp__ide__executeCode` (run code in a Jupyter kernel). Do we stop there, or also expose a `mcp__clide__*` namespace with higher-leverage tools (`open_file`, `goto_symbol`, `pql_query`, `pane_spawn`, `git_status`, …) so MCP clients other than Claude Code (Cursor, Windsurf, VS Code Copilot) can drive clide as a real backend?
- **Context:** The minimum surface keeps clide a good citizen in the `/ide` ecosystem and avoids duplicating the CLI in MCP form. The extended surface would let non-Claude-Code MCP clients integrate richly, but invites surface bloat (every CLI verb tempted to gain an MCP twin) and a maintenance second front. Note that for *Claude-Code-in-a-clide-pane*, the CLI surface already covers this — extended MCP tools serve external MCP clients only.
- **Source:** [D-68](../decisions/architecture.md#d-68-dual-integration-surface-bash-cli-primary-mcp-secondary).
- **Source:** [D-68](../decisions/architecture.md#d-68-dual-integration-surface--bash-cli-primary-mcp-secondary).
### Q-33: MCP transport — SSE, WebSocket, stdio, or all?
- **Status:** Resolved → [D-73](../decisions/architecture.md#d-73-mcp-transport-for-ide-is-sse-over-http)
- **Resolved (2026-05-19, drift-fixed 2026-06-06):** SSE over HTTP only. Closed by D-73 (and confirmed in D-68's amendment) at the time, but this index was never flipped from Open. Re-confirmed 2026-06-06: stdio/WebSocket not added — D-73's reasoning (the always-running GUI is *connected to*, not spawned) still holds and no external process-spawn MCP client is a concrete need yet.
- **Question:** Claude Code's `/ide` integration connects via SSE-IDE or WS-IDE (URL passed at startup). MCP also supports stdio for process-spawn clients. Which transport(s) should clide's MCP server expose — SSE only (the most common `/ide` server pattern), SSE + WS (broader compatibility), or all three including stdio?
- **Context:** Transport choice affects discovery and lifecycle. SSE/WS need a port and a published URL, which collides with the `XDG_RUNTIME_DIR` Unix-socket model used for the CLI; we'd likely publish the URL alongside the socket path (env var or `XDG_RUNTIME_DIR` discovery file). stdio is process-per-client and works for clients that prefer process-spawn over network. Decision interacts with [Q-32](#q-32-mcp-tool-surface-minimum-slash-ide-or-extended-clide-tools) — if the surface stays at the `/ide` minimum, SSE alone is sufficient.
- **Source:** [D-68](../decisions/architecture.md#d-68-dual-integration-surface-bash-cli-primary-mcp-secondary).
- **Context:** Transport choice affects discovery and lifecycle. SSE/WS need a port and a published URL, which collides with the `XDG_RUNTIME_DIR` Unix-socket model used for the CLI; we'd likely publish the URL alongside the socket path (env var or `XDG_RUNTIME_DIR` discovery file). stdio is process-per-client and works for clients that prefer process-spawn over network. Decision interacts with [Q-32](#q-32-mcp-tool-surface--minimum-slash-ide-or-extended-clide-tools) — if the surface stays at the `/ide` minimum, SSE alone is sufficient.
- **Source:** [D-68](../decisions/architecture.md#d-68-dual-integration-surface--bash-cli-primary-mcp-secondary).
---
+1 -1
View File
@@ -33,7 +33,7 @@ Tooling-domain questions currently live here too. Split into
### Q-19: (withdrawn)
- **Status:** Resolved → n/a
- **Note:** Earlier floated as "ticket markdown mirror vs SQLite" — no longer a split question. Markdown mirror is tracked in [Q-22](questions-architecture.md#q-22-ticket-persistence-strategy); SQLite is the current stopgap per [D-40](process.md#d-40-python-stopgap-under-toolsscriptsplan).
- **Note:** Earlier floated as "ticket markdown mirror vs SQLite" — no longer a split question. Markdown mirror is tracked in [Q-22](questions-architecture.md#q-22-ticket-persistence-strategy); SQLite is the current stopgap per [D-40](process.md#d-40-superseded-python-stopgap-under-toolsscriptsplan).
### Q-20: Kernel DB service — namespaced SQL access?
- **Status:** Open
+1 -1
View File
@@ -8,6 +8,6 @@ future reference.
### R-4: Flutter `intl` + ARB codegen for i18n
- **Rejected:** 2026-04-21
- **Reason:** ARB codegen is inflexible for plugin-contributed catalogs — every catalogue needs a codegen pass, every extension ships with pre-generated Dart, and runtime merging is fighting the tool. The fframe text-driven pattern reads JSON at runtime with no codegen, which fits extension-shipped catalogs cleanly.
- **Cross-reference:** [D-21](../decisions/accessibility.md#d-21-i18n-is-a-tier-0-contract)
- **Cross-reference:** [D-21](../decisions/accessibility.md#d-21-i18n-is-a-tier-0-contract-fframe-pattern--locale-fallback-chain)
---
+4 -4
View File
@@ -6,9 +6,9 @@ future reference.
---
### R-2: Go sidecar
- **Rejected:** 2026-04-20 (was ADR 0002; superseded by [D-5](../decisions/architecture.md#d-5-dart-core-ptyc-peer))
- **Rejected:** 2026-04-20 (was ADR 0002; superseded by [D-5](../decisions/architecture.md#d-5-dart-core-sidecar-dissolved-ptyc-as-pql-peer))
- **Reason:** The ADR picked Go on two premises — (a) the heavy work belongs in a language separate from the UI layer, and (b) pql is Go so muscle memory transfers. Both broke on reassessment. The sidecar stripped of PTY is I/O-bound glue that `dart:io` covers cleanly (unix sockets, JSON-lines framing, process tables, shell-outs). The real axis was *separate process vs shared language*, not Go vs Rust, and separate-process is what matters (session persistence needs the daemon to outlive the app), not language. PTY is the one place Dart is genuinely weak — Dart's multi-threaded VM can't safely `fork()` — and that single constraint forces a native helper regardless, independent of whether the rest of the core is Dart. Once a small native helper is accepted, the question "does *everything else* need to be in that same native language" answers itself: no. Go sidecar directory dissolved; `ptyc` (C, PTY-only, pql-peer) is the surviving native supporter tool.
- **Cross-reference:** [D-5](../decisions/architecture.md#d-5-dart-core-ptyc-peer)
- **Cross-reference:** [D-5](../decisions/architecture.md#d-5-dart-core-sidecar-dissolved-ptyc-as-pql-peer)
### R-3: `MaterialApp` root
- **Rejected:** 2026-04-21
@@ -23,11 +23,11 @@ future reference.
### R-8: Riverpod / Provider / BLoC for state
- **Rejected:** 2026-04-21
- **Reason:** Violates [D-31](../decisions/tooling.md#d-31-prefer-zero-deps-exact-pin). `ChangeNotifier` + `ListenableBuilder` ship in the SDK, fake trivially, and cover the state model we need. The ergonomic wins of Riverpod / Provider don't clear the "new dependency" bar at clide's scale.
- **Cross-reference:** [D-10](../decisions/architecture.md#d-10-state-management-changenotifier)
- **Cross-reference:** [D-10](../decisions/architecture.md#d-10-state-management--changenotifier--listenablebuilder)
### R-12: MaterialApp wrapper from design handoff
- **Rejected:** 2026-04-22
- **Reason:** The design handoff delivers theme files as `MaterialApp`/`ThemeData` Dart classes. This is the delivery format of claude.ai/design, not a design intent. Adopting Material's widget system would contradict [D-7](../decisions/architecture.md#d-7-app-root-is-bare-widgetsapp) (bare WidgetsApp, no Material/Cupertino). We translate the palette tokens and syntax roles into our existing YAML + `SurfaceTokens` pipeline.
- **Cross-reference:** [D-43](../decisions/architecture.md#d-43-design-handoff-adopt-token-palettes-reject-material-wrapper)
- **Cross-reference:** [D-43](../decisions/architecture.md#d-43-design-handoff--adopt-token-palettes-reject-material-wrapper)
---
+5 -5
View File
@@ -12,17 +12,17 @@ future reference.
### R-9: Port planning tooling into clide
- **Rejected:** 2026-04-21
- **Reason:** Earlier in the planning session the assumption was "clide owns Dart subcommands for decisions + tickets." That breaks the day a contributor works in a terminal or in VS Code / JetBrains — they have no `clide` binary to run. Reversing: pql owns planning long-term (see [D-39](../decisions/process.md#d-39-planning-tooling-lives-in-pql)); clide consumes via shell-out.
- **Cross-reference:** [D-39](../decisions/process.md#d-39-planning-tooling-lives-in-pql)
- **Reason:** Earlier in the planning session the assumption was "clide owns Dart subcommands for decisions + tickets." That breaks the day a contributor works in a terminal or in VS Code / JetBrains — they have no `clide` binary to run. Reversing: pql owns planning long-term (see [D-39](../decisions/process.md#d-39-planning-tooling-lives-in-pql-not-clide)); clide consumes via shell-out.
- **Cross-reference:** [D-39](../decisions/process.md#d-39-planning-tooling-lives-in-pql-not-clide)
### R-10: Python-script stopgap under `tooling/db/`
- **Rejected:** 2026-04-21
- **Reason:** Location, not language. Settled-reach puts scripts at `tooling/db/` — copying that path here creates a script-pollution problem: every project using the pattern commits its own copy. The accepted Python port ([D-40](../decisions/process.md#d-40-python-stopgap-under-toolsscriptsplan)) lives at `tools/scripts/plan`, clearly signalled as dev-tooling and time-limited.
- **Cross-reference:** [D-40](../decisions/process.md#d-40-python-stopgap-under-toolsscriptsplan)
- **Reason:** Location, not language. Settled-reach puts scripts at `tooling/db/` — copying that path here creates a script-pollution problem: every project using the pattern commits its own copy. The accepted Python port ([D-40](../decisions/process.md#d-40-superseded-python-stopgap-under-toolsscriptsplan)) lives at `tools/scripts/plan`, clearly signalled as dev-tooling and time-limited.
- **Cross-reference:** [D-40](../decisions/process.md#d-40-superseded-python-stopgap-under-toolsscriptsplan)
### R-11: Permanent stopgap
- **Rejected:** 2026-04-21
- **Reason:** If the Python port under `tools/scripts/plan` outlasts pql's feature parity, delete it. The deletion commit should be one changeset: remove `tools/scripts/plan`, remove its Makefile target (`decisions-validate` rewires to `pql decisions validate`), add a `CHANGELOG.md` entry under Removed, and verify `.pql/pql.db` still opens under the new `pql` binary.
- **Cross-reference:** [D-40](../decisions/process.md#d-40-python-stopgap-under-toolsscriptsplan)
- **Cross-reference:** [D-40](../decisions/process.md#d-40-superseded-python-stopgap-under-toolsscriptsplan)
---
+1 -1
View File
@@ -8,6 +8,6 @@ future reference.
### R-5: Patrol test runner
- **Rejected:** 2026-04-21
- **Reason:** Adds a dependency (violates [D-31](../decisions/tooling.md#d-31-prefer-zero-deps-exact-pin)) for a capability we get from Playwright + Flutter's own semantics tree. Patrol's value proposition (native-gesture emulation) is less relevant on Linux desktop than on mobile.
- **Cross-reference:** [D-26](../decisions/testing.md#d-26-web-driver-raw-playwright-plus-flutter-semantics)
- **Cross-reference:** [D-26](../decisions/testing.md#d-26-web-driver--raw-playwright--flutter-semantics)
---