Skip to content

Wave 18: privacy-gate prefilter, handback hold resets, semgrep partial coverage rows - #2171

Merged
remigiusz-antczak merged 1 commit into
mainfrom
land/wave-18
Oct 31, 2026
Merged

remigiusz-antczak merged 1 commit into
mainfrom
land/wave-18

Conversation

@remigiusz-antczak

Copy link
Copy Markdown
Collaborator

Summary

3 gate fixes, each pinned by a new or extended test.

  • Privacy gate: one combined grep over all patterns runs first, so a clean tree is read once, not once per pattern. Hits and per-pattern attribution are unchanged; a prefilter error fails closed.
  • handback_cap: a hold resets when its condition clears, so a later episode in the same lane is no longer released at once.
  • review_checks: a partial semgrep scan lists the files it could not fully read as not-checked rows, left out of the findings count.

Also fixes the review's fix-first item: two chunks with equal error counts no longer share one row.

Verification

Run on this head:

  • New semgrep partial test 48/48 (25/48 against the previous script); handback_cap selftest 117/117.
  • run-ci-tests.sh --affected: 68 of 69 selected suites pass (65 run one at a time after the runner's fail-fast stop). test-ci-gates.sh: 303 pass, 8 fail, the same counts as on base: sandbox-blocked process checks plus one load-sensitive case that passes alone. CI runs them on ubuntu.
  • Changelog fragments 23/23, size ratchet ok, privacy gate clean (rc 0).

🤖 Generated with Claude Code

…l coverage rows

Privacy gate: one-pass prefilter. The gate ran one grep per banlist pattern over every file, so a clean
tree was read once per pattern. It now first runs a single `grep -IlE -D skip -f` over all patterns at
once (same flags, same 1000-file batches), and the per-pattern greps read only the files that pass. The
union of the patterns lists a superset of every single pattern's matches, so per-pattern attribution and
the hit set are unchanged. The empty-input ERE probe still runs first, hits are still reported with
their content withheld, and a prefilter error fails closed. A tree holding a path with a newline in its
name skips the prefilter and falls back to the full per-pattern scan. New
scripts/test-privacy-prefilter.sh pins the hit set against an independent one-grep-per-pattern oracle,
the fail-closed paths and the newline-name fallback.

handback_cap: holds reset when their condition clears. The push/commit, background-work and
dirty-worktree holds kept the first block's time and nothing removed it, so after one block older than
the window a later episode in the same lane was released at once. check() now evaluates all three
checks before it blocks and releases each hold whose check found no such condition; a check that could
not run keeps its hold, and a condition that stays live past the window is still released. The
background-work text no longer claims the lane owns every process in its worktree: it says to wait for
the pid or stop it if this lane started it. A known limit is pinned: ps prints argv unquoted, so a
space in a -c value or -C path makes that push or commit go unheld. Selftest 83 to 117 cases.

review_checks: a partial semgrep scan names the files it could not fully read. A semgrep chunk with
errors and some clean files now adds one not-checked row per errored path (at most 20 per call, then
one summary row that names the first unlisted path, so two chunks with the same error count keep
separate rows), and the partial line on stderr keeps its exact prefix and ends with the counts:
"(N error(s) on M of S scanned file(s): <type> (<level>) xK, ...; see not-checked rows)". The
partial or not-run decision is made on the findings alone, before these rows are added, so the not-run
cases are unchanged. A warn-level parse error still makes the scan partial. The closing "N findings"
summary no longer counts not-checked rows; a separate "K not-checked row(s)" line follows when there
are any. New scripts/test-review-checks-semgrep-partial.sh (48 cases, 25/48 on the previous script).

Tests: run-ci-tests.sh --affected selected 69 suites on this tree. It stops at its first failing
suite, so the 65 after test-ci-gates.sh were run one at a time: 65/65 pass (including
test-privacy-prefilter 7/7 and test-review-checks-semgrep-partial 48/48, 25/48 on the previous
script), as do the 3 before it. test-ci-gates.sh: 303 pass, 8 fail, 2 sandbox skips here, and 303/8/2 on the base
tree 9d222d0 too: 7 shared process-liveness checks that need ps/pgrep, which this sandbox denies,
plus one load-sensitive case on each side that passes when run alone (delivery friction 16/16 on
this tree). CI runs those on ubuntu. handback_cap --selftest 117/117. Changelog fragments 23/23,
size ratchet ok, full privacy gate rc 0.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@remigiusz-antczak
remigiusz-antczak merged commit c2ba198 into main Oct 31, 2026
11 checks passed
@remigiusz-antczak
remigiusz-antczak deleted the land/wave-18 branch October 31, 2026 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant