diff --git a/.pql/changelog/ticket_history/2026-06.sql b/.pql/changelog/ticket_history/2026-06.sql index 39c90e91..1d974adc 100644 --- a/.pql/changelog/ticket_history/2026-06.sql +++ b/.pql/changelog/ticket_history/2026-06.sql @@ -985,3 +985,4 @@ These tests are tagged ''pty'' and are meant to run in the gate''s serial pass. FIXED 2026-06-09 (commit 0231cb4). Root cause: ci/test_core.sh ran ''dart test test/ipc test/pty ... test/pql'' in the DEFAULT parallel pool, so test/pty''s real-PTY tests contended for fds+CPU with the other core suites and the reader isolate was starved. (ci/test.sh already isolated pty via --concurrency=1 --tags pty; test_core.sh was the gap.) My manual ''flutter test --coverage'' repro was a separate wrong-invocation artifact — the flutter runner can''t reliably deliver the PTY master fd, which is why the gate excludes pty from the flutter pool entirely.) Fix: test_core.sh now runs a serial ''--concurrency=1 --tags pty'' pass + a parallel ''--exclude-tags pty'' pass, mirroring ci/test.sh. Verified: pty pass +5 stable across repeated runs; full core +571 unchanged. Option (a) from the ticket.', NULL, '2026-06-09 15:09:05', '2026-06-09 15:09:05', '2026-06-09 15:09:05', NULL, 'c06cbcb21ad470e62af4beba4b2e8f57', 1) ON CONFLICT(hash) DO NOTHING; INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-292', 'status', 'in_progress', 'done', NULL, '2026-06-09 15:09:05', '2026-06-09 15:09:05', '2026-06-09 15:09:05', NULL, '6e5ddf473f6094246098d13c65515825', 1) ON CONFLICT(hash) DO NOTHING; INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-236', 'status', 'backlog', 'ready', NULL, '2026-06-09 15:10:57', '2026-06-09 15:10:57', '2026-06-09 15:10:57', NULL, '004f3513ae78eb18ddde5ebdba44c518', 1) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-293', 'status', 'backlog', 'ready', NULL, '2026-06-09 15:13:06', '2026-06-09 15:13:06', '2026-06-09 15:13:06', NULL, '2dc7c5580e1bb26d741b5c6f08dbbd83', 1) ON CONFLICT(hash) DO NOTHING; diff --git a/.pql/changelog/tickets/2026-06.sql b/.pql/changelog/tickets/2026-06.sql index 624a18ff..9e1d3b54 100644 --- a/.pql/changelog/tickets/2026-06.sql +++ b/.pql/changelog/tickets/2026-06.sql @@ -2499,3 +2499,18 @@ Open question: app-scoped fallback. Persist project-scoped per the report; optio Acceptance: pick a theme (incl. the High-contrast toggle) -> restart -> same theme restored for that repo; two repos keep independent choices; with no repo open, the app default applies; a saved theme that no longer exists degrades to the default without throwing. Tests: SettingsStore round-trips ''project.theme''; opening a project applies the saved theme to the controller; select() persists; unknown saved theme falls back. Refs: T-234 (theme switcher), T-288/D-88 (picker), SettingsStore, ProjectManager.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-09 15:12:15', '2026-06-09 15:12:15', NULL, '40f736095167bf5033a84316e0e13df8', 1) ON CONFLICT(id) DO UPDATE SET type=excluded.type, parent_id=excluded.parent_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 (id, type, parent_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('T-293', 'bug', 'T-276', 'Chosen theme is not persisted per-repo across loads', 'Picking a theme (status-bar switcher T-234, or the Settings modal) applies live but is never saved, so every reload resets to the first bundled theme. The choice should persist PER REPO. + +Root cause: ThemeController.select() (lib/kernel/src/theme/controller.dart:43) only mutates _currentName + notifies — no persistence. It is constructed in facade.dart:160 as ThemeController(bundled: bundledThemes) with no initialName, so on boot it always falls back to bundled.first. + +Infra already exists — no new store needed: SettingsStore (lib/kernel/src/settings.dart) has a PROJECT scope that persists to /.clide/settings.yaml via ''project.*'' keys, and ProjectManager.openProject() already calls settings.setProjectDir() on open (project.dart:130), which loads that file. + +Proposed fix: +1. PERSIST on change — wire a listener on ThemeController (in facade.dart, where both theme + settings exist) that writes the current theme to settings whenever currentName changes; use project scope (''project.theme'') when a repo is open. currentName already encodes the high-contrast variant (resolveThemeName -> ''-hc''), so the HC toggle persists for free. +2. RESTORE on load — the project dir is set AFTER boot, so restoration must hook project-open (ProjectManager.openProject / settings.setProjectDir), not just construction: when a project opens, read ''project.theme'' and, if present + known, theme.select() it. Guard ArgumentError for a theme that is no longer bundled (fall back to default, don''t throw). + +Open question: app-scoped fallback. Persist project-scoped per the report; optionally also write ''app.theme'' as the global default so a brand-new repo inherits the last choice instead of bundled.first. Decide during implementation. + +Acceptance: pick a theme (incl. the High-contrast toggle) -> restart -> same theme restored for that repo; two repos keep independent choices; with no repo open, the app default applies; a saved theme that no longer exists degrades to the default without throwing. + +Tests: SettingsStore round-trips ''project.theme''; opening a project applies the saved theme to the controller; select() persists; unknown saved theme falls back. Refs: T-234 (theme switcher), T-288/D-88 (picker), SettingsStore, ProjectManager.', 'ready', 'medium', NULL, NULL, NULL, '2026-06-09 15:12:15', '2026-06-09 15:13:06', NULL, '138f608b7ff1aa7c449fe55f28d1c4d7', 1) ON CONFLICT(id) DO UPDATE SET type=excluded.type, parent_id=excluded.parent_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);