docs(design): settings-UI wireframes + settings-ui implementation epic (T-302, T-444)

Close T-302 with the Frame0 wireframes for the schema-driven settings UI, and
open the implementation epic T-444 under the Tier-6 epic T-8.

Wireframes (docs/design/wireframes/settings/, JSON source + PNG):
- settings-screen — modal shell + Editor category (all field-type patterns,
  scope tags, carded sections)
- settings-search — cross-category search-active state
- settings-claude — mirrors the sidebar Claude Config panel (settings controls
  + carded config lists)
- settings-appearance — theme-picker swatch grid (live bundled-theme previews)

Design answers: full-screen MODAL overlay; rail + cross-category search IA;
per-field scope-tag model (folder/globe/circle-dashed); carded sections; the
schema-driven renderer makes per-category tabs data, not new design.

Also documents the sectioned-card preference in the ui-design skill
(references/surface.md → "Settings & grouped lists — sectioned cards").

Epic T-444 children: infra (modal shell T-445, rail T-447, field renderer
T-448, scope-tag control T-449, search T-450) + per-category (Editor=T-290
reparented, Keymap T-451, Appearance/theme-picker T-452, Activity T-453,
Terminal T-455, Extensions T-456, Claude T-457).

Also files: T-441/T-442 (UI bugs), T-446 (slash-typeahead intermittent),
T-454 (Claude remote-control not plumbed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-16 15:41:55 +02:00
co-authored by Claude Opus 4.8
parent b5146cc9ad
commit 804bba1680
12 changed files with 597 additions and 0 deletions
+49
View File
@@ -5756,3 +5756,52 @@ INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, chang
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBKP67X1Y1FEE9T5R0E5DA9C', 'status', 'in_progress', 'done', NULL, '2026-06-16 10:08:00', '2026-06-16 10:08:00', '2026-06-16 10:08:00', NULL, 'a7ee8d073cb004d8f3c53a7128cc3aef', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNQM7H8JWCP59WQVD0FW4', 'status', 'done', 'ready', NULL, '2026-06-16 10:08:46', '2026-06-16 10:08:46', '2026-06-16 10:08:46', NULL, '6589fa3057a9c2d009805d1044988f43', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNQM7H8JWCP59WQVD0FW4', 'status', 'ready', 'in_progress', NULL, '2026-06-16 10:09:07', '2026-06-16 10:09:07', '2026-06-16 10:09:07', NULL, '01cb8766df16793a9290d5ae0e0b4c25', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD07ECS3GK2V7Z2WYYPJHJYC', 'description', NULL, 'Implement the schema-driven settings UI (`builtin.settings-ui`) designed in T-302. Wireframes (JSON source + PNG): `docs/design/wireframes/settings/` — settings-screen (Editor), settings-search, settings-claude, settings-appearance.
**Form factor / IA (decided in T-302):** a centered MODAL overlay over the dimmed app (modal* / modalOverlay* tokens; close ✕ + Esc), opened by a `settings.open` command. Left category rail + a cross-category search box; right scrolling panel of CARDED sections — each logical group is a card (surface fill + 1px border, ~6px corners) with a small-caps section label + count above it. See the new `ui-design` `surface.md` → "Settings & grouped lists — sectioned cards".
**Engine, not per-screen UI:** field rows render from the schema each subsystem registers against the kernel SettingsStore — toggle / enum-select / text-number / "opens external file" affordance — each with label, help, default, reset, and a per-field SCOPE TAG (folder = project `.clide` / globe = always `~/.clide` / circle-dashed = default-unset; colour + tooltip; tap → scope menu). Edits write back to the resolved scope''s settings file. Categories are DATA; the only custom control is Appearance''s theme picker.
**Decisions / consumers:** kernel SettingsStore schema; WidgetsApp-only tokens (D-7); keymap presets (T-115 / T-64 / T-65 / T-66); editor settings (T-290 / T-29); activity fold (T-183); theming (existing builtin.theme-picker, D-44 / D-69); Claude config mirrors `lib/builtin/claude/src/meta_sidebar/config_tab.dart` (T-414 / T-183). Phosphor glyphs resolve via `byName(...)` (T-314) — no consts to add.
**Children — build infra first, then categories extrapolate:**
Infra: modal shell + `settings.open`; category rail + nav; schema field renderer (the engine); scope-tag control + scope resolution; cross-category search.
Categories (register a schema, reuse the engine): Editor (T-290), Keymap, Appearance (theme-picker control), Activity, Terminal, Extensions, Claude (mirror the sidebar Config panel).', NULL, '2026-06-16 11:13:12', '2026-06-16 11:13:12', '2026-06-16 11:13:12', NULL, 'a197764303d8a520a601166822524506', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09DH88J1659FDDYJ83JH1M', 'description', NULL, 'User report 2026-06-16: typing `/` in the Claude composer **intermittently** does not open the slash-command typeahead dialog. Non-deterministic — sometimes it opens, sometimes the `/` just types with no popover.
Two hypotheses to distinguish (the fix depends which):
1. **Handler not triggering on `/`** — the composer''s keypress/text-change detection that should fire the typeahead misses the `/` (focus/IME race, the `/` not at a word boundary, the listener not firing on that change). If so, the popover never opens regardless of list contents.
2. **Empty/incomplete list** — the handler fires but the command list is empty or still loading (the slash-command set from the CLI probe / routing table not yet populated → typeahead opens with nothing and dismisses, or suppresses on empty). If so, it correlates with session warm-up / probe timing.
**Diagnosis first:** add a log at the trigger point (did `/` fire the open?) and at list-resolution (how many entries?) to see which path fails when it reproduces. Likely correlates with session/probe readiness (intermittent → timing).
**Files:** lib/builtin/claude/src/claude_composer.dart (the composer + typeahead trigger on `/`), lib/builtin/claude/src/slash_commands.dart (the command set / routing table, kClideOwnedCommands / kTuiOnlyCommands), the ClideTypeahead primitive (slash typeahead was migrated onto it). Compare with the `@`-mention typeahead (at_commands.dart), which shares the primitive — does `@` reproduce the same intermittency? That isolates primitive vs slash-specific.
**Acceptance:** `/` reliably opens the typeahead on every invocation (cold session + warm); if the list isn''t ready yet, open with a loading/empty state rather than silently not opening; a regression test around the trigger + empty-list path.', NULL, '2026-06-16 11:17:44', '2026-06-16 11:17:44', '2026-06-16 11:17:44', NULL, 'ccec4493b58264e0921ce0670e6fbe13', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09C4A0HPZSP8HP44F7A894', 'description', NULL, 'Centered modal over the dimmed app using modalSurface/modalOverlay tokens (D-7, no Material); new settings.open CommandContribution (palette + menu/hat entry); close button + Esc dismiss; hosts the category rail + scrolling carded panel; mounted in root_shell like the other overlays. Wireframe: docs/design/wireframes/settings/settings-screen.png (modal shell).', NULL, '2026-06-16 11:17:54', '2026-06-16 11:17:54', '2026-06-16 11:17:54', NULL, '71d80701bc0f7a46d2a58a543143ff5a', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09SHDMGT66C4D1DRZQZ7RR', 'description', NULL, 'Left rail listing categories (Editor, Keymap, Appearance, Claude, Activity, Terminal, Extensions) with the accent left-stripe + surfaceHi selection; selecting a category swaps the panel; the category set is derived from the registered schemas (data-driven, not hardcoded); the search box sits atop the rail. Wireframe: settings-screen.png / settings-claude.png rail.', NULL, '2026-06-16 11:18:16', '2026-06-16 11:18:16', '2026-06-16 11:18:16', NULL, '0ed6ee0b39a849c77fa8773a83576f40', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09TVT3E3ZSV09QRNTSQ8J4', 'description', NULL, 'The core engine: render carded sections of field rows from a subsystem schema registered against the kernel SettingsStore — toggle, enum/select, text/number, and opens-external-file affordance — each with label, help text, default value, and reset-to-default; writes edits back to the resolved scope''s settings file. Categories just register schemas; this draws them. Carded-section layout per ui-design surface.md. Wireframe: settings-screen.png (Editor).', NULL, '2026-06-16 11:18:27', '2026-06-16 11:18:27', '2026-06-16 11:18:27', NULL, '25283a37d7f7450ed7f53c5c9578382c', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09WB2XSRP0AZ204FDP681M', 'description', NULL, 'Per-field scope icon — folder=Project (.clide), globe=Always (~/.clide), circle-dashed=Default/unset — via PhosphorIcons.byName(''folder''|''globe''|''circle-dashed'') (T-314, no consts), colour-coded with a tooltip; tap opens a scope menu to move the value between scopes. Resolves the effective value across scope layers and writes the edit to the chosen scope''s file. Scope-tag decision: T-302. Wireframe legend on settings-screen.png.', NULL, '2026-06-16 11:18:41', '2026-06-16 11:18:41', '2026-06-16 11:18:41', NULL, 'a70401823b69148f142ac32844ece558', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09XWEXRJ4JS8MFPQGJEY5M', 'description', NULL, 'The search box filters fields across ALL categories; results render as carded groups under category subheaders, editable inline, with per-category match counts shown in the rail. Zero-match categories dim. Wireframe: settings-search.png.', NULL, '2026-06-16 11:18:51', '2026-06-16 11:18:51', '2026-06-16 11:18:51', NULL, '63bdec18d4c8933b8c9c491d1bdec82b', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNQM44CKN5QQGFKP1KWZC', 'parent_id', 'T-8', 'T-444', NULL, '2026-06-16 11:19:03', '2026-06-16 11:19:03', '2026-06-16 11:19:03', NULL, '80eef9832e6ef2048aed0b02bbfc2765', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A0ZTS9JZCSQ4W8ZVEH2VR', 'description', NULL, 'Register the keymap settings schema: preset enum select (default / vscode / jetbrains / vim — T-115, T-64, T-65, T-66) wired to KeymapService.setPreset, plus related options (e.g. sequence-timeout). Reuses the schema field renderer (T-448).', NULL, '2026-06-16 11:19:35', '2026-06-16 11:19:35', '2026-06-16 11:19:35', NULL, '1378cada399c128b9a3f5c45721c6088', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A4MY8DF6NB0KNV96RQADR', 'description', NULL, 'The one custom control beyond the four field patterns: a theme-picker swatch grid with live mini-previews of the bundled themes (D-44 / D-69), selected state, and import-custom-YAML; plus high-contrast toggle and text-size. Coordinate with / extend the existing builtin.theme-picker (T-8) and per-repo theme persistence (T-293). Design pinned in T-302. Wireframe: docs/design/wireframes/settings/settings-appearance.png.', NULL, '2026-06-16 11:19:47', '2026-06-16 11:19:47', '2026-06-16 11:19:47', NULL, 'e4d1aa3170384cb44c6099528db76ac0', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'description', NULL, 'Register the Claude-activity settings schema: activity fold level (T-183) and related conversation display options, via the standard field renderer (T-448).', NULL, '2026-06-16 11:20:21', '2026-06-16 11:20:21', '2026-06-16 11:20:21', NULL, '658bd31d93101ce02bdbf34871d2d032', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0ABC7QNEC3XCTV73YPSGR4', 'description', NULL, 'User report 2026-06-16: Claude Code''s **remote-control** feature (start / monitor / steer a running Claude Code session remotely — e.g. from claude.ai or the mobile app) is **not plumbed into clide**.
clide hosts the `claude` CLI as a stream-json child (`--session-id` / `--resume`, D-77). For remote control to work through clide, a clide-hosted session needs to be discoverable + steerable by the remote-control surface the same way a terminal-launched `claude` is.
**Step 1 — characterize (don''t assume the mechanism):** determine exactly what Claude Code exposes for remote control on the running CLI version. Likely touch points:
- the `~/.claude/sessions/<pid>.json` live-session registry we characterized in T-437 (PID-keyed: sessionId, cwd, version, kind, entrypoint, status) — is this what the remote-control surface enumerates? clide-spawned sessions DO write an entry (we saw `entrypoint: sdk-cli`). Confirm whether clide''s entry is visible/controllable remotely, or whether `entrypoint: sdk-cli` / headless spawn excludes it.
- any flag / capability in the `initialize` stream-json probe (T-411/T-151 cache) advertising remote control.
- whether enrollment requires the interactive TUI (and so is suppressed under clide''s stream-json spawn).
**Step 2 — plumb:** wire clide so a clide-hosted session participates in remote control (register correctly / pass the needed flag), and surface its state in the UI (e.g. an indicator that the session is remote-controllable / being driven remotely). If it conflicts with clide''s session ownership (pane pins a session-id, T-156), document the boundary.
**Open question:** is the goal (a) clide sessions become remotely controllable from claude.ai/mobile, or (b) clide can act as a remote controller of other sessions? Default read is (a). Confirm with the user before building.
Related: D-77 (stream-json session model), T-437 (sessions registry characterization), T-156 (clide owns session lifecycle), T-411 (capability probe).', NULL, '2026-06-16 13:20:17', '2026-06-16 13:20:17', '2026-06-16 13:20:17', NULL, 'b5428fe4b6cfec075693b19f46d0203d', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15S1A0WRTY9WWFG0R4AAZ4', 'description', NULL, 'Register the terminal settings schema (font family/size, scrollback, cursor style, bell, copy-on-select, etc.) as standard toggle / number / select fields via the field renderer (T-448).', NULL, '2026-06-16 13:20:34', '2026-06-16 13:20:34', '2026-06-16 13:20:34', NULL, '6ed2b34154ae47dc645f570889ea8c48', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15TY946689VZK3MNABSMDW', 'description', NULL, 'List installed extensions and surface each extension''s registered settings (ext.<id>.* — the extension-owned config pattern from ui-design theme.md); per-extension enable/disable + configure. Reuses the field renderer; extensions register their schema the same way core subsystems do.', NULL, '2026-06-16 13:20:47', '2026-06-16 13:20:47', '2026-06-16 13:20:47', NULL, '0f2073250cde4ea3213f33008aec0cba', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15W7SBVAD3QR5NVE67PKWR', 'description', NULL, 'Mirror lib/builtin/claude/src/meta_sidebar/config_tab.dart in the settings modal: SETTINGS controls (model / effort / permission mode / output style via SettingControlRow publishing the slash command on the live session, D-6 / T-414) plus carded config lists (Skills / Agents / Commands / Hooks / Permissions / MCP Servers) that open their .md (T-183). Reuse the data the sidebar already loads (ClaudeConfig). Wireframe: docs/design/wireframes/settings/settings-claude.png.', NULL, '2026-06-16 13:21:00', '2026-06-16 13:21:00', '2026-06-16 13:21:00', NULL, '1efc3eadc7b93d57c205deddab67bbb3', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNQM7H8JWCP59WQVD0FW4', 'status', 'in_progress', 'done', NULL, '2026-06-16 13:21:11', '2026-06-16 13:21:11', '2026-06-16 13:21:11', NULL, '6410fd78c4919240bb5eaba9daa4f807', 2) ON CONFLICT(hash) DO NOTHING;
+14
View File
@@ -269,3 +269,17 @@ INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCZGG38FF8T9ADF945Z0XPMG', 'T-442', '2026-06-16 09:27:39', '2026-06-16 09:27:39', NULL, 'c85d8fd95cd73aec1e83b477612e1131', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCRERT7X5WMZSGKQCA6T0VB4', 'T-440', '2026-06-15 17:01:25', '2026-06-15 17:01:25', NULL, 'b8e152bf87ec8d81d1bddeb023f37883', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCQZ47MAN835B215GSSMRV8W', 'T-443', '2026-06-15 15:53:05', '2026-06-16 10:17:57', NULL, 'a4d4390596d24d7dc28d80861e36d66b', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD07ECS3GK2V7Z2WYYPJHJYC', 'T-444', '2026-06-16 11:07:54', '2026-06-16 11:07:54', NULL, 'ec7a0d8d01c984d931855a6e5c4e86ec', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09C4A0HPZSP8HP44F7A894', 'T-445', '2026-06-16 11:16:20', '2026-06-16 11:16:20', NULL, '418d561d50d37c3dd9b6e3abe5fc1b1f', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09DH88J1659FDDYJ83JH1M', 'T-446', '2026-06-16 11:16:31', '2026-06-16 11:16:31', NULL, '7c0bc42be1a170b5bb2dd8bd7b027d69', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09SHDMGT66C4D1DRZQZ7RR', 'T-447', '2026-06-16 11:18:10', '2026-06-16 11:18:10', NULL, '203dfb0348a94392f2d087b79aee655f', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09TVT3E3ZSV09QRNTSQ8J4', 'T-448', '2026-06-16 11:18:20', '2026-06-16 11:18:20', NULL, '765a91fb5b51889861a41f7eea308ea6', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09WB2XSRP0AZ204FDP681M', 'T-449', '2026-06-16 11:18:32', '2026-06-16 11:18:32', NULL, '1dbd17ff345551d3f091a226bb0f7164', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09XWEXRJ4JS8MFPQGJEY5M', 'T-450', '2026-06-16 11:18:45', '2026-06-16 11:18:45', NULL, '56f97ccefa83681c387ee9cc4ca6a477', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A0ZTS9JZCSQ4W8ZVEH2VR', 'T-451', '2026-06-16 11:19:11', '2026-06-16 11:19:11', NULL, 'c329f6f1a5d205b7bdf5ab682812a6d1', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A4MY8DF6NB0KNV96RQADR', 'T-452', '2026-06-16 11:19:41', '2026-06-16 11:19:41', NULL, '71a7729a8cf7ebc4e915a9e2736717bd', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'T-453', '2026-06-16 11:19:57', '2026-06-16 11:19:57', NULL, 'd408d563785166ee1b40e7494c7f3bbc', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0ABC7QNEC3XCTV73YPSGR4', 'T-454', '2026-06-16 11:20:36', '2026-06-16 11:20:36', NULL, '27e2ae5b0897eb0f589f4617061101a9', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15S1A0WRTY9WWFG0R4AAZ4', 'T-455', '2026-06-16 13:20:25', '2026-06-16 13:20:25', NULL, '370e913c62eab739cf39bda08089e033', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15TY946689VZK3MNABSMDW', 'T-456', '2026-06-16 13:20:41', '2026-06-16 13:20:41', NULL, '6041202d66dd93ee3d22206ece3a7db7', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15W7SBVAD3QR5NVE67PKWR', 'T-457', '2026-06-16 13:20:52', '2026-06-16 13:20:52', NULL, 'c9bef415fb7d9d03444fde53ecac3bb1', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
+100
View File
@@ -6905,3 +6905,103 @@ INSERT INTO tickets (record_id, type, parent_record_id, title, description, stat
- DLL is included in the make build-windows / Windows bundle output and loads from the bundled path.
**Out of scope:** CI reproducibility, macOS .dylib cross-compile, and the wasmtime NOTICE-file vendoring — those stay on the T-25 umbrella. This ticket is the hand-built Windows DLL to unblock highlighting locally now. Once T-25''s CI cross-compile lands, the Windows target folds into it.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-15 17:01:25', '2026-06-15 17:01:25', NULL, '9965c3d1b894e3af420f2e625b46efc4', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD07ECS3GK2V7Z2WYYPJHJYC', 'epic', '06FB0TNQM6T6580D8ABDVTMNZW', 'Settings UI (builtin.settings-ui) — schema-driven settings panel', NULL, 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:07:54', '2026-06-16 11:07:54', NULL, 'd1d3289581aa33cf921259239f64596d', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD07ECS3GK2V7Z2WYYPJHJYC', 'epic', '06FB0TNQM6T6580D8ABDVTMNZW', 'Settings UI (builtin.settings-ui) — schema-driven settings panel', 'Implement the schema-driven settings UI (`builtin.settings-ui`) designed in T-302. Wireframes (JSON source + PNG): `docs/design/wireframes/settings/` — settings-screen (Editor), settings-search, settings-claude, settings-appearance.
**Form factor / IA (decided in T-302):** a centered MODAL overlay over the dimmed app (modal* / modalOverlay* tokens; close ✕ + Esc), opened by a `settings.open` command. Left category rail + a cross-category search box; right scrolling panel of CARDED sections — each logical group is a card (surface fill + 1px border, ~6px corners) with a small-caps section label + count above it. See the new `ui-design` `surface.md` → "Settings & grouped lists — sectioned cards".
**Engine, not per-screen UI:** field rows render from the schema each subsystem registers against the kernel SettingsStore — toggle / enum-select / text-number / "opens external file" affordance — each with label, help, default, reset, and a per-field SCOPE TAG (folder = project `.clide` / globe = always `~/.clide` / circle-dashed = default-unset; colour + tooltip; tap → scope menu). Edits write back to the resolved scope''s settings file. Categories are DATA; the only custom control is Appearance''s theme picker.
**Decisions / consumers:** kernel SettingsStore schema; WidgetsApp-only tokens (D-7); keymap presets (T-115 / T-64 / T-65 / T-66); editor settings (T-290 / T-29); activity fold (T-183); theming (existing builtin.theme-picker, D-44 / D-69); Claude config mirrors `lib/builtin/claude/src/meta_sidebar/config_tab.dart` (T-414 / T-183). Phosphor glyphs resolve via `byName(...)` (T-314) — no consts to add.
**Children — build infra first, then categories extrapolate:**
Infra: modal shell + `settings.open`; category rail + nav; schema field renderer (the engine); scope-tag control + scope resolution; cross-category search.
Categories (register a schema, reuse the engine): Editor (T-290), Keymap, Appearance (theme-picker control), Activity, Terminal, Extensions, Claude (mirror the sidebar Config panel).', 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:07:54', '2026-06-16 11:13:12', NULL, '7d72157d0bac885363cb1f3c5781ff3d', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09C4A0HPZSP8HP44F7A894', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Settings modal shell + settings.open command + overlay', NULL, 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:16:20', '2026-06-16 11:16:20', NULL, 'a824ba240ccb186486421d8eac08f8ba', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09DH88J1659FDDYJ83JH1M', 'bug', '06FB0TNQM5TWC00GW0P3X02HZW', 'Slash-command typeahead intermittently fails to open on /', NULL, 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 11:16:31', '2026-06-16 11:16:31', NULL, '679eb2ed603d98f47a40d2fff3c88108', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09DH88J1659FDDYJ83JH1M', 'bug', '06FB0TNQM5TWC00GW0P3X02HZW', 'Slash-command typeahead intermittently fails to open on /', 'User report 2026-06-16: typing `/` in the Claude composer **intermittently** does not open the slash-command typeahead dialog. Non-deterministic — sometimes it opens, sometimes the `/` just types with no popover.
Two hypotheses to distinguish (the fix depends which):
1. **Handler not triggering on `/`** — the composer''s keypress/text-change detection that should fire the typeahead misses the `/` (focus/IME race, the `/` not at a word boundary, the listener not firing on that change). If so, the popover never opens regardless of list contents.
2. **Empty/incomplete list** — the handler fires but the command list is empty or still loading (the slash-command set from the CLI probe / routing table not yet populated → typeahead opens with nothing and dismisses, or suppresses on empty). If so, it correlates with session warm-up / probe timing.
**Diagnosis first:** add a log at the trigger point (did `/` fire the open?) and at list-resolution (how many entries?) to see which path fails when it reproduces. Likely correlates with session/probe readiness (intermittent → timing).
**Files:** lib/builtin/claude/src/claude_composer.dart (the composer + typeahead trigger on `/`), lib/builtin/claude/src/slash_commands.dart (the command set / routing table, kClideOwnedCommands / kTuiOnlyCommands), the ClideTypeahead primitive (slash typeahead was migrated onto it). Compare with the `@`-mention typeahead (at_commands.dart), which shares the primitive — does `@` reproduce the same intermittency? That isolates primitive vs slash-specific.
**Acceptance:** `/` reliably opens the typeahead on every invocation (cold session + warm); if the list isn''t ready yet, open with a loading/empty state rather than silently not opening; a regression test around the trigger + empty-list path.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 11:16:31', '2026-06-16 11:17:44', NULL, '4cd213bf992066080ce6e54585aa701e', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09C4A0HPZSP8HP44F7A894', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Settings modal shell + settings.open command + overlay', 'Centered modal over the dimmed app using modalSurface/modalOverlay tokens (D-7, no Material); new settings.open CommandContribution (palette + menu/hat entry); close button + Esc dismiss; hosts the category rail + scrolling carded panel; mounted in root_shell like the other overlays. Wireframe: docs/design/wireframes/settings/settings-screen.png (modal shell).', 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:16:20', '2026-06-16 11:17:54', NULL, '89e4286fb5124eaac323f15255b62170', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09SHDMGT66C4D1DRZQZ7RR', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Settings category rail + navigation/selection', NULL, 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:18:10', '2026-06-16 11:18:10', NULL, 'f2bf5ab4dfae8a7cc33e7a0ceb5c057c', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09SHDMGT66C4D1DRZQZ7RR', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Settings category rail + navigation/selection', 'Left rail listing categories (Editor, Keymap, Appearance, Claude, Activity, Terminal, Extensions) with the accent left-stripe + surfaceHi selection; selecting a category swaps the panel; the category set is derived from the registered schemas (data-driven, not hardcoded); the search box sits atop the rail. Wireframe: settings-screen.png / settings-claude.png rail.', 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:18:10', '2026-06-16 11:18:16', NULL, 'f35a864ea275616c0cf8e045d4fb5fd7', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09TVT3E3ZSV09QRNTSQ8J4', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Schema-driven settings field renderer (the engine)', NULL, 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:18:20', '2026-06-16 11:18:20', NULL, '1711db6c6efda82a219d4c385e342380', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09TVT3E3ZSV09QRNTSQ8J4', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Schema-driven settings field renderer (the engine)', 'The core engine: render carded sections of field rows from a subsystem schema registered against the kernel SettingsStore — toggle, enum/select, text/number, and opens-external-file affordance — each with label, help text, default value, and reset-to-default; writes edits back to the resolved scope''s settings file. Categories just register schemas; this draws them. Carded-section layout per ui-design surface.md. Wireframe: settings-screen.png (Editor).', 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:18:20', '2026-06-16 11:18:27', NULL, 'ecf41b355896513f5edd509b67c3b859', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09WB2XSRP0AZ204FDP681M', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Per-field scope-tag control + scope resolution', NULL, 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:18:32', '2026-06-16 11:18:32', NULL, '0c3fa39331b62551b77e07a5ac7eebe8', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09WB2XSRP0AZ204FDP681M', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Per-field scope-tag control + scope resolution', 'Per-field scope icon — folder=Project (.clide), globe=Always (~/.clide), circle-dashed=Default/unset — via PhosphorIcons.byName(''folder''|''globe''|''circle-dashed'') (T-314, no consts), colour-coded with a tooltip; tap opens a scope menu to move the value between scopes. Resolves the effective value across scope layers and writes the edit to the chosen scope''s file. Scope-tag decision: T-302. Wireframe legend on settings-screen.png.', 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:18:32', '2026-06-16 11:18:41', NULL, '74e604297688044c907da7bd19b0a101', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09XWEXRJ4JS8MFPQGJEY5M', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Cross-category settings search', NULL, 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:18:45', '2026-06-16 11:18:45', NULL, '795846d24468f420c16e0ea5dbec175b', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09XWEXRJ4JS8MFPQGJEY5M', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Cross-category settings search', 'The search box filters fields across ALL categories; results render as carded groups under category subheaders, editable inline, with per-category match counts shown in the rail. Zero-match categories dim. Wireframe: settings-search.png.', 'backlog', 'high', NULL, NULL, NULL, '2026-06-16 11:18:45', '2026-06-16 11:18:51', NULL, '6b361bb70ed3915bf53a7c7477cc8cba', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNQM44CKN5QQGFKP1KWZC', 'story', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Edit editor settings (.editorconfig) from the settings panel', 'Write path for editor settings (T-29 follow-up). The editor now READS .editorconfig into a source-agnostic EditorSettings model (lib/src/editor/editor_settings.dart) and resolves it via editor_settings_resolver.dart. Add a settings-panel surface to EDIT these values and persist them — initially by writing the project .editorconfig (indent_style/size, end_of_line, max_line_length, trim_trailing_whitespace, insert_final_newline), later possibly a clide-owned settings file that merges as a higher-precedence source in resolveEditorSettings. On save the registry already re-resolves open buffers (editor.settings-changed), so the panel edits apply live. Respect EditorConfig semantics (sections/globs); start with the [*] section for the workspace defaults. Refs: T-29, D-88, editor_settings.dart, editor_settings_resolver.dart.', 'backlog', 'medium', NULL, NULL, 'D-88', '2026-06-09 07:15:14', '2026-06-16 11:19:03', NULL, '9728be42a0f8f9cd0cbf2563b3dd7555', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A0ZTS9JZCSQ4W8ZVEH2VR', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Keymap settings category (preset select + options)', NULL, 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:11', '2026-06-16 11:19:11', NULL, '3530c732f928f84a36e8ac450880835d', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A0ZTS9JZCSQ4W8ZVEH2VR', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Keymap settings category (preset select + options)', 'Register the keymap settings schema: preset enum select (default / vscode / jetbrains / vim — T-115, T-64, T-65, T-66) wired to KeymapService.setPreset, plus related options (e.g. sequence-timeout). Reuses the schema field renderer (T-448).', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:11', '2026-06-16 11:19:35', NULL, '7eba4a1e2a613734facc67e035f6ac08', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A4MY8DF6NB0KNV96RQADR', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Appearance settings category — theme picker control', NULL, 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:41', '2026-06-16 11:19:41', NULL, '02e42ddbdc8109d08129c224b097cc4b', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A4MY8DF6NB0KNV96RQADR', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Appearance settings category — theme picker control', 'The one custom control beyond the four field patterns: a theme-picker swatch grid with live mini-previews of the bundled themes (D-44 / D-69), selected state, and import-custom-YAML; plus high-contrast toggle and text-size. Coordinate with / extend the existing builtin.theme-picker (T-8) and per-repo theme persistence (T-293). Design pinned in T-302. Wireframe: docs/design/wireframes/settings/settings-appearance.png.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:41', '2026-06-16 11:19:47', NULL, '6939e563a1bd65e6ea4a2dd370358b27', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Activity settings category (fold level + display)', NULL, 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:57', '2026-06-16 11:19:57', NULL, 'bedd84023b232dc391ff4fbbce771f8a', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Activity settings category (fold level + display)', 'Register the Claude-activity settings schema: activity fold level (T-183) and related conversation display options, via the standard field renderer (T-448).', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:57', '2026-06-16 11:20:21', NULL, '9cbd66575a1785399eb3c1898720f6b9', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0ABC7QNEC3XCTV73YPSGR4', 'task', NULL, 'Plumb in Claude Code''s remote-control feature', NULL, 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 11:20:36', '2026-06-16 11:20:36', NULL, '4dd8daefbdbf993ef612b3e4fb74d67a', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0ABC7QNEC3XCTV73YPSGR4', 'task', NULL, 'Plumb in Claude Code''s remote-control feature', 'User report 2026-06-16: Claude Code''s **remote-control** feature (start / monitor / steer a running Claude Code session remotely — e.g. from claude.ai or the mobile app) is **not plumbed into clide**.
clide hosts the `claude` CLI as a stream-json child (`--session-id` / `--resume`, D-77). For remote control to work through clide, a clide-hosted session needs to be discoverable + steerable by the remote-control surface the same way a terminal-launched `claude` is.
**Step 1 — characterize (don''t assume the mechanism):** determine exactly what Claude Code exposes for remote control on the running CLI version. Likely touch points:
- the `~/.claude/sessions/<pid>.json` live-session registry we characterized in T-437 (PID-keyed: sessionId, cwd, version, kind, entrypoint, status) — is this what the remote-control surface enumerates? clide-spawned sessions DO write an entry (we saw `entrypoint: sdk-cli`). Confirm whether clide''s entry is visible/controllable remotely, or whether `entrypoint: sdk-cli` / headless spawn excludes it.
- any flag / capability in the `initialize` stream-json probe (T-411/T-151 cache) advertising remote control.
- whether enrollment requires the interactive TUI (and so is suppressed under clide''s stream-json spawn).
**Step 2 — plumb:** wire clide so a clide-hosted session participates in remote control (register correctly / pass the needed flag), and surface its state in the UI (e.g. an indicator that the session is remote-controllable / being driven remotely). If it conflicts with clide''s session ownership (pane pins a session-id, T-156), document the boundary.
**Open question:** is the goal (a) clide sessions become remotely controllable from claude.ai/mobile, or (b) clide can act as a remote controller of other sessions? Default read is (a). Confirm with the user before building.
Related: D-77 (stream-json session model), T-437 (sessions registry characterization), T-156 (clide owns session lifecycle), T-411 (capability probe).', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 11:20:36', '2026-06-16 13:20:17', NULL, '0587e7b599ca9a2a96594172eeb9cffb', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15S1A0WRTY9WWFG0R4AAZ4', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Terminal settings category', NULL, 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 13:20:25', '2026-06-16 13:20:25', NULL, '9a4be93680d3b74b4776993d9130437f', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15S1A0WRTY9WWFG0R4AAZ4', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Terminal settings category', 'Register the terminal settings schema (font family/size, scrollback, cursor style, bell, copy-on-select, etc.) as standard toggle / number / select fields via the field renderer (T-448).', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 13:20:25', '2026-06-16 13:20:34', NULL, '0e3ee0e73ee8c060bb7639a12097ebbb', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15TY946689VZK3MNABSMDW', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Extensions settings category', NULL, 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 13:20:41', '2026-06-16 13:20:41', NULL, '8d6553a634106c3acd075eb95b9d53a6', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15TY946689VZK3MNABSMDW', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Extensions settings category', 'List installed extensions and surface each extension''s registered settings (ext.<id>.* — the extension-owned config pattern from ui-design theme.md); per-extension enable/disable + configure. Reuses the field renderer; extensions register their schema the same way core subsystems do.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 13:20:41', '2026-06-16 13:20:47', NULL, '8eb78852a5c8f1e22b5afa99706cbfdb', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15W7SBVAD3QR5NVE67PKWR', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Claude settings category — mirror the sidebar Config panel', NULL, 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 13:20:52', '2026-06-16 13:20:52', NULL, '33510004b4584821ccf0c368f76b3235', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD15W7SBVAD3QR5NVE67PKWR', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Claude settings category — mirror the sidebar Config panel', 'Mirror lib/builtin/claude/src/meta_sidebar/config_tab.dart in the settings modal: SETTINGS controls (model / effort / permission mode / output style via SettingControlRow publishing the slash command on the live session, D-6 / T-414) plus carded config lists (Skills / Agents / Commands / Hooks / Permissions / MCP Servers) that open their .md (T-183). Reuse the data the sidebar already loads (ClaudeConfig). Wireframe: docs/design/wireframes/settings/settings-claude.png.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-16 13:20:52', '2026-06-16 13:21:00', NULL, '70d5a923985efd727ca999489962e7d0', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNQM7H8JWCP59WQVD0FW4', 'task', '06FB0TNQM6T6580D8ABDVTMNZW', 'Frame0 wireframe: settings screen design', 'Design the app''s settings screen as a Frame0 wireframe before building `builtin.settings-ui` (see Tier 6 epic T-8). Output is a wireframe to align on layout/IA, not implementation.
**Deliverable**
- Frame0 wireframe authored via the frame0-wireframe skill: local JSON source-of-truth synced to Frame0, exported for review.
- Covers the settings screen shell + at least one fully-rendered category so the form-field patterns are concrete.
**Scope to frame (from T-8)**
- Schema-driven panel: form fields keyed off the schema each subsystem registers against the kernel SettingsStore; edits write back to `.clide/settings.yaml`.
- Navigation/IA: how categories are grouped and selected (sidebar list? sections? search?).
- Field types to mock: toggle, enum/select (e.g. keymap preset), text/number, and a ''opens external file'' affordance (e.g. editor `.editorconfig` per T-290).
- Known consumers to account for: keymap preset switching (T-115/T-64/T-65/T-66), editor settings (T-290), activity fold level (T-183), theme picker (Tier 6 theming UI).
**Open design questions for the wireframe to answer**
- Settings as a full-screen view, a pane/tab, or a modal?
- Per-project (`.clide/settings.yaml`) vs. user-global scope — shown together or switched?
- Search/filter across all settings.
- How schema-driven fields render labels, help text, defaults, and reset.
**Constraints**
- Follow clide visual language — pull theme tokens / control geometry from the ui-design skill so the wireframe maps cleanly to real widgets (no Material/Cupertino).
This is the design step; implementation of the actual settings UI is separate child work under T-8.
## Scope-tag icon decision (review, 2026-06-10)
The per-field scope tag is an ICON, not a text label (space + cognitive load).
Chosen trio (location→global reach ladder), keeping the colour coding + a
tooltip with the word for clarity/a11y; tapping opens the scope menu:
- Project (this repo) = `folder` 0xe24a (teal) — already wired
- Always (all clide) = `globe` 0xe288 (amber) — add const
- Default (unset) = `circle-dashed` 0xe602 (grey) — add const
Alternatives considered: house (warmer home↔world pair), user-circle (mirrors
the real .clide vs ~/.clide files), gear (collides with "settings"). Note that
every Phosphor glyph already renders via PhosphorIconPainter(0xNNNN); only named
consts need adding. Preview/picking is blocked on a native glyph card (see the
new ticket) — goldens render the font as Ahem boxes.', 'done', 'medium', NULL, NULL, NULL, '2026-06-09 20:24:54', '2026-06-16 13:21:11', NULL, '1db1af71519321792537391a5f38b613', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);