Uh oh!
There was an error while loading. Please reload this page.
measure the read-seam rule's catch-fallthrough blind spot, and record the decision NOT to extend (#8845) - #8898
Merged
os-project-manager merged 1 commit intoAug 15, 2026
Conversation
…am rule to catch-fallthrough (#8845) The read-seam invention rule (#5186, extended by #6451) classifies a `catch` by the expression it returns, so a `catch` that returns nothing and lets an accumulator declared above the `try` answer for a read that never happened is cleared. Measured under the same 收窄先行 discipline #6451 followed, across the same three scan roots, before proposing any criterion. The measurement argues against the extension, so it is the measurement that is recorded — in the file's own header, which is this repo's authority on the rule — rather than the criterion being added: - 66 read seams; 41 have a valueless exit; 25 silent and undiscriminated; 15 also have an empty accumulator declared above, written inside, read below. - 7 of the 15 are already correct and would need baseline entries on a ledger that holds exactly one today. - The obvious exemption ("the catch wrote something read later") is inferred rather than declared, and clears a seam that pushes a fabricated revert-plan entry after a failed read. - Narrowing to a red set of 2 buys it by exempting three real instances, including a skipped `restrict` guard in cascadeDeleteRelations. - Dropping the READ vocabulary matches 91 of 314 catch clauses in the roots. No behaviour change: no criterion, no vocabulary entry, no baseline entry. Header comment only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011RB4waLuNbdruCo6X9oobm
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
This was referenced Aug 15, 2026
os-project-manager
marked this pull request as ready for review
August 15, 2026 16:00
This was referenced Aug 15, 2026
Uh oh!
There was an error while loading. Please reload this page.
os-project-manager
deleted the
claude/issue-8845-durability-catch-fallthrough
branch
August 15, 2026 16:08
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#8845
This card was a measurement, and the measurement came back "do not extend". No criterion is added, no vocabulary entry, no baseline entry, no behaviour change. What lands is the measurement itself, written into the checker's own header — which is this repo's declared authority on the rule — so the next author who notices this blind spot reads the numbers before re-proposing the criterion.
Measurement taken on
origin/main@8664a2c(the scan roots move fast —packages/metadata-protocol/src/protocol.tstook 10 commits in two days, so the sha is load-bearing). Gate union re-run at final HEAD647f5cf.1. The premise holds, but the mechanism in the card is slightly wrong
The card says "There is no return statement to classify". That is not quite it, and the difference matters for anyone trying to fix it.
walkBenignPaths()does model the fall-off-the-end exit — it pushes{ benign, expr: undefined, node: block }. The exit exists in the model. What happens next is thatinventedEmptyValue()andidentityPassThrough()both answerundefinedfor a valueless exit, so it is never classified as an invention. That is the same deliberate exclusion the empty-value table already documents for a barereturn;("in a Promise-of-void method that is not an invented answer at all"), which happens to cover fall-through too.So the honest statement is: the shape is not invisible to the AST, it is declined by a documented exclusion whose stated reason does not extend to this case.
Confirmed, and both of the card's other claims with it:
durability-read-invention.baseline.jsonholds exactly one entry,referenceExists;Two-direction ablation, because a green run proves nothing here
This gate reads package source, not
dist/, so no rebuild is involved. Planted in a scan root (packages/metadata-protocol/src/build-probes.ts), then reverted:catch { return []; }no invented answerSurveyed, counted, cleared. That is the #6116 shape a third time, and it is the evidence the card asked for.
2. The census
The scan roots' 66 read seams, narrowing one criterion at a time. Every number below is a first measurement, not a ratchet being raised — nothing here was previously counted.
--listexactly)returnanywheretry, written inside, read below3. Why 15 is not #6451's zero
#6451 landed because its true new red set was zero — "the strongest possible answer to is the red set controllable". This one would land 15 red on a ledger that holds one entry.
7 of the 15 are already correct and would each need a baseline entry. Every one of them delivers the failure:
errors++into a returned{ deleted, errors }(history-cleanup, 3 seams),issues.pushinto the returned probe report (build-probes),failed.pushinto the returned envelope (deletePackage, discardPackageDrafts), andreport.unreadableObjects.pushin the dangling-reference audit — a seam written precisely so its report "cannot be mistaken for a clean bill of health". Baselining seven correct seams to land a criterion is the "baselined into uselessness" outcome the card names, in advance.The obvious exemption for them is unsound, and measurably so. "The catch WROTE something that is read later" cuts 15 to 7 — but it is inferred, not declared, which is the one discipline this file holds everywhere ("Declared, never inferred"); it would be a second de-facto propagation vocabulary drifting alongside the real one; and it clears
publishPackageDrafts, whose catch pushes a fabricated revert-plan entry (existedBefore: false, prevVersion: null) after a failed read. An exemption that fires on an invention is not an exemption.Narrowing further makes it worse, not better. Also exempting a catch whose only statement is a jump cuts the red set to 2 —
diffMetaItemand one other. That looks like a clean result and is the trap: it buys the number by exempting three real instances, includingcascadeDeleteRelations, where a failed dependents probe skips arestrictguard outright. Tuning a criterion until only the instance you already knew about is red is how a gate stops meaning anything.Even the true positives are flagged for the wrong reason.
findReferencesToMeta's harm lives inout, not the flaggeditems;cascadeDeleteRelationsandcheckGovernancehave no accumulator at all, only a skipped guard. A message naming the wrong variable teaches the wrong fix.And the scope is the only thing holding the line. Drop the READ vocabulary and this shape matches 91 of the 314 catch clauses in the three roots. Since #5186 explicitly defers "evaluate widening as its own issue", that is the cliff the criterion would be sitting on.
4. What the shape actually needs
Not a looser invention criterion — a declared failure-propagation vocabulary for the read-seam rule. The log-level rule has one (
FAILURE_PROPAGATION_CALLEES/_SITES); the two rules share none, on purpose. With one, "the catch reported it" becomes a declared, checkable fact and the 7 already-correct seams stop being noise. That is a design question with a maintainer in it, not a criterion extension, so it is left un-taken here and written down instead.5.
diffMetaItemwas not touchedIts disposition stays with #8833, where the maintainer has three candidate response contracts. Since no criterion was added, no extension went red on it and there was nothing to resolve. Its seam is unchanged.
6. On the CI wiring question raised in #8889
Checked, because if the gate were not running on source changes then "green on main" would mean "did not run" and the card's baseline would be different. It runs.
.github/workflows/lint.ymlhas nopaths:filter at all — not on theon:block, not on thelintjob, not on the step. Everypathshit in that file is prose explaining why there deliberately is none. So the gate executes on every PR to main, every merge-queue build and every push to main, whatever changed.The derivation that names the gate is
scripts/pm/dispatch-gates.mjs, which reads path literals out of each check script's own source — and it resolves correctly:main-green is therefore a real measurement, and the answer to "would an extension ever fire in CI" is yes.7. Findings filed, not fixed
The census turned up seams that are defects on their own terms. Filed unassigned, none touched here:
restrictguard entirely, so a delete that should be refused succeeds silently #8895 —cascadeDeleteRelationsfails open: a failed dependents probe skips therestrictguard, so a delete that should be refused succeeds silently. The most consequential thing the measurement found.loadExistingRecords,searchAll,findReferencesToMeta,getMetaDiagnostics,checkGovernance), pluspublishPackageDrafts' fabricated revert-plan entry and its comment/code divergence.collectLoggedLevelsonly recognises a logger named logger/log/console, so a catch that reports through an injected logger reads as silent to BOTH rules #8897 (finding) —collectLoggedLevelsonly recognises a receiver namedlogger/log/console, so the dangling-reference audit'sport.warn?.()reads as silent to both rules. Latent today; recorded rather than rediscovered.Verification
Union re-run after the final commit, at
647f5cf:Gate families re-derived against the real diff (
node scripts/pm/dispatch-gates.mjs scripts/check-durability-degradation-log-level.mjs):check:durability-log-levelonly, plus the convention-scopedcheck:nul-bytes. Both above. Judged by exit status, not by grepping output.Comment-only change to a root
scripts/file, which is not a published package, so no changeset —skip-changesetapplied.Generated by Claude Code