resolver: tier-3 import boost reaches any file whose BASENAME STEM matches an import segment, across crate boundaries — a single-candidate phantom #134

Closed
opened 2026-09-05 00:04:28 +02:00 by buildagent · 2 comments
Member

Found first-hand on 2026-09-05 while implementing #127. Not introduced by it: #127 only made the pre-existing rule produce a reachable phantom, and manifest_layering::no_resolved_edge_crosses_an_undeclared_crate_boundary caught it immediately.

The defect

index::reachable_predicate's own doc states the rule:

the candidate symbol's file either sits in the same directory as the ref's file, or is named by one of the ref file's import rows. Import matching mirrors the daemon's importers_of_file semantics (exact match on the candidate file's module-symbol names or basename stem, keyed through the temp file_keys table) plus a segment match via IMPORT_SEGMENTS.

A basename stem carries no crate, package or root. So an import of code_index_daemon::server::RPC_METHODS makes every server.rs in the workspace reachable from the importing file — including crates/mcp-server/src/server.rs, which lives in a crate code-index-daemon does not (and cannot) depend on.

The reproduction, verbatim

crates/daemon/tests/rpc_coverage_e2e.rs imports

use code_index_daemon::{server::RPC_METHODS, IndexAccess, RpcIndex};

and (as of #127) calls rpc.read_epoch(). There are four read_epoch definitions:

file stem reachable from that import?
crates/daemon/src/access.rs (IndexAccess::read_epoch) access no — the segment is IndexAccess, not access
crates/daemon/src/rpc_index.rs (RpcIndex::read_epoch) rpc_index no — the segment is RpcIndex
crates/daemon/src/local_index.rs (LocalIndex::read_epoch) local_index no
crates/mcp-server/src/server.rs (routing_tests::StubIndex::read_epoch) server yes

Exactly one candidate is reachable, so tier 3 resolves it. find_callers on the mcp-server symbol reports the bind directly:

crates/daemon/tests/rpc_coverage_e2e.rs:327  .read_epoch()
  target_id: 527422, resolution: "resolved", resolved_by: "tier3_import_boost"

and the gate names the edge:

resolved edges cross crate boundaries Cargo does not declare — these are phantoms,
and they reach users as `resolved` callers:
  crates/daemon -> crates/mcp-server (1 edge(s)):
    crates/daemon/tests/rpc_coverage_e2e.rs -> crates/mcp-server/src/server.rs

The two other rpc.read_epoch() call sites (crates/daemon/tests/reader_epoch_e2e.rs) stayed name_fallback — that file's imports reach more than one candidate, so tier 3 declines. The phantom is an artefact of the reachable set collapsing to ONE, which is exactly the shape the tier-3 gate is supposed to trust.

Why it is worse than one bad edge

  • It is silent. The row ships as resolution: "resolved" with a resolved_by that reads like provenance.
  • The stem is attacker-free but coincidence-rich: server.rs, common.rs, util.rs, config.rs, handle.rs, error.rs all repeat across crates in this workspace and in every customer repo.
  • It gets more likely as a trait grows impls, because each new impl adds a same-name method in a new file — one of which may be the only reachable one.
  • This is the same family as #52 (tier-1Q anchored on file stems with no invalidation).

What was NOT done, and why

The obvious fix — require the candidate file to be in a crate the ref's crate declares — is not available to the resolver: it has no Cargo knowledge, and legitimate cross-crate resolution (mcp-server -> daemon) is a large part of what tier 3 buys. A same-root guard would cause real recall loss. Filed rather than patched: reproduce the failure mode before changing the rule.

#127's lane worked around the single instance by making the one call site UFCS (IndexAccess::read_epoch(&rpc)), which makes the ref QUALIFIED and therefore structurally outside tier 3 (st.qualified = 0 in run_tier3_reachability). The comment at that call site says so and points here. That is a workaround for one site, not a fix.

Candidate directions

  1. Rank stem matches below module-symbol matches, and refuse a tier-3 decision whose sole candidate is a stem match. Costs recall wherever a stem match is the only evidence; measurable against the corpus ratchet and precision_gate.
  2. Exclude #[cfg(test)]-module symbols from the cross-file EXPORTED pool. The winning candidate here is routing_tests::StubIndex::read_epoch, a test double. This is one clause and structural, but it changes recall for every legitimate test-helper bind.
  3. Give file_keys a root/package column and require a stem match to agree on it. Needs a notion of "crate" the index does not have today.

Direction 1 or 2 needs a measured before/after (bind-for-bind, per the "inspect binds, not deltas" rule), not a count.

Found first-hand on 2026-09-05 while implementing #127. Not introduced by it: #127 only made the pre-existing rule produce a *reachable* phantom, and `manifest_layering::no_resolved_edge_crosses_an_undeclared_crate_boundary` caught it immediately. ## The defect `index::reachable_predicate`'s own doc states the rule: > the candidate symbol's file either sits in the same directory as the ref's file, **or is named by one of the ref file's import rows**. Import matching mirrors the daemon's `importers_of_file` semantics (exact match on the candidate file's module-symbol names **or basename stem**, keyed through the temp `file_keys` table) plus a segment match via `IMPORT_SEGMENTS`. A basename stem carries no crate, package or root. So an import of `code_index_daemon::server::RPC_METHODS` makes **every `server.rs` in the workspace** reachable from the importing file — including `crates/mcp-server/src/server.rs`, which lives in a crate `code-index-daemon` does not (and cannot) depend on. ## The reproduction, verbatim `crates/daemon/tests/rpc_coverage_e2e.rs` imports ```rust use code_index_daemon::{server::RPC_METHODS, IndexAccess, RpcIndex}; ``` and (as of #127) calls `rpc.read_epoch()`. There are four `read_epoch` definitions: | file | stem | reachable from that import? | |---|---|---| | `crates/daemon/src/access.rs` (`IndexAccess::read_epoch`) | `access` | no — the segment is `IndexAccess`, not `access` | | `crates/daemon/src/rpc_index.rs` (`RpcIndex::read_epoch`) | `rpc_index` | no — the segment is `RpcIndex` | | `crates/daemon/src/local_index.rs` (`LocalIndex::read_epoch`) | `local_index` | no | | `crates/mcp-server/src/server.rs` (`routing_tests::StubIndex::read_epoch`) | **`server`** | **yes** | Exactly one candidate is reachable, so tier 3 resolves it. `find_callers` on the mcp-server symbol reports the bind directly: ``` crates/daemon/tests/rpc_coverage_e2e.rs:327 .read_epoch() target_id: 527422, resolution: "resolved", resolved_by: "tier3_import_boost" ``` and the gate names the edge: ``` resolved edges cross crate boundaries Cargo does not declare — these are phantoms, and they reach users as `resolved` callers: crates/daemon -> crates/mcp-server (1 edge(s)): crates/daemon/tests/rpc_coverage_e2e.rs -> crates/mcp-server/src/server.rs ``` The two other `rpc.read_epoch()` call sites (`crates/daemon/tests/reader_epoch_e2e.rs`) stayed `name_fallback` — that file's imports reach more than one candidate, so tier 3 declines. **The phantom is an artefact of the reachable set collapsing to ONE**, which is exactly the shape the tier-3 gate is supposed to trust. ## Why it is worse than one bad edge * It is silent. The row ships as `resolution: "resolved"` with a `resolved_by` that reads like provenance. * The stem is attacker-free but coincidence-rich: `server.rs`, `common.rs`, `util.rs`, `config.rs`, `handle.rs`, `error.rs` all repeat across crates in this workspace and in every customer repo. * It gets *more* likely as a trait grows impls, because each new impl adds a same-name method in a new file — one of which may be the only reachable one. * This is the same family as #52 (tier-1Q anchored on file stems with no invalidation). ## What was NOT done, and why The obvious fix — require the candidate file to be in a crate the ref's crate declares — is not available to the resolver: it has no Cargo knowledge, and *legitimate* cross-crate resolution (`mcp-server` -> `daemon`) is a large part of what tier 3 buys. A same-root guard would cause real recall loss. Filed rather than patched: reproduce the failure mode before changing the rule. **#127's lane worked around the single instance** by making the one call site UFCS (`IndexAccess::read_epoch(&rpc)`), which makes the ref QUALIFIED and therefore structurally outside tier 3 (`st.qualified = 0` in `run_tier3_reachability`). The comment at that call site says so and points here. That is a workaround for one site, not a fix. ## Candidate directions 1. **Rank stem matches below module-symbol matches**, and refuse a tier-3 decision whose sole candidate is a stem match. Costs recall wherever a stem match is the only evidence; measurable against the corpus ratchet and `precision_gate`. 2. **Exclude `#[cfg(test)]`-module symbols from the cross-file EXPORTED pool.** The winning candidate here is `routing_tests::StubIndex::read_epoch`, a test double. This is one clause and structural, but it changes recall for every legitimate test-helper bind. 3. **Give `file_keys` a root/package column** and require a stem match to agree on it. Needs a notion of "crate" the index does not have today. Direction 1 or 2 needs a measured before/after (bind-for-bind, per the "inspect binds, not deltas" rule), not a count.
Author
Member

Two follow-ups from the #165/#167 lane that bear directly on this issue's own reasoning. Both are corrections in your favour.

1. The gate you added was already there, and already broken

#165 reads as "a defect in #134 as merged". It is not. The IMPORT_SEGMENTS GLOB ('*' || fp.pkg_tail || '.*') comparison — a kebab-case package DIRECTORY tail tested against a snake_case import module — entered on tier 1b's name-import and container-import arms in 722fbf6 (I023, 2026-07-20) and has shipped in 64 releases since v0.5.15. 2f16e22 copied I046's gate into tier 3's Edge 2, exactly as its comment says it does, and that is what finally made the loss visible: on rust-analyzer only tier3_import_boost (10321 → 9617) and tier1q_pass1/tier1r_receiver moved with your commit, while tier1b_name_import (5084) and tier1b_container_import (1490) were identical before and after it — and the separator fix moves those two by +2106 and +150.

So this issue's direction-3 ("give file_keys a root/package column and require a stem match to agree on it") was right, and the reason it looked like a −58% recall loss was a spelling bug two months older than the gate. With the fold in place the gate is a net +15 246 on rust-analyzer, 99.8 % of it into hyphenated crates, and the Crate@327 bind you would want removed stays removed while HirFileId@331 comes back.

2. Direction 3 has a second half nobody has evidence for

temp.file_pkg.pkg_dir spells two different facts the same way: "the nearest manifest is at the repository root" and "no manifest covers me at all". The origin gate's middle disjunct reads '' as the first, so in any tree where the walker finds no manifest, COALESCE(fpr.pkg_dir,'') = fp.pkg_dir is true of every pair in the tree and this gate is silently off. #167 is that state reached through a harness; gitignored, oversized or simply absent manifests reach it in production.

I implemented the fix and refused it, because splitting the two spellings is only half — the other half is a fallback partition for manifest-less trees, and there is no ground truth to pick one:

  • package_root_of (the parent directory) breaks three tier-3 fixtures, by the same split I046 measured as 67 lost ripgrep resolutions;
  • the top-level directory keeps those three and breaks four others, one of them by admitting a bind the fixture calls a phantom outright (OrphanOp, the C# monorepo);
  • neither is measurable on the pinned corpus — all nine repos carry discoverable manifests, so the fallback never fires and the full bind digest is byte-identical under both.

Every fixture disagrees because this gate has never been exercised in a manifest-less fixture: the old '' = '' kept it switched off in all of them. Recorded in index::nearest_package_dir and in _prdoc/records/84-P4-parity-deltas.md; what would settle it is a manifest-less corpus repo, which is a corpus change rather than a resolver one.

3. Your fixture's blind spot, closed

tier3_origin_gate.rs is a good fixture and it could not have caught #165: its crates are alpha and beta. Neither could the tier-1 corpus — ripgrep's crates are core, globset, grep, ignore, matcher, pcre2, printer, regex, searcher, cli. The precision gate now stages a hyphenated package for rust (crates/hyphen-pkg imported as hyphen_pkg) and javascript (packages/ui-kit required as ui-kit, where the two spellings agree), and the pair is load-bearing: folding only the segment side leaves the rust probe GREEN and the javascript one RED.

🤖 Generated with Claude Code

https://claude.ai/code/session_01K1zj5VcFJvJt3pQxe9259K

Two follow-ups from the #165/#167 lane that bear directly on this issue's own reasoning. Both are corrections in your favour. ## 1. The gate you added was already there, and already broken #165 reads as "a defect in #134 as merged". It is not. The `IMPORT_SEGMENTS GLOB ('*' || fp.pkg_tail || '.*')` comparison — a kebab-case package DIRECTORY tail tested against a snake_case import module — entered on tier 1b's **name-import** and **container-import** arms in `722fbf6` (I023, 2026-07-20) and has shipped in **64 releases** since v0.5.15. `2f16e22` copied I046's gate into tier 3's Edge 2, exactly as its comment says it does, and that is what finally made the loss visible: on `rust-analyzer` only `tier3_import_boost` (10321 → 9617) and `tier1q_pass1`/`tier1r_receiver` moved with your commit, while `tier1b_name_import` (5084) and `tier1b_container_import` (1490) were **identical before and after it** — and the separator fix moves those two by +2106 and +150. So this issue's direction-3 ("give `file_keys` a root/package column and require a stem match to agree on it") was right, and the reason it looked like a −58% recall loss was a spelling bug two months older than the gate. With the fold in place the gate is a **net +15 246** on rust-analyzer, 99.8 % of it into hyphenated crates, and the `Crate@327` bind you would want removed stays removed while `HirFileId@331` comes back. ## 2. Direction 3 has a second half nobody has evidence for `temp.file_pkg.pkg_dir` spells **two different facts the same way**: "the nearest manifest is at the repository root" and "no manifest covers me at all". The origin gate's middle disjunct reads `''` as the first, so in any tree where the walker finds no manifest, `COALESCE(fpr.pkg_dir,'') = fp.pkg_dir` is true of **every pair in the tree** and this gate is silently off. #167 is that state reached through a harness; gitignored, oversized or simply absent manifests reach it in production. I implemented the fix and **refused it**, because splitting the two spellings is only half — the other half is a fallback partition for manifest-less trees, and there is no ground truth to pick one: * `package_root_of` (the parent directory) breaks **three** tier-3 fixtures, by the same split I046 measured as 67 lost ripgrep resolutions; * the top-level directory keeps those three and breaks **four** others, one of them by admitting a bind the fixture calls a phantom outright (`OrphanOp`, the C# monorepo); * neither is measurable on the pinned corpus — all nine repos carry discoverable manifests, so the fallback never fires and the full bind digest is byte-identical under both. Every fixture disagrees because **this gate has never been exercised in a manifest-less fixture**: the old `'' = ''` kept it switched off in all of them. Recorded in `index::nearest_package_dir` and in `_prdoc/records/84-P4-parity-deltas.md`; what would settle it is a manifest-less corpus repo, which is a corpus change rather than a resolver one. ## 3. Your fixture's blind spot, closed `tier3_origin_gate.rs` is a good fixture and it could not have caught #165: its crates are `alpha` and `beta`. Neither could the tier-1 corpus — ripgrep's crates are `core`, `globset`, `grep`, `ignore`, `matcher`, `pcre2`, `printer`, `regex`, `searcher`, `cli`. The precision gate now stages a hyphenated package for **rust** (`crates/hyphen-pkg` imported as `hyphen_pkg`) and **javascript** (`packages/ui-kit` required as `ui-kit`, where the two spellings agree), and the pair is load-bearing: folding only the segment side leaves the rust probe GREEN and the javascript one RED. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01K1zj5VcFJvJt3pQxe9259K
Author
Member

Triage 2026-09-06: CLOSING. Direction 3 landed, the origin gate is one clause in two funnels, and the precision gate is 7/7 with phantoms=0 — verified with the corpus actually mounted.

Verified against master, not from a lane report. Analysis in the (closed) #165; fix in 2f16e22 and efccc89.

What landed, and why it is not a heuristic

2f16e22 records the diagnosis: this was duplicated-rule drift, not the tradeoff the issue feared. Tier 1b's file-key arm has carried the package-origin gate since I046, and import_key_rel's own column comment said outright that tier 3 carried no origin gate at all. Tier 3's Edge 2 now reads the same three disjuncts from the same relation — index::reachable_predicate, crates/indexer/src/index.rs:2211. No new rule, no new heuristic, and none of the three risky directions this issue named.

efccc89 then found the older half: a package directory (hir-expand) and an import (hir_expand) name the same package differently, so the gate computed "hir_expand".ends_with("hir-expand") and refused every legitimate cross-crate bind into a hyphenated crate. One clause, two funnels — fold_pkg_sep at index.rs:1850, fold_pkg_sep_sql at :1194 — applied once at the temp.file_pkg insert so every reader inherits it. That defect was two months old (I023, shipped in 64 releases); #134's gate is what made it measurable.

Measured bind-for-bind, as this issue demanded — not by counting

rust-analyzer, against the pre-fix binary, binds diffed and read at source: +16717 gained, −1471 withdrawn, net +15246 (127867 → 143113). 99.8% of gains target a hyphenated crate. Withdrawals are the good direction (549 were .clone() on an arbitrary receiver bound to syntax::Parse<T>::clone), and all 109 re-pointings moved a call off the wrong crate's same-named method onto the one its use names. Phantoms bound from an oracle outside the resolver (each crate's own Cargo.toml): 16444 of the gains cross a declared boundary, 229 of the remaining 231 travel a real re-export, and the last two are phantoms — filed as #168. Undeclared-cross-crate rate 3.383% → 2.534%.

The other eight pinned repos are byte-identical, bind-for-bind and rule-for-rule.

The gate was structurally blind, and now is not

No fixture and no tier-1 corpus repo had a hyphenated package directory, which is why a 58% recall loss reached a bless decision. write_hyphen_pkg_decoys — crates/daemon/tests/precision_gate.rs:505 — stages one for rust (directory and import spelled differently) and javascript (spelled the same). The pair is load-bearing: folding only the segment side leaves the rust probe green and the javascript one red.

Runs (all exit 0, corpus mounted)

cargo test -p code-index-indexer --test tier3_origin_gate -- --nocapture     → 2 passed
cargo test -p code-index-indexer --test manifest_layering -- --nocapture     → 1 passed
    (no_resolved_edge_crosses_an_undeclared_crate_boundary, repo-wide)
cargo test -p code-index-daemon  --test precision_gate -- --nocapture        → 7/7, recall 1.000, phantoms=0 every language
COSI_CORPUS_DIR=… COSI_CORPUS_REQUIRE=1 cargo test --release -p code-index-indexer --test corpus_ratchet
    → executed=7 unavailable=0 controls=14
COSI_CORPUS_DIR=… COSI_CORPUS_REQUIRE=1 cargo test --release -p code-index-indexer --test corpus_tier3_ratchet
    → executed=2 controls=8; rust-analyzer 143113 resolved

Baseline md5s match #165's closing comment exactly: baseline.json 914dda1a…, tier3-baseline.json 94abf592…, stage-baseline.json 7d9695be….

Three residuals, none hidden

  1. The original reproduction is MASKED, not removed. #127's UFCS workaround is still live at crates/daemon/tests/rpc_coverage_e2e.rs:341 (IndexAccess::read_epoch(&rpc)), and its comment at :329-340 still calls itself a workaround for one site. manifest_layering covers the class repo-wide, but reverting that one call to rpc.read_epoch() is the single strongest available proof and it has not been taken. Cheap, and worth doing.
  2. The gate is silently OFF in manifest-less trees. "" spells both "covered by the root manifest" and "covered by no manifest", and the middle disjunct reads it as the first. Documented on index::nearest_package_dir, index.rs:1979-2015. Two fallback partitions were implemented and refused for lack of ground truth — recorded in _prdoc/records/84-P4-parity-deltas.md:232-241, not guessed at.
  3. #168 — the 2 remaining phantoms, from package_root_of counting a top-level lib/ as a source dir (SRC_DIRS, index.rs:2044). Owned elsewhere.

Also recorded rather than fixed: the C# extension pass still carries no origin gate, noted at the site because narrowing it owes its own measurement.

Closing on (1)-(3) being named and tracked, and the reported defect class being gated repo-wide with zero phantoms.

🤖 Triage lane, 2026-09-06, master 45cf6e4

## Triage 2026-09-06: CLOSING. Direction 3 landed, the origin gate is one clause in two funnels, and the precision gate is 7/7 with `phantoms=0` — verified with the corpus actually mounted. Verified against master, not from a lane report. Analysis in the (closed) **#165**; fix in `2f16e22` and `efccc89`. ### What landed, and why it is not a heuristic `2f16e22` records the diagnosis: this was **duplicated-rule drift, not the tradeoff the issue feared**. Tier 1b's file-key arm has carried the package-origin gate since I046, and `import_key_rel`'s own column comment said outright that tier 3 carried no origin gate at all. Tier 3's Edge 2 now reads the **same three disjuncts from the same relation** — `index::reachable_predicate`, `crates/indexer/src/index.rs:2211`. No new rule, no new heuristic, and **none of the three risky directions this issue named**. `efccc89` then found the older half: a package *directory* (`hir-expand`) and an *import* (`hir_expand`) name the same package differently, so the gate computed `"hir_expand".ends_with("hir-expand")` and refused every legitimate cross-crate bind into a hyphenated crate. One clause, two funnels — `fold_pkg_sep` at `index.rs:1850`, `fold_pkg_sep_sql` at `:1194` — applied once at the `temp.file_pkg` insert so every reader inherits it. That defect was **two months old** (I023, shipped in 64 releases); #134's gate is what made it measurable. ### Measured bind-for-bind, as this issue demanded — not by counting rust-analyzer, against the pre-fix binary, binds diffed and **read at source**: +16717 gained, −1471 withdrawn, net **+15246** (127867 → 143113). 99.8% of gains target a hyphenated crate. Withdrawals are the good direction (549 were `.clone()` on an arbitrary receiver bound to `syntax::Parse<T>::clone`), and all 109 re-pointings moved a call off the wrong crate's same-named method onto the one its `use` names. Phantoms bound from an oracle **outside** the resolver (each crate's own `Cargo.toml`): 16444 of the gains cross a declared boundary, 229 of the remaining 231 travel a real re-export, and the last **two** are phantoms — filed as **#168**. Undeclared-cross-crate rate 3.383% → **2.534%**. The other eight pinned repos are byte-identical, bind-for-bind and rule-for-rule. ### The gate was structurally blind, and now is not No fixture and no tier-1 corpus repo had a hyphenated package directory, which is why a 58% recall loss reached a bless decision. `write_hyphen_pkg_decoys` — `crates/daemon/tests/precision_gate.rs:505` — stages one for rust (directory and import spelled differently) **and** javascript (spelled the same). The pair is load-bearing: folding only the segment side leaves the rust probe green and the javascript one red. ### Runs (all exit 0, corpus mounted) ``` cargo test -p code-index-indexer --test tier3_origin_gate -- --nocapture → 2 passed cargo test -p code-index-indexer --test manifest_layering -- --nocapture → 1 passed (no_resolved_edge_crosses_an_undeclared_crate_boundary, repo-wide) cargo test -p code-index-daemon --test precision_gate -- --nocapture → 7/7, recall 1.000, phantoms=0 every language COSI_CORPUS_DIR=… COSI_CORPUS_REQUIRE=1 cargo test --release -p code-index-indexer --test corpus_ratchet → executed=7 unavailable=0 controls=14 COSI_CORPUS_DIR=… COSI_CORPUS_REQUIRE=1 cargo test --release -p code-index-indexer --test corpus_tier3_ratchet → executed=2 controls=8; rust-analyzer 143113 resolved ``` Baseline md5s match #165's closing comment exactly: `baseline.json 914dda1a…`, `tier3-baseline.json 94abf592…`, `stage-baseline.json 7d9695be…`. ### Three residuals, none hidden 1. **The original reproduction is MASKED, not removed.** #127's UFCS workaround is still live at `crates/daemon/tests/rpc_coverage_e2e.rs:341` (`IndexAccess::read_epoch(&rpc)`), and its comment at `:329-340` still calls itself a workaround for one site. `manifest_layering` covers the class repo-wide, but **reverting that one call to `rpc.read_epoch()` is the single strongest available proof and it has not been taken.** Cheap, and worth doing. 2. **The gate is silently OFF in manifest-less trees.** `""` spells both "covered by the root manifest" and "covered by no manifest", and the middle disjunct reads it as the first. Documented on `index::nearest_package_dir`, `index.rs:1979-2015`. Two fallback partitions were implemented and **refused** for lack of ground truth — recorded in `_prdoc/records/84-P4-parity-deltas.md:232-241`, not guessed at. 3. **#168** — the 2 remaining phantoms, from `package_root_of` counting a top-level `lib/` as a source dir (`SRC_DIRS`, `index.rs:2044`). Owned elsewhere. Also recorded rather than fixed: the C# extension pass still carries no origin gate, noted at the site because narrowing it owes its own measurement. Closing on (1)-(3) being named and tracked, and the reported defect class being gated repo-wide with zero phantoms. 🤖 Triage lane, 2026-09-06, master `45cf6e4`
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.

Dependencies

No dependencies set

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