sync governance question index
Regenerated by `pql decisions sync` — moves resolved questions (Q-6, Q-19, Q-21, Q-22) into a Resolved section. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2301,3 +2301,10 @@ INSERT INTO ticket_history (ticket_id, field, old_value, new_value, changed_by,
|
||||
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-184', 'status', 'in_progress', 'done', NULL, '2026-05-31 10:17:09', '2026-05-31 10:17:09', '2026-05-31 10:17:09', NULL, '8d23aadcaeebbf9b08ba0ccf495578bf', 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-185', 'status', 'backlog', 'done', NULL, '2026-05-31 10:22:02', '2026-05-31 10:22:02', '2026-05-31 10:22:02', NULL, 'a91a00cea5b083cc7c555aa0662495c2', 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-164', 'status', 'backlog', 'done', NULL, '2026-05-31 10:22:03', '2026-05-31 10:22:03', '2026-05-31 10:22:03', NULL, '2738e39138046b8e3704fc64d6f8d787', 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-95', 'status', 'backlog', 'done', NULL, '2026-05-31 11:20:21', '2026-05-31 11:20:21', '2026-05-31 11:20:21', NULL, '0236a359632b1fcf101f68a25131abb5', 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-162', 'status', 'backlog', 'in_progress', NULL, '2026-05-31 11:42:11', '2026-05-31 11:42:11', '2026-05-31 11:42:11', NULL, '39d0ae4510e70f877b5c07417d486ac1', 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-187', 'status', 'backlog', 'in_progress', NULL, '2026-05-31 11:42:11', '2026-05-31 11:42:11', '2026-05-31 11:42:11', NULL, 'b4eea5fc17737821e8e9ce3d53ea62ba', 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-188', 'status', 'backlog', 'in_progress', NULL, '2026-05-31 11:42:11', '2026-05-31 11:42:11', '2026-05-31 11:42:11', NULL, 'fd62fc2dc8e6278288a7c52ad450ab0d', 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-192', 'description', 'The pre-push gate (make push-check) and the inner-loop make test are slow; cost is dominated by ''flutter test --coverage --exclude-tags pty'' running the whole flutter suite WITH coverage instrumentation (ci/test.sh). Two concrete levers found by reading the pipeline: (1) FREE WIN — a11y tests run TWICE in push-check: the coverage run in ci/test.sh has no path filter so it already includes test/a11y/, then ci/test_a11y.sh (''flutter test test/a11y/'') runs them again in a separate flutter invocation, chained AFTER test (so not even fast-fail). Drop test-a11y from the push-check chain (keep ''make test-a11y'' as a standalone dev target) to remove a whole redundant flutter compile+boot+run; same tests still execute under test. (2) Coverage is on the dev inner loop — make test always runs --coverage, which is only needed where coverage-gate reads lcov (push-check/CI). Split a fast no-coverage ''make test'' for the edit loop from a coverage run used by push-check/CI; the script even claims <60s warm but coverage blows past that. MEASURE FIRST (cheap): time each ci/*.sh step, check ''flutter test --concurrency'' vs nproc, and look at per-file timing for golden/alchemist tests before further changes. Acceptance: dev ''make test'' runs without coverage and is meaningfully faster; push-check no longer double-runs the a11y suite; coverage is still gated (coverage-gate unchanged, floor 95); all gates stay green; the fast-vs-coverage split is documented in the Makefile/CONTRIBUTING. Domain: tooling/CI. Raised 2026-05-31 while the push gate kept interrupting flow.', 'The pre-push gate (make push-check) and the inner-loop make test are slow; cost is dominated by ''flutter test --coverage --exclude-tags pty'' running the whole flutter suite WITH coverage instrumentation (ci/test.sh). Two concrete levers found by reading the pipeline: (1) FREE WIN — a11y tests run TWICE in push-check: the coverage run in ci/test.sh has no path filter so it already includes test/a11y/, then ci/test_a11y.sh (''flutter test test/a11y/'') runs them again in a separate flutter invocation, chained AFTER test (so not even fast-fail). Drop test-a11y from the push-check chain (keep ''make test-a11y'' as a standalone dev target) to remove a whole redundant flutter compile+boot+run; same tests still execute under test. (2) Coverage is on the dev inner loop — make test always runs --coverage, which is only needed where coverage-gate reads lcov (push-check/CI). Split a fast no-coverage ''make test'' for the edit loop from a coverage run used by push-check/CI; the script even claims <60s warm but coverage blows past that. MEASURE FIRST (cheap): time each ci/*.sh step, check ''flutter test --concurrency'' vs nproc, and look at per-file timing for golden/alchemist tests before further changes. Acceptance: dev ''make test'' runs without coverage and is meaningfully faster; push-check no longer double-runs the a11y suite; coverage is still gated (coverage-gate unchanged, floor 95); all gates stay green; the fast-vs-coverage split is documented in the Makefile/CONTRIBUTING. Domain: tooling/CI. Raised 2026-05-31 while the push gate kept interrupting flow.
|
||||
|
||||
Add a per-test timeout to the gate''s flutter test (e.g. ci/test.sh: ''flutter test --coverage --timeout 60s''). Motivation discovered 2026-05-31: a hung pumpAndSettle has a 10-MINUTE default timeout, so a few hanging widget tests wedge make push-check for 30+ minutes — which is almost certainly why a MacBook session resorted to ''git push --no-verify'' (the gate never returned; it was not disabled, it was hung). A tight per-test timeout makes any future hang fail fast (60s) instead of wedging a pre-push, so the gate stays usable and nobody is tempted to bypass it. Pair with: keep writing pump()-bounded tests instead of pumpAndSettle() where a view has overlapping async loads (see the T-188 decision_reader_test hang).', NULL, '2026-05-31 12:31:58', '2026-05-31 12:31:58', '2026-05-31 12:31:58', NULL, 'e42f8392c580eee1269d266cb0fb9749', 1) ON CONFLICT(hash) DO NOTHING;
|
||||
|
||||
@@ -2886,3 +2886,64 @@ Phase 1 (single-agent, ships the prompt-gap + lifecycle fix): stream-json transp
|
||||
Phase 2 (unified model): session orchestrator (spawn/show/hide), clide-hosted MCP coordination broker + injected team-awareness, sidebar cockpit (tasks + messages + roster controls), fork-into-a-pane.
|
||||
|
||||
Supersedes the transcript-tail + observe-tmux-team approach of epic T-132. Acceptance: Claude runs over stream-json with native prompts + --resume; teams are clide-orchestrated managed sessions controlled from the sidebar; the tmux dependency for Claude is gone (terminal builtin retained for general shell).', 'done', 'high', NULL, NULL, 'D-77', '2026-05-24 16:26:05', '2026-05-31 10:22:03', NULL, 'dcad2cbbc0c36eab5c9787ed5fb30be1', 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-95', 'bug', NULL, 'TerminalGestureHandler tertiary-tap wired to secondary; middle-button mis-typed', '**File:** `lib/src/terminal/src/ui/gesture/gesture_handler.dart` (build wiring + state-method body) + `lib/src/terminal/src/ui/gesture/gesture_detector.dart` (dead public API).
|
||||
|
||||
**Bug:** Middle-clicks ("tertiary tap") are routed through the wrong handler chain, and even the unreachable target carries a button-enum typo. Same shape as T-93 but on a different gesture pair.
|
||||
|
||||
Trace:
|
||||
|
||||
1. `TerminalGestureHandler.build` (gesture_handler.dart:65–82) wires:
|
||||
```dart
|
||||
onTertiaryTapDown: onSecondaryTapDown,
|
||||
onTertiaryTapUp: onSecondaryTapUp,
|
||||
```
|
||||
Right-hand sides are the state''s `onSecondaryTapDown` / `onSecondaryTapUp` *methods* (lines 138–144), not the tertiary equivalents. So a middle-click reaches `_tapDown(widget.onSecondaryTapDown, details, TerminalMouseButton.right)` — i.e. fires the **secondary** callback with **button=right**.
|
||||
2. The state''s `onTertiaryTapDown` and `onTertiaryTapUp` methods (lines 147–152) are therefore **dead** — they''re declared but never invoked anywhere.
|
||||
3. `onTertiaryTapUp` at line 152 has a copy-paste error: `TerminalMouseButton.right` where the function is named tertiary and the comment paragraph clearly intends middle. Even if the wiring were correct, the button reported on tertiary-up would be wrong.
|
||||
4. The `onTertiaryTapDown` / `onTertiaryTapUp` *parameters* on `TerminalGestureHandler` (lines 24–25, 45–47) and `TerminalGestureDetector` (lines 13–14, 30–31) are **dead public surface** — no in-tree caller passes them, like T-93''s `onTapUp`.
|
||||
|
||||
**Two layers of "dead" again:**
|
||||
|
||||
- The wiring is wrong, so middle-clicks dispatch as if they were right-clicks.
|
||||
- The public API to receive proper middle-click notifications doesn''t reach any caller, so even if a consumer passes `onTertiaryTapDown:` to `TerminalView`, it would do nothing today (TerminalView doesn''t expose tertiary callbacks).
|
||||
|
||||
**User-visible impact:**
|
||||
|
||||
A consumer relying on right-click for context-menu behaviour on `TerminalView` will accidentally trigger that menu on middle-click as well, which is wrong on every desktop platform (middle-click is conventionally paste / scroll-wheel-button). Tests of secondary-tap will pass for both right- and middle-clicks, masking the issue.
|
||||
|
||||
**Resolutions, like T-93:**
|
||||
|
||||
- **A. Fix the wiring + typo.** In `TerminalGestureHandler.build`, change `onTertiaryTapDown: onSecondaryTapDown` to `onTertiaryTapDown: onTertiaryTapDown` (and same for Up). Fix line 152''s `TerminalMouseButton.right` → `middle`. Adds a parameter on `TerminalView` (`onTertiaryTapDown` / `onTertiaryTapUp`) so consumers can register middle-click handlers. Test surfaces the new path.
|
||||
- **B. Delete the dead surface.** Remove `onTertiaryTapDown` / `onTertiaryTapUp` parameters from both `TerminalGestureHandler` and `TerminalGestureDetector`, plus the state''s tertiary methods. If middle-click ever needs distinct handling, add it back deliberately. Cleanest because no caller depends on tertiary today.
|
||||
|
||||
Recommendation: **option B**. Same logic as T-93''s recommendation — the surface is documented but unwired and unused. Adding it back later with a real consumer + tests is cheaper than fixing dead surface today.
|
||||
|
||||
**Aside:** there''s a related dead branch in `onDragStart` (line 176):
|
||||
```dart
|
||||
details.kind == PointerDeviceKind.mouse
|
||||
? renderTerminal.selectCharacters(details.localPosition)
|
||||
: renderTerminal.selectWord(details.localPosition);
|
||||
```
|
||||
The `PanGestureRecognizer` in `TerminalGestureDetector` is registered with `supportedDevices: {PointerDeviceKind.mouse}` (gesture_detector.dart:143) — so non-mouse drags can''t reach `onDragStart`. The `selectWord` else-branch is unreachable through the current wiring. Consider removing it as part of the same cleanup pass, or extending PanGestureRecognizer to accept touch.
|
||||
|
||||
**Acceptance:**
|
||||
|
||||
- Either:
|
||||
- **A:** Tertiary tap parameters on `TerminalView` exist and fire on middle-click with `button=middle`. Regression test verifies a middle click reaches the user callback with the resolved cell offset.
|
||||
- **B:** `onTertiaryTapDown` / `onTertiaryTapUp` removed from `TerminalGestureHandler`, `TerminalGestureDetector`, and the state''s tertiary methods. Existing tests still pass.
|
||||
- The `selectWord` branch in `onDragStart` is either reachable (extend PanGestureRecognizer.supportedDevices) or removed.
|
||||
|
||||
**Surfaced from:** T-91 ui/ gesture sweep. The `onTertiaryTap*` lines (gesture_handler.dart:147-152) showed as uncovered in the lcov diff — the gestures sweep skipped writing tests for them because they''re unreachable production code.
|
||||
|
||||
**Cross-references:** T-91 (epic parent), T-93 (same shape on `onTapUp`), T-89 (coverage epic).
|
||||
', 'done', 'medium', NULL, NULL, NULL, '2026-05-08 10:48:59', '2026-05-31 11:20:21', NULL, 'e4f5f6de2aab279291c19bebe5f57224', 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-186', 'epic', NULL, 'Sidebar readers: fix message-bus open + add back/forward + pin', 'The right-side sidebar READERS — the markdown reader (builtin.markdown, lib/builtin/markdown/src/markdown_viewer.dart) and the decision reader (builtin.decisions, lib/builtin/decisions/src/decision_detail_view.dart) — are separate from the editor and open via the kernel MessageBus, the same pattern as the still-working ticket panel (lib/builtin/tickets): a click publishes (publisher, channel ''selection''); an extension activates the context-panel tab; the reader widget subscribes and renders. Two open paths are currently broken and we also want reading-navigation (back/forward) plus a single-slot pin on BOTH readers. Grouped as one set because all four tickets touch the same two reader widgets. Root-cause investigation done 2026-05-31 (see child tickets).', 'backlog', 'high', NULL, NULL, NULL, '2026-05-31 11:37:34', '2026-05-31 11:37:34', NULL, '7f69e3d9e0377bb4ed300dc537e8411d', 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-189', 'story', 'T-186', 'Back/forward navigation on the markdown & decision readers', 'Add Back/Forward buttons to both sidebar readers so you can return to what you were reading. Neither reader keeps history today: _MarkdownViewerState (markdown_viewer.dart) holds only _path/_content; _DecisionDetailViewState (decision_detail_view.dart) holds only _decision. Add a history stack + index to each, pushing on each new open; Back/Forward walk the stack and load the entry WITHOUT re-publishing a ''selection'' (in-widget navigation). For the decision reader, back/forward must not trigger the extension tab re-contribution — coordinate with the decision-open bug fix (T-188), which should stop re-contributing per selection. Custom chrome only (no Material). Acceptance: Back/Forward controls on both readers walk reading history and disable at the ends; widget tests. Sequence after the reader-open bug fixes (T-187/T-188) since it shares those widgets.', 'backlog', 'medium', NULL, NULL, NULL, '2026-05-31 11:38:36', '2026-05-31 11:38:36', NULL, 'ca447bc78eac102564ab57c097a562fb', 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-190', 'story', 'T-186', 'Pin a doc in the markdown & decision readers (single-slot quick-return)', 'Add a one-click PIN to both sidebar readers. Semantics per the reporter: a SINGLE pin slot per reader — clicking pin remembers the CURRENT doc; setting a new pin REPLACES the previous one (no list to manage); the pinned doc is always one click away to return to, so it is easy to use inline as you work. It is a quick-return bookmark, NOT a freeze-incoming toggle. Add a pinned-doc ref to _MarkdownViewerState and _DecisionDetailViewState; a pin button (set/replace) plus a jump-to-pin affordance in the reader chrome; persist for at least the session. Custom chrome only (no Material). Acceptance: pinning a doc lets you one-click return to it later; pinning another replaces it; works on both readers; widget tests. Sequence after the reader-open bug fixes (T-187/T-188); pairs naturally with back/forward (T-189).', 'backlog', 'medium', NULL, NULL, NULL, '2026-05-31 11:38:42', '2026-05-31 11:38:42', NULL, 'dc5690ae5f2916336ceb3ec4d112bf7b', 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-188', 'bug', 'T-186', 'Decision reader no longer opens on click', 'Clicking a decision (in the decisions list, or a D-ref from a ticket/markdown) no longer opens it in the decision reader. The channels are CORRECT — publishers emit (''builtin.decisions'',''selection'') and DecisionDetailView subscribes to the same (decision_detail_view.dart ~line 26). Suspected cause (confirm at fix time): DecisionsExtension.activate (decisions/src/extension.dart ~23-37) tears down and re-contributes the decisions.detail tab on EVERY selection (uncontribute then contribute with initialId), and the context-panel slot may not be surfaced (setVisible/setCollapsed not always succeeding) — unlike the still-working ticket panel, which uses a STATIC tab + activateTab + load (ticket_detail_controller.dart). Fix direction: align the decision reader with the ticket panel pattern (static tab; activateTab + load on selection; no per-click re-contribution) and ensure the context panel is revealed. Acceptance: clicking a decision anywhere reliably opens it in the decision reader, including same-decision-twice and rapid-sequential clicks; widget test.', 'in_progress', 'high', NULL, NULL, NULL, '2026-05-31 11:38:28', '2026-05-31 11:42:11', NULL, '64083356b2ba4b989b8c1e902c438316', 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-187', 'bug', 'T-186', 'Markdown reader no longer opens on click (files panel, Claude Config tab, wiki links)', 'Clicking a .md no longer opens it in the right-side markdown reader; only the pql markdown tab still works (it is the one surface that correctly publishes (''builtin.markdown'',''selection'')). Broken surfaces: the files panel (file_tree_view.dart _openFile / _FilteredFileRow, ~lines 213-222 and 284-285) and the Claude Config tab (claude_meta_sidebar.dart _configFileRow, ~553-556, shipped in T-183) both call ipc.request(''editor.open'',...) which targets the EDITOR, not the reader; the in-markdown wiki-link handler (markdown_viewer.dart _navigateToRecord) does not handle .md links; and a dead fallback subscribes to DaemonEvent kind ''editor.buffer_activated'' which the EditorRegistry never emits (it emits ''editor.active-changed''). Working pattern: publish (''builtin.markdown'',''selection'') -> the markdown extension activates the context-panel tab and bridges to channel ''load'' after mount -> MarkdownViewer renders. Fix: route .md clicks from the files panel, the Claude Config tab, and .md wiki links to publish (''builtin.markdown'',''selection''); fix or remove the dead editor-event fallback. Design note: per the reporter, clicking a .md should open the READER (non-.md files stay in the editor). Regression: files panel at 681ce3b (2026-04-22); Config tab born-broken at 494a6f1 (T-183). Acceptance: clicking a .md in the files panel, the Claude Config tab, and a wiki .md link each open it in the markdown reader; the dead fallback is gone; widget tests.', 'in_progress', 'high', NULL, NULL, NULL, '2026-05-31 11:38:20', '2026-05-31 11:42:11', NULL, '9b3f89015a2fd3d29f0ed0b34bcf369f', 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-162', 'bug', 'T-132', 'Slash typeahead omits clide-owned commands (/resume)', '/resume works when typed but doesn''t appear in the composer slash typeahead. Cause: the typeahead sources its command list from activeClaudeConfig.slashCommands (the CLI stream-json probe), which does not include ''resume'' (it''s not an in-session slash command the CLI advertises; clide owns/intercepts it). /clear appears because ''clear'' IS in the probe list. Fix: union kClideOwnedCommands (slash_commands.dart) into the typeahead''s command source — e.g. in ClaudeComposer''s default slashCommandsResolver return {...?activeClaudeConfig?.slashCommands, ...kClideOwnedCommands}. Acceptance: typing /res suggests /resume; /clear still suggested; widget test asserting clide-owned commands appear even when absent from the probe list. Follow-up to T-152/T-156.', 'in_progress', 'low', NULL, NULL, NULL, '2026-05-24 09:29:07', '2026-05-31 11:42:11', NULL, 'b50d70ae11b092f80652fb4dcf2e36b6', 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-191', 'story', 'T-186', 'Edit pencil in the reader action bar — open the current doc in the editor', 'Since clicking a .md now opens the READER (T-187), give the user a deliberate one-click way to open the SAME doc in the editor in edit mode. Add an edit pencil to the action bar of BOTH sidebar readers (markdown reader, decision reader). The pencil fires the editor path the readers moved away from for plain clicks: kernel.ipc.request(''editor.open'', {path}) on the reader''s current doc. Markdown reader: its current file path. Decision reader: the D-record''s backing file (decisions expose file_path = governance/decisions/<domain>.md via pql decisions read; resolve and open that — note it opens the whole domain file, since a decision is a section within it, unless we later add anchor support). Lives in the same reader chrome as back/forward (T-189) and pin (T-190). Custom chrome only (no Material). Acceptance: a pencil button in each reader opens the currently-shown doc in the editor; widget tests. Sequence with the other reader-chrome work (Wave B).', 'backlog', 'medium', NULL, NULL, NULL, '2026-05-31 11:58:19', '2026-05-31 11:58:19', NULL, '942200e1435cac298f011e2e3973a0c8', 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-192', 'task', NULL, 'Speed up the test gate: dedupe the a11y run + decouple coverage from the dev loop', 'The pre-push gate (make push-check) and the inner-loop make test are slow; cost is dominated by ''flutter test --coverage --exclude-tags pty'' running the whole flutter suite WITH coverage instrumentation (ci/test.sh). Two concrete levers found by reading the pipeline: (1) FREE WIN — a11y tests run TWICE in push-check: the coverage run in ci/test.sh has no path filter so it already includes test/a11y/, then ci/test_a11y.sh (''flutter test test/a11y/'') runs them again in a separate flutter invocation, chained AFTER test (so not even fast-fail). Drop test-a11y from the push-check chain (keep ''make test-a11y'' as a standalone dev target) to remove a whole redundant flutter compile+boot+run; same tests still execute under test. (2) Coverage is on the dev inner loop — make test always runs --coverage, which is only needed where coverage-gate reads lcov (push-check/CI). Split a fast no-coverage ''make test'' for the edit loop from a coverage run used by push-check/CI; the script even claims <60s warm but coverage blows past that. MEASURE FIRST (cheap): time each ci/*.sh step, check ''flutter test --concurrency'' vs nproc, and look at per-file timing for golden/alchemist tests before further changes. Acceptance: dev ''make test'' runs without coverage and is meaningfully faster; push-check no longer double-runs the a11y suite; coverage is still gated (coverage-gate unchanged, floor 95); all gates stay green; the fast-vs-coverage split is documented in the Makefile/CONTRIBUTING. Domain: tooling/CI. Raised 2026-05-31 while the push gate kept interrupting flow.
|
||||
|
||||
Add a per-test timeout to the gate''s flutter test (e.g. ci/test.sh: ''flutter test --coverage --timeout 60s''). Motivation discovered 2026-05-31: a hung pumpAndSettle has a 10-MINUTE default timeout, so a few hanging widget tests wedge make push-check for 30+ minutes — which is almost certainly why a MacBook session resorted to ''git push --no-verify'' (the gate never returned; it was not disabled, it was hung). A tight per-test timeout makes any future hang fail fast (60s) instead of wedging a pre-push, so the gate stays usable and nobody is tempted to bypass it. Pair with: keep writing pump()-bounded tests instead of pumpAndSettle() where a view has overlapping async loads (see the T-188 decision_reader_test hang).', 'backlog', 'medium', NULL, NULL, NULL, '2026-05-31 12:08:42', '2026-05-31 12:31:58', NULL, '015fe328db1b9ba7193301a809129dc6', 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);
|
||||
|
||||
@@ -128,7 +128,6 @@ You might also want, project-permitting:
|
||||
- [Q-3: Event persistence + audit/undo](questions/architecture.md#q-3-event-persistence--auditundo) — _architecture_
|
||||
- [Q-4: `.canvas` schema compatibility with Obsidian](questions/architecture.md#q-4-canvas-schema-compatibility-with-obsidian) — _architecture_
|
||||
- [Q-5: IPC wire-format stability + `schema_version:`](questions/architecture.md#q-5-ipc-wire-format-stability--schema-version) — _architecture_
|
||||
- [Q-6: Window chrome — native frame vs frameless custom](questions/architecture.md#q-6-window-chrome--native-frame-vs-frameless-custom) — _architecture_
|
||||
- [Q-7: macOS app bundle signing / notarisation](questions/architecture.md#q-7-macos-app-bundle-signing--notarisation) — _architecture_
|
||||
- [Q-8: Extension API shape — widgets, subcommands, both?](questions/extensions.md#q-8-extension-api-shape--widgets-subcommands-both) — _extensions_
|
||||
- [Q-9: Lua runtime vendoring](questions/extensions.md#q-9-lua-runtime-vendoring) — _extensions_
|
||||
@@ -141,10 +140,7 @@ You might also want, project-permitting:
|
||||
- [Q-16: `tree-sitter-dart` grammar maintenance](questions/process.md#q-16-tree-sitter-dart-grammar-maintenance) — _process_
|
||||
- [Q-17: Icon set growth](questions/process.md#q-17-icon-set-growth) — _process_
|
||||
- [Q-18: Theme hot-reload in release builds](questions/process.md#q-18-theme-hot-reload-in-release-builds) — _process_
|
||||
- [Q-19: (withdrawn)](questions/process.md#q-19-withdrawn) — _process_
|
||||
- [Q-20: Kernel DB service — namespaced SQL access?](questions/process.md#q-20-kernel-db-service--namespaced-sql-access) — _process_
|
||||
- [Q-21: Pql absorbs planning vs keeps separate](questions/architecture.md#q-21-pql-absorbs-planning-vs-keeps-separate) — _architecture_
|
||||
- [Q-22: Ticket persistence strategy](questions/architecture.md#q-22-ticket-persistence-strategy) — _architecture_
|
||||
- [Q-23: SSH-remote development — run clide against a remote workspace](questions/architecture.md#q-23-ssh-remote-development--run-clide-against-a-remote-workspace) — _architecture_
|
||||
- [Q-25: Body text face — mono everywhere vs Josefin Sans UI + mono code](questions/architecture.md#q-25-body-text-face--mono-everywhere-vs-josefin-sans-ui--mono-code) — _architecture_
|
||||
- [Q-26: Small screen layout (< 1000px)](questions/architecture.md#q-26-small-screen-layout--1000px) — _architecture_
|
||||
@@ -156,6 +152,13 @@ You might also want, project-permitting:
|
||||
- [Q-32: MCP tool surface — minimum slash-ide or extended clide tools?](questions/architecture.md#q-32-mcp-tool-surface--minimum-slash-ide-or-extended-clide-tools) — _architecture_
|
||||
- [Q-33: MCP transport — SSE, WebSocket, stdio, or all?](questions/architecture.md#q-33-mcp-transport--sse-websocket-stdio-or-all) — _architecture_
|
||||
|
||||
## Resolved questions
|
||||
|
||||
- [Q-6: Window chrome — native frame vs frameless custom](questions/architecture.md#q-6-window-chrome--native-frame-vs-frameless-custom) — _architecture_
|
||||
- [Q-19: (withdrawn)](questions/process.md#q-19-withdrawn) — _process_
|
||||
- [Q-21: Pql absorbs planning vs keeps separate](questions/architecture.md#q-21-pql-absorbs-planning-vs-keeps-separate) — _architecture_
|
||||
- [Q-22: Ticket persistence strategy](questions/architecture.md#q-22-ticket-persistence-strategy) — _architecture_
|
||||
|
||||
## Rejected
|
||||
|
||||
- [R-2: Go sidecar](rejected/architecture.md#r-2-go-sidecar) — _architecture_
|
||||
|
||||
Reference in New Issue
Block a user