Skip to content

gate: an unchecked file is not a clean file - #296

Open
EdbertChan wants to merge 1 commit into
stack/EdbertChan/reflect/ui-input-guard-hook-freshness-20260908/catch-concession-user-found-miss--5b8f852afrom
stack/EdbertChan/reflect/ui-input-guard-hook-freshness-20260908/unchecked-file-clean-file--fa24ac4d
Open

gate: an unchecked file is not a clean file#296
EdbertChan wants to merge 1 commit into
stack/EdbertChan/reflect/ui-input-guard-hook-freshness-20260908/catch-concession-user-found-miss--5b8f852afrom
stack/EdbertChan/reflect/ui-input-guard-hook-freshness-20260908/unchecked-file-clean-file--fa24ac4d

Conversation

@EdbertChan

@EdbertChanEdbertChan commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Summary

A detector that opens a file has three possible outcomes, not two: it found the thing, it did not find the thing, or it could not read the input at all. Collapsing the third into the second is how a guard reports an unchecked file as clean.

That is not hypothetical. The first version of ui-input-guard in this stack skipped any wrapper script over 64 KB and any path holding an unresolved shell variable, and returned "clean" for both. The user caught it in review with "why would you submit a rule or principle that would ignore files straight up".

check_hook_test_coverage now requires any file-reading detector to carry a test that pins its unreadable-input behavior. Fail open or fail closed remains the hook's own documented choice; leaving it untested does not.

scope-lock was the single real gap the new rule found across 23 hooks. Its two reads resolve in opposite directions on purpose: a corrupt state file means no lock is in force, while an unreadable transcript means no scope contract was recorded, so an existing lock is not released by a file that could not be read. Both are now asserted.

Review Claim

A file-reading hook detector cannot land without a test pinning what it does with input it could not read.

Review Lane

behavior

Review Unit

tooling-policy

Safety Invariant

The gate only adds a third requirement alongside the existing positive and negative ones, and only for detectors whose source opens or sizes a file. An inline-only detector is unaffected, a missing or unreadable detect.py makes the new check answer no rather than raise, and the accepted test names include the fail-open vocabulary already in use, so no existing hook had to change its behavior to pass. One scope-lock test file gained assertions; no detector logic changed.

Slice Rationale

The general rule and its enforcement are separable from the hook that motivated them, and this slice is the one a future detector actually collides with.

Non-goals

Does not decide direction for anyone: the gate never asserts that a given hook must fail closed. Does not inspect what a test body proves, only that a test named for the unreadable case exists. Does not extend the same rule to skills or scripts outside engine/hooks/.

Test Plan

Test Plan
  • python3 -m unittest discover -s tests -p "test_check_hook_test_coverage.py" — 8 tests, OK (fires on a file-reading detector with no unreadable test, silent once one exists, silent for an inline-only detector, and asserts the real repo passes)
  • python3 -m unittest discover -s engine/hooks/scope-lock/tests — 35 tests, OK (4 new)
  • python3 scripts/check_hook_test_coverage.py — OK (23 hooks)
  • python3 scripts/check_no_dated_provenance.py --base origin/main — ok
  • python3 scripts/check_codify_has_code.py --base origin/main — ok

Revert Plan

Revert Plan
  • Safe to revert? Yes
  • Revert command: git revert <sha>
  • Post-revert steps: None
  • Data migration? No

🤖 Generated with Claude Code

https://claude.ai/code/session_01KU2pPKob4MJ1NqjsfTNyYJ

@cursor

cursorBot commented Sep 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_d0f306f0-20dc-4761-af99-ba40311edccb)

@EdbertChan

EdbertChan commented Sep 9, 2026

Copy link
Copy Markdown
OwnerAuthor

This pull request is part of a Mergify stack:

#Pull RequestLink
1hook: hook-freshness warns when the checkout behind the hooks is stale#290
2hook: ui-input-guard blocks synthetic input at the user's live session#291
3docs: prove UI work on a disposable surface, not the user's session#292
4hook(wrong-check-reflect): catch a concession that the user found the miss#298
5gate: an unchecked file is not a clean file#296👈

A detector that opens a file has a third outcome besides hit and clean:
input it could not read. A size cap that silently skips anything larger
reports an unchecked file as clean, which is the opposite of what a guard
is for.
check_hook_test_coverage now requires any file-reading detector to have a
test that pins its unreadable-input behavior. Fail open or fail closed stays
the hook's own documented choice; leaving it untested does not. scope-lock
was the one real gap the new rule found: its state file fails open and its
transcript read fails closed, both now asserted.
The evidence rules gain the general form, grounded in Saltzer and
Schroeder's fail-safe defaults.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KU2pPKob4MJ1NqjsfTNyYJ
Change-Id: Ifa24ac4d096e44be20c30733c5beea8d9218e578
@EdbertChan
EdbertChan changed the base branch from stack/EdbertChan/reflect/ui-input-guard-hook-freshness-20260908/wire-ui-input-guard-hook-freshness-inventories--09cebee8 to mainSeptember 9, 2026 06:22
@EdbertChan
EdbertChanforce-pushed the stack/EdbertChan/reflect/ui-input-guard-hook-freshness-20260908/unchecked-file-clean-file--fa24ac4d branch from c43becf to 4b02d65CompareSeptember 9, 2026 06:22
@EdbertChan
EdbertChan changed the base branch from main to stack/EdbertChan/reflect/ui-input-guard-hook-freshness-20260908/catch-concession-user-found-miss--5b8f852aSeptember 9, 2026 06:22
@cursor

cursorBot commented Sep 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_14422852-611f-44c2-bda6-5e13feeb7f13)

@EdbertChan

Copy link
Copy Markdown
OwnerAuthor

Revision history

#TypeChangesReasonDate
1initialc43becf2026-09-09 06:22 UTC
2rebasec43becf → 4b02d65(rebase only)2026-09-09 06:22 UTC

Sign up for freeto 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

@EdbertChan