Fix flaky [skip <check>] detection in ci_skip_requested (grep -q SIGPIPE under pipefail)
### Problem to Solve The `ci_skip_requested` helper in `scripts/ci-skip-utils.sh:38` can spuriously fail to detect a `[skip <check-name>]` tag in commit messages, blocking otherwise-valid commits at the pre-commit hook stage. The line pipes `git log ... --format=%B` into `grep -qF "${tag}"` under `set -o pipefail`. `grep -q` exits as soon as it finds the first match and closes the pipe, which SIGPIPEs `git log` (exit 141). With `pipefail`, the pipeline takes that non-zero exit, so the `&& return 0` never runs and the helper falls through to `return 1` — i.e. the skip tag is present but reported as absent. It is timing-dependent (only triggers when `grep -q` short-circuits before `git log` finishes), so it manifests as a flaky local hook failure on large histories. Hit on `gitlab-org/orbit/knowledge-graph!1592`: an ETL-only change (`config/ontology/`) with `[skip schema-version-check]` in both the MR description and a commit message still failed the local `schema-version-check` lefthook, forcing a `--no-verify` commit. CI was unaffected because it reads `CI_MERGE_REQUEST_DESCRIPTION` first. ### Proposed Solution Make the `git log | grep` pipeline in `ci_skip_requested` tolerant of the SIGPIPE/early-exit. Any of: - Don't short-circuit the producer: `git log ... --format=%B 2>/dev/null | grep -cF "${tag}"` and test the count, or - Buffer first: capture to a var (`local msgs; msgs=$(git log ...)`) then `grep -qF`, or - Neutralize the producer's exit: `{ git log ... || true; } | grep -qF`. Validation: this is shell-only. Reproduce by committing an `config/ontology/` change with `[skip schema-version-check]` in the commit message and confirming the hook now passes; `bash scripts/check-schema-version.sh origin/main` should exit 0. <details> <summary><b>Agent context</b> — extended analysis, alternatives considered, related-code dumps</summary> **Buggy line** (`scripts/ci-skip-utils.sh:38`): ```bash git log "${BASE_REF}"...HEAD --format=%B 2>/dev/null | grep -qF "${tag}" && return 0 ``` **Why it's flaky, not always-broken:** `grep -q` returns 0 and stops reading on the first match. If `git log` has already finished writing (small history) the producer exits 0 and pipefail is happy. On a large history `git log` is still streaming when `grep -q` closes the read end → `git log` gets SIGPIPE (141) → with `set -o pipefail` the pipeline exits 141 → `&& return 0` is skipped → function returns 1 at line 41. **Observed on !1592:** - The tag was provably in range: `git log origin/main...HEAD --format=%B | grep -cF '[skip schema-version-check]'` → `1`. - The exact `grep -qF` pipe returned 0 when run standalone, but `bash -x scripts/check-schema-version.sh origin/main` traced `+ git log ... | grep -qF ... ` → `+ return 1`. - The non-`-q` consuming variants (`grep -cF`, fully unwrapped `git`/`grep`) all matched; only the short-circuiting `-q` form under pipefail failed. **Callers / blast radius:** `ci_skip_requested` is the shared skip detector sourced by the version-check scripts (e.g. `scripts/check-schema-version.sh`, and any sibling `[skip ...]` check using the same util). The fix is in one place and benefits all of them. CI is mostly unaffected because lines 26/29 (`CI_MERGE_REQUEST_DESCRIPTION` / `CI_MERGE_REQUEST_TITLE`) usually match before reaching the `git log` fallback, but the fallback (line 31-39) exists precisely for stale-description cases and should be reliable. **Difficulty:** L0 — single shell file, no Rust, no server. Validatable with `bash scripts/check-schema-version.sh origin/main`. </details>
issue