Repository navigation
tech-debt(guards): the exec-bit baseline cannot detect an entry that outlived its fix, and its tests broke when the backlog hit zero #15762
Description
Activity
- added 4 commits that reference this issue
on Sep 5, 2026 Audit of the first acceptance criterion — asking the same question of the repo's other shrink-only baselines. Read-only; no change proposed here.
A generic staleness guard already exists, and it catches a different shape
repo_tests/stranded_recorder_entries_test.py(#15566) discovers 34 Python ledgers automatically — fromKNOWN_LARGE's 499 rows to three-entry lint allowlists — plus registered text/JSON baselines, and fails on entries the tree no longer holds.It does not catch this issue's defect, and it says so itself:
The recorded path is not in the tracked tree and not on disk. Nothing weaker: a count that no longer matches or a name that no longer resolves are the same class, but they are per-recorder semantics, and a guard that tried to know all of them would know none of them well.
That is a deliberate, correct scoping decision, and it means the two shapes need to be named separately:
Detected by Example Stranded — the recorded path no longer exists stranded_recorder_entries_test.pya baselined file that was deleted or moved Outlived — the path exists but no longer describes a violation nothing tools/lint/check_no_blocking_io_in_async.py, executable on base while still listed as dormantSo this issue is not a gap in #15566; it is the per-recorder half that #15566 declined to guess at. The check has to be written per recorder, and the exec-bit baseline is the first instance.
The escalation: on a tolerance list, an outlived entry is an open door
I filed this as tidiness. It is worse than that, and the distinction is what a recorder is for:
- A record with an outlived entry overstates a backlog. Misleading, not dangerous.
- A tolerance list with an outlived entry silently exempts that path forever.
_KNOWN_DORMANTis the second kind:(known if target in _KNOWN_DORMANT else blocking). A listed path never blocks. So ifcheck_no_blocking_io_in_async.pyhad lost its exec bit again after being fixed, the guard would have classified the fresh violation as "known dormant and tracked in #14181" and passed — a genuine regression, on a path already fixed once, permanently invisible.That risk is gone for this list because it is now empty. The shape is not: every tolerance-shaped ledger in the repo has it, and
stranded_recorder_entries_test.pycannot see any of them, because the exempted path still exists — that is the whole point of it being exempted.Revised acceptance criteria
- Distinguish record ledgers from tolerance ledgers, and treat the second as the priority — an outlived record misinforms, an outlived tolerance suppresses
- For each tolerance ledger, a per-recorder check that every entry is still an actual violation.
core_router_auth_guard_test.py'stest_every_recorded_exemption_is_still_ungatedis the working model: it fired the moment security(auth): cognition-store seed's admin check never runs -- missing Depends() #15759's gate landed and forced the entry's removal in the same change - Enumerate the tolerance ledgers rather than fixing them one at a time. Candidates seen so far:
_KNOWN_DORMANT(fixed),_KNOWN_REPO_VIOLATIONS(no-print-console),env_var_bare_cast_allowlist,python_filter_uncovered_reads. test(guard): an unchecked scope box whose artefact already exists in the tree is a detectable contradiction #15566's discovery pass already finds 34 ledgers — the tolerance subset can be derived from it rather than hand-listed - Every such check's fixture must be synthetic, because a tolerance list that is doing its job trends to empty — which is exactly how three tests broke when fix(lint): tools/lint/check_no_local_schemas.py lost its executable bit, blocking the no-local-schemas pre-commit hook #15750 emptied this one
Related
- test(guard): an unchecked scope box whose artefact already exists in the tree is a detectable contradiction #15566 — the stranded-entry guard, and the scoping decision that leaves this half open
- security(auth): ten registered routers have no authentication, six of them exposing write operations #15745 /
core_router_auth_guard_test.py— the shrink-side check that works, as a model
Re-verification against current
origin/main(2026-09-20). Tracked branchissue-15743-changepwis already gone from origin.Confirmed unimplemented — 0 of 3 ACs:
- A test asserting every
_KNOWN_DORMANTentry is still an actual violation (not just still configured as a hook) — checkedpipeline-scripts/check_hook_exec_bits_test.py's full test list;test_the_dormant_baseline_has_no_stale_entriesandtest_the_staleness_check_would_catch_a_dead_entryexist, but per this issue's own description these ask "is it still some hook's entry", not "is it still executable" — no new test matches the gap._KNOWN_DORMANTis currently empty (confirmed, per fix(auth): change-password gates on caller identity, closing the account-takeover path #15752), so there's nothing live to check against right now, but the missing mechanism itself wasn't added either — a synthetic fixture could still exercise it. - The same shrink-side check for the other named shrink-only baselines (
hardcoded_values_baseline.txt, the file-size ratchet pair) — no matching test found in either area. - A documented convention that a guard's own test fixtures must be synthetic, never the live baseline, for any guard whose backlog can reach zero — searched
docs/developer/*.mdand the guard's own test file for this rule; not found.
Nothing here contradicts the issue's own "Fixed in #15752" section (which I did not re-verify, since it's explicitly marked already done) — this comment covers only the three items the issue itself lists as NOT yet fixed. No branch exists to build on. Leaving open.
- A test asserting every
Found while fixing a CI red on #15752, which #15750's exec-bit restoration caused.
Two defects, one root
pipeline-scripts/check_hook_exec_bits.pykeeps a shrink-only baseline,_KNOWN_DORMANT, and states the rule in its own comment: "This list only ever shrinks. A hook comes off it in the same change that fixes its violations and flips its exec bit."1. The guard cannot detect a stale entry.
tools/lint/check_no_blocking_io_in_async.pywas executable onDev_new_gui(mode100755) while still listed as dormant. The staleness test that exists —test_the_dormant_baseline_has_no_stale_entries— asks whether a baselined path is still some hook's entry, which it was. Nothing asks whether it is still a violation. So an entry survives its own fix indefinitely, and the baseline overstates the backlog with no signal.2. Two of the guard's own tests used the live baseline as their fixture, so finishing the backlog broke them:
test_a_known_dormant_entry_is_reported_but_not_blockingdidnext(iter(guard._KNOWN_DORMANT))—StopIterationon an empty baseline.test_running_from_a_subdirectory_does_not_report_cleanassertedknownwas non-empty, which held only while the repository still carried a violation to classify.#15750 restored the exec bit on
tools/lint/check_no_local_schemas.py— the last live entry. The baseline emptied, and both tests failed. Not because the guard regressed, but because it succeeded. A guard whose tests stop working when its backlog reaches zero punishes finishing the work, and the cheapest way to make CI green again would have been to re-break the exec bit.Fixed in #15752, and what is left
Both tests now use synthetic fixtures (monkeypatched
_KNOWN_DORMANT, fabricated mode maps), so they assert the guard's actual properties whether or not a backlog exists. The CWD test asserts both directions — anchored run classifies, CWD-relative run loses it — and is mutation-checked: breaking the root anchoring fails it._KNOWN_DORMANTis now empty, both entries removed: one because this change fixed it, one because it had been fixed earlier and never recorded.What is not fixed, and is this issue:
_KNOWN_DORMANTentry is still an actual violation, so an entry cannot outlive its fix. This is the shrink-side check the existing staleness test does not performhardcoded_values_baseline.txt, the file-size ratchet pair — since "entry that no longer describes a violation" is a shape, not an instanceRelated
_KNOWN_DORMANTtracked, now empty