Skip to content

docs(review): a new gate makes existing tests fail like a stale expectation (#17054) - #17396

Merged
mrveiss merged 1 commit into
mainfrom
docs-review-gate-pattern
Sep 24, 2026
Merged

mrveiss merged 1 commit into
mainfrom
docs-review-gate-pattern

Conversation

@mrveiss

@mrveiss mrveiss commented Sep 24, 2026

Copy link
Copy Markdown
Owner

Thinking Path

Three test fixtures in one PR (#17054) failed for the same reason, and twice the repair I suggested would have deleted the coverage it appeared to fix. That is worth a line in the self-review list, because the failure is indistinguishable in a CI log from ordinary expectation drift.

A change adds an authorization gate upstream. Every test whose fixture predates it now short-circuits before reaching its own subject. The log says assert <new> == <old> with a plausible new value, so the obvious move is to update the assertion — which goes green and removes the test's real subject.

I made this mistake twice in one afternoon from the reviewing seat:

  • I read assert 1008 == 1011 as a corrected close code (1008 Policy Violation being right for an authz refusal where 1011 Internal Error was wrong) and advised updating it with a comment. Wrong: the tests patched authenticate_websocket to return a user with no role, so the gate refused before the handshake ran. 1011 was never a changed code, it was a code no longer reached. Re-pinning would have made both tests assert authz — already covered by the gate's own suite — and removed the only coverage of the handshake-failure path.
  • A third file, role: "user", stopped reaching accept() at all. Fixing only its fixture would have left the gate's headline case — a signed-in account without mcp.desktop.control — covered by nothing, because the broken fixture was exercising it by accident.

The cheap tell, which is what makes this checkable rather than a matter of judgement: if the "corrected" expectation duplicates what the new gate's own suite already asserts, the test has stopped testing its own subject.

What Changed

One entry appended to docs/developer/CLAUDE_REVIEW.md's "Self-review before pushing: known self-inflicted patterns" list, as item 9, in the existing numbered format with its citation.

It records the question to ask (did the observed value come from the subject, or from something that now precedes it?), the remedy (fix the fixture, not the expectation), the worked instances, and the duplicate-assertion tell.

Nothing else. No code, no test, no behaviour.

Verification

docs/developer/CLAUDE_REVIEW.md   268 -> 284 lines

Docs-only: git diff --name-only origin/main...HEAD returns exactly that one path. No .py, .ts or .vue file is touched, so no test behaviour can change.

The three instances cited are real and were each verified against the tree at the time:

file fixture what the gate did
vnc_proxy_handshake_wiring_test.py (x2) {"username": "alice"}, no role refused with 1008 before the handshake ran; tests asserted 1011
vnc_proxy_websocket_auth_test.py {"username": "alice", "role": "user"} refused; accept() never awaited

user holds no mcp.desktop.control; on merged main only Role.ADMIN and Role.OPERATOR do.

The entry is advisory prose in a checklist that already carries eight such entries, so there is nothing here a guard could assert — it is read by a human before pushing, which is what the section is for.

Refs #17054

Model Used

Claude Opus 5 (1M context).

…tation (#17054)

Three fixtures in one PR hit the same defect and twice the suggested repair
would have deleted the coverage it appeared to fix.

When a change adds an authorization gate upstream, every test whose fixture
predates it short-circuits before reaching its own subject. The failure reads
as `assert <new> == <old>` with a plausible new value, which is
indistinguishable in a CI log from an expectation that has simply drifted. The
obvious repair -- update the assertion -- goes green and removes the test's
real subject.

Observed on #17054's desktop-authz gate:

- two VNC handshake tests whose fake user carried no `role` began reporting
  the gate's `close(1008)` where the test asserted the handshake's `1011`;
  1011 was never a changed code, it was a code no longer REACHED
- a third, `role: "user"`, stopped reaching `accept()` at all

Re-pinning those expectations would have removed the only coverage of the
handshake-failure path and of the accept path, and left the gate's own
headline case -- a signed-in account without the permission -- covered by
nothing.

The tell recorded with it is the cheap one: if the "corrected" expectation
duplicates what the new gate's own suite already asserts, the test has stopped
testing its own subject.

Docs only; no code or test behaviour changes.

Refs #17054
@coderabbitai

coderabbitai Bot commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 44 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: mrveiss/AutoBot-AI/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: b3d2ef77-63c9-4a04-b78c-547149ddac25

📥 Commits

Reviewing files that changed from the base of the PR and between b92b80e and 9c08cc6.

📒 Files selected for processing (1)
  • docs/developer/CLAUDE_REVIEW.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mrveiss

mrveiss commented Sep 24, 2026

Copy link
Copy Markdown
Owner Author

Approve

Reviewed at 9c08cc61d. Docs-only, 16 lines, and the entry earns its place — it is the pattern that
nearly cost #17369 three tests, written down before anyone had to rediscover it.

The sharpest line is the tell, and it is the part I would not have thought to state:

If updating a test makes it a second copy of a neighbour, it has stopped testing its own subject.

That is checkable by a reviewer in seconds, unlike "think about whether the value came from the
subject", and it is what distinguishes this pattern from ordinary expectation drift. Fixture fixes preserve coverage; expectation fixes spend it is the same idea in a form someone will remember at
the moment they are tempted.

Two notes, neither blocking:

No size ceiling applies. I checked for a _MAX_LINES-style guard on CLAUDE_REVIEW.md before
raising it as a concern — there is none (repo_tests/ has one for THREAT_MODEL.md, not this file),
and the doc is 268 lines with the entry. So nothing to re-pin, unlike the threat-model raise in
#17369.

The pattern has a mechanizable half, for later rather than here. "An expectation moved to match
new behaviour" is visible in a diff: a changed assert x == <literal> in a test file that the PR
otherwise only touches at its fixtures. That would be noisy as a hard gate and is not what a
checklist entry should become — but if this recurs a third time it is worth a guard that reports
rather than blocks, in the shape of #17384's counting instrument rather than a keyword matcher.

Ledger: review 17396 9c08cc61d approve.

@mrveiss
mrveiss merged commit bcd7c8d into main Sep 24, 2026
51 checks passed
@mrveiss
mrveiss deleted the docs-review-gate-pattern branch September 24, 2026 12:06
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