honesty: disclose symbol-blind and plugin-unavailable coverage by extension #81

Closed
opened 2026-08-26 12:34:26 +02:00 by buildagent · 1 comment
Member

Relates to #75, but independently filable and fixable today. Customer-driven, and it is the I063 shape again: a hardcoded enumeration standing in for a measurement.

Part 1 — the enumerated list has already drifted, and the shipped copy is the wrong one

There is no named constant. The "a ref_count of 0 can be vacuous" claim is duplicated as prose in three places, and they disagree:

copy location causes named get measurement consts
tool description crates/mcp-server/src/server.rs:5287 2 ("alias-qualified calls, Rust consts") — —
MCP resource docs/ref-kinds crates/mcp-server/src/server.rs:11514-11543 3 11 / 846 325
rustdoc on the field crates/daemon/src/local_index.rs:73-122 3 11 / 834 326

Verified by grep. Same claims, different numbers — and the copy an agent actually pays tokens to read (the shipped resource) is the one disagreeing with the internal doc.

This is exactly what producer_coverage_matrix.rs:295-302 refuses to commit: three copies of one closed set, free to rot. And it fails the customer case concretely — a C#/WPF user checks a two-item list, matches neither, and reasonably concludes their 0 is tight.

Part 2 — the thing that would have warned them is not measured

Verified: .xaml, .axaml, .xsd are in EXTRA_TEXT_EXTENSIONS (crates/indexer/src/text_only.rs:30-52) → kind='text', searchable, zero symbols. *.Designer.cs — where typed-DataSet members are generated — is refused by the C# plugin itself (crates/plugins/src/csharp.rs:48).

So for that codebase a large share of the real reference graph is structurally invisible, and nothing in any payload says so.

The fix, and the design constraint that makes it work

Do not report a bare percentage. This repo is 254 code / 113 text files — 31% text-kind — and that number is noise here because it's md and toml. The same number is a klaxon there. What makes it readable is not aggregating away the extensions:

here:  md 86, toml 18, json 4, yml 3, sh 1, csproj 1   → docs and config, move on
there: xaml N, xsd M, resx K, config J                 → that is the UI and data layer

No framework knowledge anywhere; the reader judges, we decline to hide the evidence.

Cost is nil and it comes free with correctness. languages is already SELECT lang, COUNT(*) FROM files GROUP BY lang (crates/daemon/src/local_index.rs:816) and GROUP BY kind measures at 2 ms. Add kind to that grouping and both lists fall out of one pass — which also guarantees they cannot contradict each other, the property WholeWordWindow.semantics exists to enforce (server.rs:3876-3918).

Scope

  1. project_overview.symbol_blind_extensions — extension + count for every kind='text' file. A new field, not a change to languages: that is Vec<(String, u64)> and widening the tuple is an arity break on shipped wire.
  2. Delete the enumeration. Replace all three copies with one payload-resident, derived count_basis / count_basis_semantics. This doesn't merely stop the list rotting — it deletes two copies and makes the third computable. One definition, per the ineligible_code pattern (server.rs:3470-3484).
  3. Point at the tool that can answer. safe_delete's FTS channel already covers text-kind files — all 113 here are in files_fts, no kind filter in the query — so "is this DataSet member actually used?" already has an honest answer today and nothing points at it.
  4. Skew: additive field, both directions, non-empty payloads, per the I062 discipline.

Test shape

Registry gate: a fixture with code files, reference-bearing text files (.xaml, .erb, .vue), inert text (.md), and a refused .Designer.cs. Assert each text extension is named with the right count; that an md-only project reads as unremarkable while a xaml-heavy one is visibly dominated; and — anti-vacuity — that a project with no text files omits the block rather than reporting an empty one.

Mutation it must catch: aggregating the extensions into a single total. That version is useless, and a test that still passes on it is grading the wrong axis.

What to tell the customer

Their 36% is better than this repo's own Rust (24.5%) and is not the thing to worry about — unresolved LINQ/BCL extension methods are correctly unresolved because the targets aren't in the project; the figure largely measures stdlib surface. The XAML/DataSet half is the real issue, and it is more consequential than "carries no symbols" sounds, because XAML holds genuine edges (Click=, x:Name, {Binding}) that no count in any payload currently reflects.

Runtime-plugin architecture extension

With #75, kind='text' is no longer the whole symbol-blind population. Coverage must be derived against the project’s active generation and requested package state.

project_overview must distinguish, by extension/count:

  • text-only and intentionally symbol-blind under the active generation;
  • claimed by an active plugin and structurally indexed;
  • requested plugin not installed;
  • installed but ABI/capability/conformance rejected;
  • quarantined or failed activation while the prior generation remains active;
  • plugin-excluded/generated source such as Designer.cs;
  • permanently unclaimed.

Do not subtract an extension from symbol_blind merely because a package manifest claims it. Only active contributions with a successful generation count as structural coverage.

The block carries active generation identity and unavailable semantics for older daemons. Counts must come from the same project-scoped query/snapshot as the language/plugin coverage block in #80 so the disclosures cannot contradict each other.

#81 remains independently shippable now: its initial implementation can report current text/excluded extensions. The schema should be additive so #80 can refine each extension into the states above without changing the meaning of the original count.

Relates to #75, but **independently filable and fixable today**. Customer-driven, and it is the I063 shape again: a hardcoded enumeration standing in for a measurement. ## Part 1 — the enumerated list has already drifted, and the shipped copy is the wrong one There is **no named constant**. The "a `ref_count` of 0 can be vacuous" claim is duplicated as prose in **three** places, and they disagree: | copy | location | causes named | `get` measurement | consts | |---|---|---|---|---| | tool description | `crates/mcp-server/src/server.rs:5287` | **2** ("alias-qualified calls, Rust consts") | — | — | | MCP resource `docs/ref-kinds` | `crates/mcp-server/src/server.rs:11514-11543` | 3 | 11 / **846** | **325** | | rustdoc on the field | `crates/daemon/src/local_index.rs:73-122` | 3 | 11 / **834** | **326** | Verified by grep. Same claims, different numbers — and the copy an agent actually pays tokens to read (the shipped resource) is the one disagreeing with the internal doc. This is exactly what `producer_coverage_matrix.rs:295-302` refuses to commit: three copies of one closed set, free to rot. And it fails the customer case concretely — a C#/WPF user checks a two-item list, matches neither, and reasonably concludes their `0` is tight. ## Part 2 — the thing that *would* have warned them is not measured Verified: `.xaml`, `.axaml`, `.xsd` are in `EXTRA_TEXT_EXTENSIONS` (`crates/indexer/src/text_only.rs:30-52`) → `kind='text'`, searchable, **zero symbols**. `*.Designer.cs` — where typed-DataSet members are generated — is refused by the C# plugin itself (`crates/plugins/src/csharp.rs:48`). So for that codebase a large share of the real reference graph is structurally invisible, and nothing in any payload says so. ## The fix, and the design constraint that makes it work **Do not report a bare percentage.** This repo is 254 code / 113 text files — 31% text-kind — and that number is *noise* here because it's `md` and `toml`. The same number is a klaxon there. What makes it readable is **not aggregating away the extensions**: ``` here: md 86, toml 18, json 4, yml 3, sh 1, csproj 1 → docs and config, move on there: xaml N, xsd M, resx K, config J → that is the UI and data layer ``` No framework knowledge anywhere; the reader judges, we decline to hide the evidence. **Cost is nil and it comes free with correctness.** `languages` is already `SELECT lang, COUNT(*) FROM files GROUP BY lang` (`crates/daemon/src/local_index.rs:816`) and `GROUP BY kind` measures at **2 ms**. Add `kind` to that grouping and both lists fall out of **one pass** — which also guarantees they cannot contradict each other, the property `WholeWordWindow.semantics` exists to enforce (`server.rs:3876-3918`). ## Scope 1. **`project_overview.symbol_blind_extensions`** — extension + count for every `kind='text'` file. A **new field**, not a change to `languages`: that is `Vec<(String, u64)>` and widening the tuple is an arity break on shipped wire. 2. **Delete the enumeration.** Replace all three copies with one payload-resident, derived `count_basis` / `count_basis_semantics`. This doesn't merely stop the list rotting — it **deletes two copies and makes the third computable**. One definition, per the `ineligible_code` pattern (`server.rs:3470-3484`). 3. **Point at the tool that can answer.** `safe_delete`'s FTS channel **already covers text-kind files** — all 113 here are in `files_fts`, no kind filter in the query — so "is this DataSet member actually used?" already has an honest answer today and nothing points at it. 4. **Skew:** additive field, both directions, non-empty payloads, per the I062 discipline. ## Test shape Registry gate: a fixture with code files, reference-bearing text files (`.xaml`, `.erb`, `.vue`), inert text (`.md`), and a refused `.Designer.cs`. Assert each text extension is named with the right count; that an `md`-only project reads as unremarkable while a `xaml`-heavy one is visibly dominated; and — **anti-vacuity** — that a project with **no** text files omits the block rather than reporting an empty one. **Mutation it must catch:** aggregating the extensions into a single total. That version is useless, and a test that still passes on it is grading the wrong axis. ## What to tell the customer Their 36% is **better than this repo's own Rust (24.5%)** and is not the thing to worry about — unresolved LINQ/BCL extension methods are correctly unresolved because the targets aren't in the project; the figure largely measures stdlib surface. The XAML/DataSet half is the real issue, and it is *more* consequential than "carries no symbols" sounds, because XAML holds genuine edges (`Click=`, `x:Name`, `{Binding}`) that no count in any payload currently reflects. ## Runtime-plugin architecture extension With #75, kind='text' is no longer the whole symbol-blind population. Coverage must be derived against the project’s active generation and requested package state. project_overview must distinguish, by extension/count: - text-only and intentionally symbol-blind under the active generation; - claimed by an active plugin and structurally indexed; - requested plugin not installed; - installed but ABI/capability/conformance rejected; - quarantined or failed activation while the prior generation remains active; - plugin-excluded/generated source such as Designer.cs; - permanently unclaimed. Do not subtract an extension from symbol_blind merely because a package manifest claims it. Only active contributions with a successful generation count as structural coverage. The block carries active generation identity and unavailable semantics for older daemons. Counts must come from the same project-scoped query/snapshot as the language/plugin coverage block in #80 so the disclosures cannot contradict each other. #81 remains independently shippable now: its initial implementation can report current text/excluded extensions. The schema should be additive so #80 can refine each extension into the states above without changing the meaning of the original count.
buildagent changed title from honesty: the vacuous-zero story — three drifted copies of one list, and no measure of the symbol-blind surface to honesty: disclose symbol-blind and plugin-unavailable coverage by extension 2026-08-26 13:39:08 +02:00
Author
Member

Delivered — closing, with one requirement deliberately inverted

symbol_blind_extensions ships in project_overview and is live in the installed v0.25.0 binary. Verified today against this repo:

symbol_blind: md 115, toml 27, json 5, sh 3, yml 3, csproj 1   (text_only_under_active_generation)
structural:   rust 418, ruby 13, python 9, typescript 8, javascript 7, php 7, csharp 6,
              de.h-dv.xaml/xaml 2                              (claimed_and_structurally_indexed)

The block also carries states (a closed vocabulary) and states_not_derived, which names each state no row can carry and why — so an absent state is never read as "none of those exist".

The gate this issue asked for

crates/mcp-server/tests/symbol_blind_coverage_e2e.rs:

  • every_symbol_blind_extension_is_named_separately
  • the_dominant_blind_extension_distinguishes_two_projects — the md-only vs xaml-heavy contrast
  • the_count_basis_is_measured_on_this_index

One requirement was inverted ON PURPOSE, and the test records why

This issue asked for the block to be omitted when there is nothing to report. The implementation reports a measured empty list instead, and says so in an_all_code_project_reports_a_measured_empty_list:

"#81 asks for the block to be omitted when there is nothing to report. This project's standing rule is stronger and wins."

An EMPTY list is a measurement — "we looked, there is nothing symbol-blind here". ABSENT means "this build did not report", which is a different fact with a different repair. Omitting on empty would collapse the two and is the exact defect the rest of this issue exists to prevent. Closing as delivered with that deviation standing.

Why it mattered, from the field

A customer session on a large WPF/C# solution independently reported "XAML and typed DataSets are symbol-blind, and C# reference resolution is 36%, so ref_count is a floor, not a measurement" — reaching that conclusion from this block plus count_basis. That is this issue working as intended on a repo none of us wrote.

## Delivered — closing, with one requirement deliberately inverted `symbol_blind_extensions` ships in `project_overview` and is live in the installed v0.25.0 binary. Verified today against this repo: ``` symbol_blind: md 115, toml 27, json 5, sh 3, yml 3, csproj 1 (text_only_under_active_generation) structural: rust 418, ruby 13, python 9, typescript 8, javascript 7, php 7, csharp 6, de.h-dv.xaml/xaml 2 (claimed_and_structurally_indexed) ``` The block also carries `states` (a closed vocabulary) and `states_not_derived`, which names each state no row can carry **and why** — so an absent state is never read as "none of those exist". ### The gate this issue asked for `crates/mcp-server/tests/symbol_blind_coverage_e2e.rs`: - `every_symbol_blind_extension_is_named_separately` - `the_dominant_blind_extension_distinguishes_two_projects` — the md-only vs xaml-heavy contrast - `the_count_basis_is_measured_on_this_index` ### One requirement was inverted ON PURPOSE, and the test records why This issue asked for the block to be **omitted** when there is nothing to report. The implementation reports a **measured empty list** instead, and says so in `an_all_code_project_reports_a_measured_empty_list`: > *"#81 asks for the block to be omitted when there is nothing to report. This project's standing rule is stronger and wins."* An EMPTY list is a measurement — "we looked, there is nothing symbol-blind here". ABSENT means "this build did not report", which is a different fact with a different repair. Omitting on empty would collapse the two and is the exact defect the rest of this issue exists to prevent. Closing as delivered with that deviation standing. ### Why it mattered, from the field A customer session on a large WPF/C# solution independently reported *"XAML and typed DataSets are symbol-blind, and C# reference resolution is 36%, so `ref_count` is a floor, not a measurement"* — reaching that conclusion from this block plus `count_basis`. That is this issue working as intended on a repo none of us wrote.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
h-dv/code-index#81
No description provided.