You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Filed while working #8582 (session session_01RDTnVvsgA6cUZ4xFVtPZRy), which swept the 78 test-double matches(row, where) fakes that pnpm check:where-matcher discovered and grandfathered in scripts/where-matcher-conformance.baseline.json.
The gap
scripts/check-where-matcher-conformance.mjs's discovery only considers a candidate matcher when it is a function with two or more identifier parameters — see discoverInSource's params.length >= 2 && params[0] && params[1] gate. That is deliberate (it is how the control probe stays name-independent), but it has a structural blind spot: a single-param.filter() callback that closes over where/filter from its enclosing scope, rather than taking it as its own second parameter, is invisible to discovery — even when its body is textually identical to a matcher the gate already knows how to grade.
Measured on main (as of this filing), this exact shape —
Each treats where/filter as an ordinary field bag via Object.entries(...).every(([k,v]) => r[k] === v) with no $or/$and branch — the identical failure shape (b) #8494/#8582 exist to catch. Whether each is live (a suite actually hands it a $or/$and) is unmeasured — same as #8582's worklist was before it was swept — but the shape itself is not in question; it is byte-for-byte the pattern the gate already grades everywhere it CAN see it.
Why this is worth a decision, not a silent tolerance
check-where-matcher-conformance's own header states discovery is "self-verifying: membership is decided by behaviour, not by a name" — true for the matchers it finds, but the two-param requirement means a whole authoring STYLE (inline .filter() capturing an outer where) sits entirely outside its authority. A gate that cannot see a class of instance cannot grade it green OR red; "not in the ledger" reads as "conforming" to anyone skimming check:where-matcher's output, which is exactly backwards for these 17.
Options (not investigated further — this is the finding, not the fix)
Extend discovery to also match a single-param .filter/.some/.every callback whose body reads Object.entries(<name>) where <name> resolves (via the same visibleDeclarations walk already built for extraction) to an enclosing parameter or destructured option — i.e., loosen the "must be its own 2nd parameter" requirement to "the where-shaped identifier must resolve to something in scope," while keeping the behavioural control probe as the real filter against false positives.
Filed while working #8582 (session
session_01RDTnVvsgA6cUZ4xFVtPZRy), which swept the 78 test-doublematches(row, where)fakes thatpnpm check:where-matcherdiscovered and grandfathered inscripts/where-matcher-conformance.baseline.json.The gap
scripts/check-where-matcher-conformance.mjs's discovery only considers a candidate matcher when it is a function with two or more identifier parameters — seediscoverInSource'sparams.length >= 2 && params[0] && params[1]gate. That is deliberate (it is how the control probe stays name-independent), but it has a structural blind spot: a single-param.filter()callback that closes overwhere/filterfrom its enclosing scope, rather than taking it as its own second parameter, is invisible to discovery — even when its body is textually identical to a matcher the gate already knows how to grade.Measured on
main(as of this filing), this exact shape —— or a same-file
filtervariant, appears 17 times across 16 files, none of them reachable bypnpm check:where-matcherand none in its ledger:packages/plugins/plugin-email/src/attachment-reclaim.test.ts:58packages/plugins/plugin-email/src/template-locale-resolution.test.ts:67packages/plugins/plugin-security/src/bootstrap-declared-positions.test.ts:29packages/plugins/plugin-security/src/bootstrap-declared-permissions.test.ts:18packages/plugins/plugin-security/src/bootstrap-platform-admin.test.ts:30packages/plugins/plugin-auth/src/admin-import-users.test.ts:36packages/core/src/security/api-key.test.ts:20packages/metadata-protocol/src/migrations/recorded-by-sentinel.test.ts:76packages/core/src/utils/migration-journal.test.ts:84packages/rest/src/import-runner-selfref.test.ts:47packages/rest/src/import-runner-idempotency.test.ts:56packages/services/service-storage/src/lax-deviation-reclamation-gate.test.ts:61and:88(two instances)packages/services/service-storage/src/file-reference-lifecycle.test.ts:237(a second, undiscovered instance in a file finding: 78 test-double WHERE matchers have no combinator branch at all — they read$oras a field name and silently drop the row #8582 already fixed a different, discovered matcher in)packages/runtime/src/migration-recovery-plugin.test.ts:48packages/runtime/src/http-dispatcher.keys.test.ts:28packages/runtime/src/http-dispatcher.test.ts:3947Each treats
where/filteras an ordinary field bag viaObject.entries(...).every(([k,v]) => r[k] === v)with no$or/$andbranch — the identical failure shape (b) #8494/#8582 exist to catch. Whether each is live (a suite actually hands it a$or/$and) is unmeasured — same as #8582's worklist was before it was swept — but the shape itself is not in question; it is byte-for-byte the pattern the gate already grades everywhere it CAN see it.Why this is worth a decision, not a silent tolerance
check-where-matcher-conformance's own header states discovery is "self-verifying: membership is decided by behaviour, not by a name" — true for the matchers it finds, but the two-param requirement means a whole authoring STYLE (inline.filter()capturing an outerwhere) sits entirely outside its authority. A gate that cannot see a class of instance cannot grade it green OR red; "not in the ledger" reads as "conforming" to anyone skimmingcheck:where-matcher's output, which is exactly backwards for these 17.Options (not investigated further — this is the finding, not the fix)
.filter/.some/.everycallback whose body readsObject.entries(<name>)where<name>resolves (via the samevisibleDeclarationswalk already built for extraction) to an enclosing parameter or destructured option — i.e., loosen the "must be its own 2nd parameter" requirement to "the where-shaped identifier must resolve to something in scope," while keeping the behavioural control probe as the real filter against false positives.$oras a field name and silently drop the row #8582 did its 78 — cheaper per-instance, but does not close the gate's blind spot for the next one someone writes in this style.Either way the two are not mutually exclusive; 2 without 1 leaves the hole open for new code.
Refs: #8582 (the sweep that surfaced this), #8494 (the gate this extends), #7620 (the original 16-file $or short-circuit finding).
Generated by Claude Code