doctor cannot prove never on a project with packages installed — 35/35 land in NOT CLASSIFIED where index_coverage proves them permanent #218
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#218
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?
Follow-up to #210, reported by the lane that fixed it — against its own fix. Filed because the fix is weaker on the reporting repository than #210's text implies, and the reason is structural.
What #210 achieved, and where it stops
Before, on this repo:
After:
Both harms named in #210 are gone: no false staleness claim, the permanent WARN is cleared, and real drift would now show up in the
coverable with no rowfigure instead of being buried. The two surfaces no longer contradict each other — one provesnever, the other declines to guess.But the useful half is missing.
index_coverageproves those same 35 paths arenever/ineligible_extension/hint: "Permanent".doctorcan only say it did not classify them.Why, precisely
~/.code-index/approvalsholds an approval for this project, sopackages::any_installed(root)is true. The completeness gate that #210 correctly adopted — the same oneEligibility::from_builtinsapplies — then says a builtin refusal proves nothing, because a package could claim.wasm.That gate is right. A package can only ADD claims, and
Manifest::validaterefuses at discovery any package whose claims intersect a compiled-in language's — so a builtinCodeverdict is sound without consulting the package set, while a builtinIneligibleis a proof of permanence only when no package could claim anything here.index_coverageescapes this because it asks the daemon and getseligibility_source: "project"— the project's real extractor set.doctoris a synchronous CLI with no tokio runtime and noIndexAccess, so it cannot ask, and correctly degrades rather than guessing.So on any project with at least one package installed,
doctor's never-indexable population is permanently empty and everything lands in NOT CLASSIFIED. On a package-free project the full three-way split appears as designed.The fix
Give
doctorthepath_claimsRPC — the same callindex_coverageuses to learn the project's claimed extensions — so it can consult the active generation instead of falling back to builtins.The cost is real and is why the #210 lane did not do it: it turns a synchronous check into an asynchronous one, which is a structural change to
doctor, well outside the scope of the issue it was fixing. That was the right call; it belongs here.Requirements:
doctormust reach the same verdictindex_coveragedoes for the same path, and the NOT CLASSIFIED population must go to zero on this repository.doctorthat guesses when the daemon is down is worse than one that declines.eligibility_sourceshould be reported so the reader can tell which of the two answered.Mutations
doctorat builtins while the daemon is up → the "matchesindex_coverage" assertion must go RED.never→ the honest-degradation assertion must go RED. This is the important one: it is the failure the current code avoids and the fix could reintroduce.Related, and NOT fixed
The same lane found an adjacent gap in
Eligibility::from_builtinsitself, filed separately:PathEligibility::Ineligible("auto-generated (plugin-excluded)")is package-independent by construction and is degraded anyway. Fixing that would strengthen bothdoctorandindex_coveragewithout any RPC.Eligibility::from_builtinsdegradesauto-generated (plugin-excluded), which is package-independent by construction #219Eligibility::from_builtinsdegradesauto-generated (plugin-excluded), which is package-independent by construction #219.claude/, which the walker excludes, so the index silently serves someone else's tree #220Fixed in
f28df60— "doctorproves whatindex_coverageproves, by asking the project" — onmaster, shipping in v0.27.0.doctorcould not proveneveron a project with packages installed, so 35 of 35 files landed in NOT CLASSIFIED. It now asks the project's own extractor set rather than a built-in list, which is whatindex_coveragealready did — so the two surfaces give the same verdict on the same file, and the answer carrieseligibility_source=project.Closing on merge.