|
|
|
@@ -3174,3 +3174,26 @@ Fix: give each run its own coverage output via flutter test --coverage-path <tmp
|
|
|
|
|
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 ('06FB4RD1DDSYM4J7WYEGTXARB4', 'task', NULL, 'Make the coverage harness concurrency-safe (per-run paths)', 'ci/test.sh --coverage runs two flutter test --coverage passes that both write the fixed coverage/lcov.info, copies it to coverage/lcov.parallel.info, merges, then rm -f''s the intermediate. Any concurrent flutter test --coverage (a second push gate, or a ''make test'' during a push) races on those shared paths — the second run''s rm -f deletes lcov.parallel.info mid-merge, crashing merge_lcov.py with FileNotFoundError (observed during a push, 2026-06-10).
|
|
|
|
|
|
|
|
|
|
Fix: give each run its own coverage output via flutter test --coverage-path <tmp>, with a per-run mktemp dir for the two passes + the merge; only the final merged result lands in coverage/lcov.info via an atomic rename within coverage/. No shared intermediate paths, so concurrent runs can''t corrupt each other.', 'done', 'medium', NULL, NULL, NULL, '2026-06-10 16:33:23', '2026-06-10 16:34:51', NULL, '75938b68f10edf857e25100141d08544', 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 ('06FB4VG3N3YJSV8G7M1HFSYW2W', 'task', NULL, 'Profile and speed up the push-check gate', 'The push gate (make push-check) is dominated by ''flutter test --coverage'' (coverage instrumentation ~doubles flutter-test wall-time vs the ~20s no-coverage ''make test''). Recent slowness was traced to concurrent-session contention (fixed by T-345), not suite bloat — but there is real speedup headroom.
|
|
|
|
|
|
|
|
|
|
Findings (2026-06-10):
|
|
|
|
|
- 245 test files; the 39 Flutter-free core files (test/ipc, daemon, git, panes, files, editor, pql) run TWICE in the gate: under flutter test --coverage (for the coverage floor) AND under dart test (test-core, the Flutter-free contract guard). Each serves a purpose but it is the clearest redundancy.
|
|
|
|
|
- 33 test files use pumpAndSettle (ci/test.sh''s own comment warns against it; prefer the pumpAsync helper) — a common wall-time/hang sink.
|
|
|
|
|
- 47 ''Duration(seconds:)'' occurrences in tests; some are legit timeouts, some are real-time waits that add wall-clock.
|
|
|
|
|
|
|
|
|
|
Scope:
|
|
|
|
|
1. Profile: one timed run (JSON reporter / --reporter) to rank the ~20 slowest tests; the pumpAndSettle + Duration(seconds:) files are prime suspects.
|
|
|
|
|
2. Fix the genuinely slow ones (bounded pumps, fake-async, no real sleeps) per feedback_tests_run_light + feedback_runasync_for_io.
|
|
|
|
|
3. Investigate collapsing the core double-run — collect coverage from the dart test core pass and drop those 39 files from the flutter --coverage pass — only if the profile shows that slice is large enough to justify the refactor.
|
|
|
|
|
|
|
|
|
|
Do NOT cut tests for speed: 245 files for a public tool with a 95% floor is comprehensive, not over-tested. Make slow tests fast instead.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-10 16:46:54', '2026-06-10 16:46:54', NULL, '481a097650e0b1badea0b24cdf48afda', 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 ('06FB4XCM5KBXDDSCWJ37GPYG3R', 'bug', NULL, 'pql pane fails in desktop-launched clide: PATH not expanded on Linux', 'The pql sidebar pane (and any PATH-resolved tool) fails when clide is launched from a desktop launcher rather than a terminal. lib/kernel/src/toolchain_paths.dart _expandedPath() augments PATH with ~/.local/bin + /usr/local/bin etc. ONLY on macOS (line: ''if (!Platform.isMacOS) return base;''). On Linux it uses the raw inherited PATH.
|
|
|
|
|
|
|
|
|
|
A GUI/desktop-launched app inherits a minimal PATH (e.g. /usr/bin:/bin) with no ~/.local/bin, so _findOnPath(''pql'') returns null, clide falls back to spawning the literal ''pql'', and Process.start fails with ENOENT — the pql pane errors. pql is installed to ~/.local/bin. Reproduced: ''env -i PATH=/usr/bin:/bin command -v pql'' → not found. Works under ''make run'' only because the terminal PATH includes ~/.local/bin.
|
|
|
|
|
|
|
|
|
|
Fix: extend _expandedPath() to also augment on Linux — prepend ~/.local/bin and /usr/local/bin (keep the homebrew dirs macOS-only). Affects pql, tmux, and PATH-resolved git alike. User running the installed build needs a rebuild+reinstall after the fix; immediate workaround is launching clide from a terminal.', 'backlog', 'high', NULL, NULL, NULL, '2026-06-10 16:55:10', '2026-06-10 16:55:10', NULL, '4a647a5c33b044df6ace163651fc8e93', 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 ('06FB4XCM5KBXDDSCWJ37GPYG3R', 'bug', NULL, 'pql pane fails in desktop-launched clide: PATH not expanded on Linux', 'The pql sidebar pane (and any PATH-resolved tool) fails when clide is launched from a desktop launcher rather than a terminal. lib/kernel/src/toolchain_paths.dart _expandedPath() augments PATH with ~/.local/bin + /usr/local/bin etc. ONLY on macOS (line: ''if (!Platform.isMacOS) return base;''). On Linux it uses the raw inherited PATH.
|
|
|
|
|
|
|
|
|
|
A GUI/desktop-launched app inherits a minimal PATH (e.g. /usr/bin:/bin) with no ~/.local/bin, so _findOnPath(''pql'') returns null, clide falls back to spawning the literal ''pql'', and Process.start fails with ENOENT — the pql pane errors. pql is installed to ~/.local/bin. Reproduced: ''env -i PATH=/usr/bin:/bin command -v pql'' → not found. Works under ''make run'' only because the terminal PATH includes ~/.local/bin.
|
|
|
|
|
|
|
|
|
|
Fix: extend _expandedPath() to also augment on Linux — prepend ~/.local/bin and /usr/local/bin (keep the homebrew dirs macOS-only). Affects pql, tmux, and PATH-resolved git alike. User running the installed build needs a rebuild+reinstall after the fix; immediate workaround is launching clide from a terminal.', 'done', 'high', NULL, NULL, NULL, '2026-06-10 16:55:10', '2026-06-10 16:57:07', NULL, '98d93fef85789907f6bf6efc52a3fcdb', 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);
|
|
|
|
|