pre-push: skip the test suite unless lib/ or pubspec changed (T-348)

The hook ran the full ~2min push-check on every push, even one touching
only docs, changelog, pql data, tests, or assets. Diff the pushed range
(from the hook's stdin) and run the full gate only when lib/ (app/runtime
source) or pubspec.* (deps/version) changed; otherwise run just the
instant decisions + changelog gates.

Other changes ride along with a lib change in practice, the full suite
stays available via `make push-check`, and the release CI runs it forced
on a tagged version. A state we can't classify (unfetched remote sha, new
branch) falls back to the full gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-10 19:22:12 +02:00
co-authored by Claude Opus 4.8
parent b0f2580150
commit b7e0835b74
4 changed files with 55 additions and 2 deletions
@@ -3508,3 +3508,4 @@ 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 ('06FB2T11GCV1EV07DYD5BZENTM', 'status', 'backlog', 'ready', NULL, '2026-06-10 16:22:37', '2026-06-10 16:22:37', '2026-06-10 16:22:37', NULL, 'c62c5ac18a88ba763b5194f89a2a7482', 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 ('06FB4RD1DDSYM4J7WYEGTXARB4', 'status', 'backlog', 'done', NULL, '2026-06-10 16:34:51', '2026-06-10 16:34:51', '2026-06-10 16:34:51', NULL, '56cde33409eb796ad4fb420ed3033c70', 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 ('06FB4XCM5KBXDDSCWJ37GPYG3R', 'status', 'backlog', 'done', NULL, '2026-06-10 16:57:07', '2026-06-10 16:57:07', '2026-06-10 16:57:07', NULL, '1ce291d54831d3ede687384037c379ff', 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 ('06FB50YE6S6YWNP2ZSFWES9B2W', 'status', 'backlog', 'done', NULL, '2026-06-10 17:13:53', '2026-06-10 17:13:53', '2026-06-10 17:13:53', NULL, '87b069d3f25c91622c9720147d359360', 2) ON CONFLICT(hash) DO NOTHING;
+1
View File
@@ -172,3 +172,4 @@ 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 ('06FB4RD1DDSYM4J7WYEGTXARB4', 'T-345', '2026-06-10 16:33:23', '2026-06-10 16:33:23', NULL, '9f26d5036c05057d4bd0fc53ddaddafd', 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 ('06FB4VG3N3YJSV8G7M1HFSYW2W', 'T-346', '2026-06-10 16:46:54', '2026-06-10 16:46:54', NULL, 'a64940cb0b4ec4fb489eac27065dc447', 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 ('06FB4XCM5KBXDDSCWJ37GPYG3R', 'T-347', '2026-06-10 16:55:10', '2026-06-10 16:55:10', NULL, '9d40226dbc6136072d2d5d0eda71f141', 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 ('06FB50YE6S6YWNP2ZSFWES9B2W', 'T-348', '2026-06-10 17:10:42', '2026-06-10 17:10:42', NULL, '8bb5ad92551f272417840869a0774668', 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);
+6
View File
@@ -3197,3 +3197,9 @@ INSERT INTO tickets (record_id, type, parent_record_id, title, description, stat
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);
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 ('06FB50YE6S6YWNP2ZSFWES9B2W', 'task', NULL, 'Pre-push gate: skip the test suite for docs/changelog/pql/meta-only pushes', 'The .githooks/pre-push hook runs ''make push-check'' unconditionally — the full ~2min coverage + test-core suite even when a push touches only documentation, the changelog, pql ticket data, or other meta files that cannot affect the Flutter/Dart build or tests.
Make the hook path-aware: diff the commits being pushed (remote_sha..local_sha from the hook''s stdin). If every changed file is under an allowlist that can''t affect tests — docs/, governance/, .pql/, .claude/, CHANGELOG.md, README.md, CLAUDE.md — run only the instant gates (decisions-validate + changelog-gate) and skip test-coverage/coverage-gate/test-core. Any code-ish path (lib/, test/, assets/, pubspec.*, native/, ci/, .githooks/, Makefile, platform dirs) → full gate. Fail safe: unknown/new-branch states run the full gate.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-10 17:10:42', '2026-06-10 17:10:42', NULL, 'edb52a1ac5c6a0e01ebaaf5ceff5e96c', 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 ('06FB50YE6S6YWNP2ZSFWES9B2W', 'task', NULL, 'Pre-push gate: skip the test suite for docs/changelog/pql/meta-only pushes', 'The .githooks/pre-push hook runs ''make push-check'' unconditionally — the full ~2min coverage + test-core suite even when a push touches only documentation, the changelog, pql ticket data, or other meta files that cannot affect the Flutter/Dart build or tests.
Make the hook path-aware: diff the commits being pushed (remote_sha..local_sha from the hook''s stdin). If every changed file is under an allowlist that can''t affect tests — docs/, governance/, .pql/, .claude/, CHANGELOG.md, README.md, CLAUDE.md — run only the instant gates (decisions-validate + changelog-gate) and skip test-coverage/coverage-gate/test-core. Any code-ish path (lib/, test/, assets/, pubspec.*, native/, ci/, .githooks/, Makefile, platform dirs) → full gate. Fail safe: unknown/new-branch states run the full gate.', 'done', 'medium', NULL, NULL, NULL, '2026-06-10 17:10:42', '2026-06-10 17:13:53', NULL, 'f846b01b35bda1b8e247f360c46d472f', 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);