Skip to content

[finding] The filter-subtree author invariant is now written and pinned, but still not ENFORCED — the survey's caller classifier exists only as a transcript #9074

Description

@os-zhuang

Filed unassigned, finding only — grading and routing are triage's field. Observation class: nothing is broken today. Duplicate-searched first (keyword + packages/spec/src/data/filter-subtree-provenance over open issues): no existing card.

Recording this because #8836 closes with PR #9073, and a residual carried only by a closed card is the shape #8836 itself was filed to avoid.

What #8836 delivered, and the exact edge of it

PR #9073 shipped both graded halves: the docblock correction, and an executable pin of

no filter object that can be vouched author may outlive the request that vouched it.

The pin works and discriminates (the disclosure case and its fresh-object control bracket the mechanism from both sides; two reverse-verification ablations reddened it as predicted). But it is a unit test in packages/spec, and that package cannot see "the request" — so what it pins is the cost of a violation, not the violation itself. Stated plainly in the test's own docblock rather than left implied.

So the actual guard against a future caller breaking the invariant is unchanged from before #8836: none. A new caller that hands the engine a module-level constant, a cached scope or reused view metadata in options.where still goes green everywhere.

The missing half, and it is already written once

#8794's survey did not reason its zero — it scripted it. For every where: identifier option site in non-test source it classified the identifier's declaration as module scope or function-local, and it carried a positive control: a synthetic module-scope filter in the docblock's exact shape made the classifier report 1, proving the detector fires. That classifier is the enforcing artifact, and today it exists only as a quoted transcript on a closed card.

Turning it into a repo gate would convert the invariant from documented to enforced. Two things a builder must not narrow, both measured on the closed card:

  • the markable population is options.whereand the arms of a pure { $and: [...] } root, not the root alone;
  • a zero-hit gate needs its positive control wired in as a self-test, or it will pass forever after the day it silently stops matching.

Why this is filed rather than folded into #8836

The triage grading on #8836 scoped it to exactly two deliverables and said so twice; a new gate is a third, with its own verification surface and its own baseline. It is also not obviously wanted — a whole-repo scanning gate has real cost, and the measured pull is zero in-repo callers. That is a triage judgment, not a dev one.

⛔ Note this is not a mechanism change and does not re-open #8794's ruling: a static check over caller code changes nothing about the mark, first-mark-wins, or where the stamp may be applied. If triage instead decides the pin plus the corrected docblock is the right resting place, closing this not planned with that reasoning recorded is a complete disposition.

Related


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions