precision_gate's population is far smaller than its reputation — phantom_count == 0 bounds ~50 hand-written probes, not the corpus, and it is cited across the tree as an absolute guarantee #188
Labels
No labels
code-review
correctness
dos
performance
security
severity/high
severity/low
severity/medium
tech-debt
Kind/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
h-dv/code-index#188
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found while auditing the
cs-dappercorpus delta from #172. The fix there admitted 34 wrong binds on the pinned corpus whileprecision_gatereported 7/7 withphantom_count == 0. Both statements are true, and the reason they are compatible is the finding.Measured
The C# population is 3 files, 66 lines, 4 probes — and contains ZERO generic call sites.
So #172's entire defect class — a call site spelling explicit type arguments — was outside the gate's population by construction. Not missed: unreachable. The fixture has no
<T>call to get wrong.It never indexes a corpus repo.
Its fixture root is
tests/fixtures/<lang>/project, resolved fromworkspace_root(). There is no code path by which any of the nine pinned corpus repositories reaches it.The whole universe of the gate:
~47 probes over 54 files.
And a phantom is only scored against a DECLARED decoy. The oracle's contract (
crates/daemon/tests/precision_gate.rs, module docs) is: each probe names sites that MUST resolve to it (expect_resolved) and sites that must NEVER (forbid_resolved— same-name decoys).phantom_countcounts binds landing on aforbid_resolvedsite. A wrong bind to a symbol nobody thought to list as a decoy is invisible even inside the 66-line fixture. The gate cannot say "this bind is wrong"; it can only say "this bind hit a target I predicted would be wrong".What
phantom_count == 0does and does not assertDoes assert: across ~47 hand-authored probes in 7 languages, no reference resolved to a same-name decoy that the oracle explicitly declared. That is a real and valuable regression gate — it caught the I023 same-dir method-call phantom, and it is non-gameable in the direction that matters (a resolver that "resolves everything" scores worse).
Does NOT assert: anything whatsoever about the 3811 C# binds on
cs-dapper, the ~13.5k onphp-guzzle, or any other corpus repository. It is not a bound on the product's phantom rate. It is not violated by a change that admits 34 wrong binds on a real repository, because it never looks at one.Why this matters more than the fix that found it
The gate is cited across the tree as an absolute guarantee, and the citations do not carry the scope:
CLAUDE.md:62— "precision_gatemust stay 7/7 withphantom_count == 0." Stated as a repository-wide invariant with no population named.precision_gatedoes gate".phantom_count == 0)".phantom_count == 0is the gate that must not move."Every one of those sentences is literally true and reads as a much stronger claim than the gate makes. A reviewer who trusts it — as I did, and as the issue authors did — will approve a change that adds phantoms to every real repository we index, on the strength of 47 probes.
Why existing gates could not see this
corpus_ratchetpinsresolvedas a COUNT. A wrong bind and a right bind are both +1.corpus_stagepins which RULE claimed each bind. It moves when a rule's share moves, and it did (#172) — but it cannot say whether a bind is correct.precision_gateitself is the thing being measured, so it cannot report its own population. Nothing in the tree states how many probes it runs or over how much code. That number had to be counted by hand for this issue.What must NOT be done
phantom_count == 0over the pinned corpora. There is no ground truth there. Every bind oncs-dapperwould have to be adjudicated by hand to know which are wrong, and without a decoy discipline an undeclared wrong bind is invisible by construction — the same blindness this issue is about, relocated to a bigger fixture. A corpus-scale gate needs an explicit oracle of adjudicated (site → correct target) pairs, built and reviewed, not derived from the resolver's own output.CLAUDE.mdalone. Correcting the prose is necessary but it is the smaller half: the gate should REPORT its own population (probes, files, per-language) in its output, so a reader of a passing run sees7/7, phantoms=0 over 47 probes / 54 files / 0 corpus reposand cannot mistake it for a corpus claim. A number that has to be counted by hand to be doubted will not be doubted.Suggested shape (not prescriptive)
#178lesson: mutate the predicate, not just the data).CLAUDE.mdand the tool descriptions state the scope in the same breath as the number.Measured vs inferred
All counts above are measured on the tree at
f6a878aand quoted verbatim from the commands shown. That the citations mislead a reader is a judgement, supported by the fact that it misled this session repeatedly: three issue authors and this lane all invoked the gate as a corpus-scale clearance.🤖 Generated with Claude Code
https://claude.ai/code/session_01K1zj5VcFJvJt3pQxe9259K
Verdict: CONFIRMED. The gate now measures and prints its own population, and a floor fails when any of it shrinks.
Your counts were right; two are worse than reported once measured on the STAGED project (the runtime decoys
write_phantom_decoys/write_hyphen_pkg_decoysadd files, andEXPECTATIONS.mdwas inside your line count). The number that matters most was never counted at all.What a green run now says
All seven, measured on the tree with the #189 fix in it:
forbid_sitesis the number your issue is about and nothing in the tree had it. It is the entire denominator ofphantom_count == 0— a phantom can only be scored against a site the oracle listed. So the honest statement is:And for JavaScript that is 1 site. A green JS run means one declared decoy did not bind. I recorded it as
1rather than rounding it up, because the number IS the finding.Mechanism, so it cannot go unstated again
probes/expect_sites/forbid_sitesare counted off the loaded oracle.files/code_linesare walked on the STAGED project — so the runtime decoys are inside the number exactly as they are inside the run, which is whycsharpreads 9 files / 94 lines and not your 3 / 66.symbols/refs/refs_resolvedcome fromrpc.stats()on the index the daemon actually built. A hand-maintained constant would be the same unstated population one indirection further away.corpus_repos=0is a named constant with its reason in its doc, printed on every run. It is a structural fact — the fixture root istests/fixtures/<lang>/projectfromworkspace_root(), and no code path reaches a pinned repo — not a measurement.POPULATION_FLOORis a per-language ratchet at the values measured on this tree, checked as afailures.pushinsiderun_gate. Shrinking a fixture, deleting a probe, or emptying aforbid_resolvedlist fails the gate for the language it happened in, and the failure text says the thing that makes it a finding: "The gate still reports phantoms={n}, and that is the point: a shrunken fixture keeps passing every other check in this file." Raising a floor is a claim that coverage grew. Lowering one has to be written down.phantom_count == 0ASSERTS, AND WHAT IT DOES NOT, including thatCOSI_CORPUSappears nowhere in the file.Mutations, both RUN to real RED
Per the #178 lesson, one on the PREDICATE and one on the DATA:
("csharp", 4, 3, 9, 94)→95. RED:csharp: POPULATION FLOOR — code_lines=94 is below the recorded floor 95. Proves the check is live and bound to a real measurement rather than to a literal echoing itself.tests/fixtures/csharp/project/Util.csto 6 lines. RED:code_lines=79 is below the recorded floor 94, withexpect_sitesdropping 2 → 1 in the same report. Proves it catches an emptied fixture. Fixture restored, md5 verified.The prose half
CLAUDE.mdhad already been corrected on this tree (8d90075). Two things were still missing and are now fixed:precision_gateat all. It now does, with-- --nocapture, and says why that is not decoration: cargo swallows the population line on a pass, and a green run you cannot read the population of is the exact thing #188 reports.forbid_sitesfirst, names JavaScript's1, and says the floor exists.One further in-tree citation was overstated and is corrected:
daemon/src/local_index.rs'sname_fallback_shape_excludeddoc said adding those rows would manufacture "the phantomsphantom_count == 0forbids", which reads as all phantoms. It now says it forbids the ones its oracles DECLARE, and points here.What I did NOT do, per your two warnings
Gates
Staged by path, not pushed.
Still open, and I am not closing it
forbid_sites=23is now visible, but it is still 23 hand-written predictions. The population report makes the gate's reach legible; it does not make it large. A corpus-scale phantom oracle — adjudicated(site → correct target)pairs, built and reviewed rather than derived from the resolver's own output — remains the piece of work you named, and this change makes the case for it in one line of every green run rather than requiring a hand count.CLOSING — verified on merged master
fc329a8, gate RUN, and the floor MUTATED to real RED by this laneClose-out lane, independent of the lane that did the work. The C# lane's comment declined to close on the grounds that
forbid_sites=23is still 23 hand-written predictions. That residual is real, but this issue's own body excludes it: "A separate, explicitly-scoped corpus phantom oracle is a real piece of work with its own issue", and "Do not simply assertphantom_count == 0over the pinned corpora". That work has a home — #49 (frozen SCIP-derived authoritative targets, phantom detection confidence-gated, honest denominator) — and it is open. Keeping #188 open as well would double-count it.Both things the issue asked for are in the tree and graded.
1 — the gate reports its own population, measured rather than declared.
crates/daemon/tests/precision_gate.rs:measure_staged()(:800) walks the STAGED project so the runtime decoys are inside the number;symbols/refs/refs_resolvedcome fromrpc.stats()on the index the daemon actually built;CORPUS_REPOS_INDEXED(:711) is a named constant carrying its structural reason. Printed at:1010on every run.RUN on this tree —
cargo test --release -p code-index-daemon --test precision_gate -- --nocapture, exit 0, 7 passed:corpus_repos=0on every line. Your hand counts were right; the staged figures are larger because the runtime decoys are counted where they belong.2 —
POPULATION_FLOORfails when the population shrinks, and I ran the mutation myself rather than taking it on report.POPULATION_FLOORat:741, checked as afailures.pushinsiderun_gate(:975-990). Data mutation: truncatetests/fixtures/csharp/project/Util.csfrom 21 lines to 6.Note what that emptied fixture still reported:
phantoms=0. That is the whole finding, now caught. Fixture restored, md547eb057cd8555fb79947c18779ea31feverified, tree clean.3 — the prose.
CLAUDE.md:57now listsprecision_gatein the verification-gate block with-- --nocapture, and says why that is not decoration ("a green run you cannot read the population of is the exact thing #188 reports").CLAUDE.md:68-80leads withforbid_sites, names JavaScript's 1, statescorpus_repos=0, records that it stayed 7/7 across a change admitting 34 wrong binds, and tells the next lane to measure binds by joining on(path, line, col, kind, occurrence)instead.Corpus gates, run alongside so the green is not read narrowly —
COSI_CORPUS_DIR=… COSI_CORPUS_REQUIRE=1, all with non-zeroexecuted:corpus_ratchetexecuted=7exit 0 ·corpus_stageexecuted=7exit 0 ·corpus_tier3_ratchetexecuted=2exit 0.Carried forward to #49, not dropped: the population is now legible, not large. A corpus-scale oracle of adjudicated
(site → correct target)pairs is still the only thing that would makephantom_count == 0a statement about real repositories.total: 0for a literal its own variant scan found in the same reply, and asserted the spellings were DISJOINT searches while behaving separator-insensitively #195