Eligibility::from_builtins degrades auto-generated (plugin-excluded), which is package-independent by construction #219
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#219
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 by the #210 lane while adopting
from_builtins' completeness gate. Small, and it strengthens two surfaces at once with no RPC.The gap
Eligibility::from_builtinsdegrades every builtinIneligibleverdict when packages are installed, on the sound principle that a package might claim the extension. That is correct forineligible_extension.It is not correct for
PathEligibility::Ineligible("auto-generated (plugin-excluded)"). That verdict means a builtin claims the extension and excluded the file as generated. SinceManifest::validaterefuses at discovery any package whose claims intersect a compiled-in language's, no installed package can ever claim an extension a builtin already claims. So this verdict cannot be overturned by any package set — it is package-independent by construction — and degrading it underBuiltinPartialthrows away a proof that was already sound.Why it was not fixed in #210
The lane deliberately mirrored the existing behaviour rather than make
doctorstronger thanindex_coverage, which is the right instinct: two surfaces disagreeing is the defect #210 exists to remove, and a lane fixingdoctorshould not unilaterally widen the shared ladder.Fixing it in
from_builtinsmoves both surfaces together, which is the correct place.What the fix must do
Distinguish the two
Ineligiblereasons infrom_builtins: keep degradingineligible_extension(a package could claim it), stop degradingauto_generated(no admissible package can). The justification rests onManifest::validate's intersection refusal, so the fix should cite it — if that refusal is ever relaxed, this exemption must go with it.Mutations
auto_generatedagain → the assertion that a generated file is provedneverwith packages installed must go RED.ineligible_extension→ the assertion that.wasmis NOT provedneverwith packages installed must go RED. Both directions need grading or the fix is a one-way widening.Manifest::validate's intersection refusal → a test pinning that refusal must go RED, since this exemption is only sound while it holds. That is the guard worth most: it stops a future change from quietly invalidating the reasoning here.Related: #210 (the fix that surfaced it), #218 (the RPC that would close the rest of the same gap).
REFUTED. Closing without the fix, and the counterexample is now pinned so it cannot be silently re-implemented.
The premise this issue rests on — "no installed package can ever claim an extension a builtin already claims" — was true before #84 and is not true now.
Manifest::validate(crates/package/src/manifest.rs:1142) no longer callscheck_against(&builtin_claim_table(), Scope::PackageVsBuiltin). It callsself.displacements()→builtin::displaced_by, which refuses an intersection only when[[displaces]]did not declare it. Intersection is now consent-gated, not forbidden.And it lands exactly on this verdict rather than near it:
includes: ext:cswithexcludes: suffix .Designer.cs, suffix .g.cs(crates/package/src/builtin.rs:97) — those excluded files are the entire population behindauto-generated (plugin-excluded);Displacementcarries the builtin's key,ext:cs, which is wider than what the builtin actually indexes, andDisplaced::coverstests that key — so it coversFoo.Designer.cs;path_eligibility_inconsultsdisplacing_routebefore the builtins, so the package wins.Measured end-to-end through the production door — packed by
Container::pack, signed, installed into a realStore, approved viaApprovalRecord, discovered byPackageSet::discover_with_store— with a package claimingext:csplus[[displaces]] csharp ext:cs:Half this evidence was already in the tree:
crates/package/tests/builtin_displacement.rs:225(a_conservative_intersection_is_still_a_consented_displacement) usesFoo.Designer.csagainst csharp as its fixture and asserts consent admits it.The fix would have been actively harmful
Under
Source::BuiltinPartial(daemon silent, packages installed) the exemption would emitnever / auto_generatedfor a file the daemon's owneligibility::claims(crates/daemon/src/eligibility.rs:477) reports ascode/claimed_by: "package". Two surfaces of one binary disagreeing about one path — the exact defect #210 exists to remove — reintroduced by the change meant to strengthen it. It would also be a negative finding drawn from an answer nobody asked for, which is whateligibility.rsis built to prevent.The neighbouring
Codeexemption is unaffectedWorth stating because the two look identical. Displacement can only turn
Code(builtin)intoPackage(route), never intoText/Ineligible—path_eligibility_infalls through toselect_pluginwhendisplacing_routedeclines. Both map toClaim::Code, so the claim does not move. Row 3 above measures that.Ineligible → Packagedoes move it, which is why only this verdict is affected.What landed instead
crates/package/tests/displaced_builtin_exclusions.rs— a guard, not a fix, pinning both halves of the premise, merged ased139ff. Two mutations run, each reddening only its own test:Displaced::coverson the builtin route (the change that would make #219 true) →svc/Foo.Designer.cs is inside the displaced domain, so the compiled-in csharp lost it.displaced_by'sif !consent.contains(&c.right)→if false(this issue's own third mutation; the refusal's only remaining site) →a package claiming.cswith no consent must be refused.So the next lane that reads this issue and reaches for the "obvious" exemption gets a RED naming the counterexample.
If the proof is still wanted
It is not obtainable from a ladder clause. A sound version needs the displacement half of the package state — precisely the state
from_builtinsdoes not have and cannot get. That points at #218's RPC, not here.Correction to the issue as filed:
from_builtinsis incrates/mcp-server/src/eligibility.rs:366, notcrates/indexer/src/index.rs. My error in the original report. It also has substantial existing coverage — 15 call sites, 14 in tests — so unlike #209/#211/#217 this was not a zero-test surface..claude/, which the walker excludes, so the index silently serves someone else's tree #220