Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1623,6 +1623,17 @@ unqualified name receive a global candidate only when that name is unique in the
symbol set. Otherwise they remain `ambiguous` or `unresolved`, and dependency queries do not
fall back to a same-name edge.

C# type-reference resolution uses `LogicalPartialSymbolGrouper` for declarations that have a
valid logical partial-family identity. Full and scoped refreshes persist the same stable
`family:` target key used by grouped symbol discovery, so multiple physical declarations in one
language/kind/namespace-and-container/generic-arity family produce `resolved_group` rather than
semantic ambiguity. `resolution_candidate_count` deliberately remains the physical declaration
count, and `symbol_reference_candidates` retains every physical symbol row. Search ranking,
grouped hotspots, inspect, dependencies, and impact consume the logical identity while APIs that
list definitions remain deterministic and physical. The reference-identity contract version
must be advanced when this key changes; version 9 forces full, scoped, no-op, and deletion-only
index paths to replace older physical-path target keys before identity-aware reads become ready.

C# common member names are never discarded during extraction. The writer persists their
receiver/type evidence in `target_qualifier`, and reference finalization records
`resolution_state`. Bare-name `references` and unqualified graph discovery remain broad and
Expand Down Expand Up @@ -5579,6 +5590,17 @@ resolution を再構築し、同じ transaction で marker を設定します。
対象となる symbol 集合で名前が一意の場合だけ global candidate を持ちます。それ以外は
`ambiguous` または `unresolved` のままとし、dependency query は同名 edge へ fallback しません。

C# の type-reference resolution は、有効な論理 partial-family identity を持つ declaration に
`LogicalPartialSymbolGrouper` を使用します。full / scoped refresh は grouped symbol discovery と同じ
安定した `family:` target key を永続化するため、language、kind、namespace / container、generic arity が
同じ 1 family 内の複数物理 declaration は semantic ambiguity ではなく `resolved_group` になります。
`resolution_candidate_count` は意図的に物理 declaration 数のままとし、
`symbol_reference_candidates` はすべての物理 symbol row を保持します。search ranking、grouped hotspot、
inspect、dependency、impact は論理 identity を使用し、definition 一覧 API は決定的な物理定義を維持します。
この key を変更するときは reference-identity contract version を進める必要があります。version 9 は
identity-aware read を ready にする前に、full、scoped、no-op、削除のみの index path で旧来の
物理 path target key を置き換えます。

C# の一般的な member 名は extraction 時に破棄しません。writer は receiver / 型の evidence を
`target_qualifier` に永続化し、reference finalization は `resolution_state` を記録します。bare-name の
`references` と無修飾 graph discovery は広い検索結果と保存済み resolution label を維持します。一方、
Expand Down
2 changes: 2 additions & 0 deletions TESTING_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Use the full suite by default. Use targeted filters only while iterating locally
- Reference-identity refresh coverage treats a stable graph rebuild as a physical-write performance contract. Keep NULL-safe changed-row predicates for source identity, the four-column target-resolution tuple, self-reference, and mutual-recursion updates; trigger audits must remain at zero on a stable rerun, repair each corrupted phase once, and prove a later-phase failure rolls back earlier identity writes. SQLite `changes()` must continue to report the final mutual-recursion phase.
- Fresh-reference resolution coverage belongs in `FreshReferenceResolutionTests`. Keep the empty/rebuild/symbols-only policy truth table, the unchanged 14-parameter insert shape with distinct fresh/ordinary SQL cache entries, canonical provisional values, the materialized candidate-side aggregation shape, and exact fresh-versus-full semantic parity for `unresolved`, `resolved`, `resolved_group`, `ambiguous`, and self-reference rows across C# and a non-C# language. The fresh insert must preserve literal input order, choose same-file nested source symbols with the ordinary containment tie-break across C# and Python, leave out-of-range sources NULL, and omit the final source UPDATE; ordinary full and differential repair paths remain covered separately. Failure tests must prove that fresh defaults remain pending after graph rollback and clear only after a successful commit. Pair these database tests with the full-scan bulk-load theory that observes `unresolved` provisional rows on a fresh CLI scan and NULL resolution state on rebuild. MCP remains outside this opt-in because its per-file durable transactions require the existing graph-failure retry contract.
A full-scan barrier regression must commit a candidate-free row from a second connection after the early empty observation but before the outer write transaction, then prove transaction-local revalidation switches to ordinary full resolution and normalizes that row.
- Logical C# partial-family reference coverage is split between `FreshReferenceResolutionTests` and `IndexCommandRunnerUpdateTests`. Keep direct database fixtures for partial class, struct, record, and generic families, plus namespace and arity separation, and assert that one logical family persists `resolved_group` with a stable family target while `resolution_candidate_count` and candidate rows retain every physical declaration. The CLI lifecycle fixture must cover member references across family files, add/remove/rename/move updates, prior-contract restamping, grouped reference ranking, hotspots, inspect, dependencies, impact, and deterministic ungrouped definitions. Full and scoped refreshes must remain semantically identical, and unrelated same-leaf families must stay ambiguous.
- C# reference-graph fact coverage is an SQL-shape performance contract. Each of the six managed arity/receiver/value-type functions must occur once only in its reference or symbol materialization statement, and full, scoped, and retained refresh chains must populate reference, symbol, type-identity, and constructor-identity facts in that order before normalization and candidate consumers. Candidate SQL must use the WITHOUT ROWID fact primary keys without retaining project/file-local identity construction or constructor-owner range scans. Keep full/scoped/retained semantic snapshots across partial generic and file-local constructors, primary constructors with same-leaf generic arities, scoped target-definition mutations, fallback owners, legacy NULL identities, stale-row cleanup, and refresh rollback/retry alongside the focused property-receiver regressions.
- Rank-5 C# instantiation fallback coverage must keep the set-based SQL shape and its semantic oracle together. Require exactly four materialized stages for type members, unique families, family-driven constructor members, and constructor summaries; at most the one lower-rank correlated subquery; and an indexed `constructor` search rather than a physical constructor scan. The shared behavior fixture must retain raw-case fold collisions, exact and NULL-wildcard arity, deterministic partial representatives, constructor overloads, class/record implicit defaults, value-type zero-argument rules, enum/delegate handling, ambiguous families, and lower-rank suppression.
- C# metadata-target resolver coverage treats propagation work and stable reruns as performance contracts. Keep the reverse-ordered 8,000-class chain at exactly `n - 1` dependency edges and `n` queue visits instead of using a wall-clock threshold; retain cross-file partial fan-in, an unseeded cycle, pre-cancellation, rollback of an earlier row after an injected later update failure, zero trigger-audited writes on a stable rerun, and exactly one write when repairing a corrupted derived row.
Expand Down Expand Up @@ -1163,6 +1164,7 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests"
- reference identity refresh coverage は、安定graphの再構築を物理writeのperformance contractとします。source identity、target resolutionの4列tuple、self reference、mutual recursionの更新にはNULL-safeなchanged-row predicateを維持し、安定rerunのtrigger auditは0、各corrupt phaseのrepairは1回、後段phaseの失敗で先行identity writeもrollbackされることを検証してください。SQLite `changes()` は引き続き最後のmutual-recursion phaseを表します。
- fresh reference resolutionのcoverageは`FreshReferenceResolutionTests`が担当します。empty/rebuild/symbols-onlyのpolicy truth table、fresh/ordinaryでSQL cache entryを分けても14 parameterのinsert shapeが不変であること、canonicalな暫定値、candidate側materialized aggregationのSQL shape、およびC#と非C#言語を横断する`unresolved`、`resolved`、`resolved_group`、`ambiguous`、self-referenceのfresh/full完全同値を維持してください。fresh insertはliteral input順序を保ち、C# / Pythonの同一file nested source symbolを通常の包含tie-breakで選び、range外sourceをNULLのままにして、最終source UPDATEを省略する必要があります。通常fullとdifferentialのrepair経路は別途coverageを維持します。failure testはgraph rollback後もfresh defaultsがpendingのままで、成功commit後にだけ解除されることを証明します。database testは、fresh CLI scanで暫定`unresolved`、rebuildでNULL resolution stateを観測するfull-scan bulk-load theoryと対にしてください。MCPはfile単位のdurable transactionが既存graph失敗再試行契約を必要とするため、このopt-inの対象外です。
full-scan barrier回帰では、早期empty確認後からouter write transaction開始前の間に別connectionからcandidate-free rowをcommitし、transaction内の再検証が通常のfull resolutionへ切り替わってそのrowを正規化することを必須とします。
- C# の論理 partial-family reference coverage は `FreshReferenceResolutionTests` と `IndexCommandRunnerUpdateTests` が分担します。partial class、struct、record、generic family、および namespace / arity の分離を直接 database fixture で維持し、1つの論理 family が安定した family target の `resolved_group` になりつつ、`resolution_candidate_count` と candidate row が全物理 declaration を保持することを検証してください。CLI lifecycle fixture は family file をまたぐ member reference、add / remove / rename / move update、旧 contract の restamp、grouped reference ranking、hotspot、inspect、dependency、impact、決定的な ungrouped definition を網羅します。full / scoped refresh の意味を同一に保ち、無関係な same-leaf family は曖昧なままにしてください。
- C# reference-graph fact coverage は SQL shape の performance contract です。arity / receiver / value-type を求める6つの managed function は reference または symbol の materialization statement 内にそれぞれ1回だけ置き、full / scoped / retained refresh chain は reference、symbol、type identity、constructor identity の fact をこの順で normalization と candidate consumer より前に投入してください。candidate SQL は WITHOUT ROWID fact の主キーを使い、project / file-local identity の再構築や constructor-owner range の再走査を残してはいけません。partial generic / file-local constructor、同名別 generic arity を持つ primary constructor、scoped target 定義変更、fallback owner、legacy NULL identity、stale row cleanup、refresh rollback / retry の full / scoped / retained semantic snapshot と、focused property-receiver regression を維持します。
- rank 5 の C# instantiation fallback coverage は、集合処理 SQL shape と semantic oracle を同じ契約として維持してください。type member、一意 family、family 起点の constructor member、constructor summary の materialized stage は厳密に4つ、相関 subquery は lower-rank 用の最大1つとし、物理 constructor scan ではなく indexed `constructor` search を要求します。共有 behavior fixture では raw-case の fold collision、exact / NULL-wildcard arity、partial type の決定的な代表、constructor overload、class / record の implicit default、value type の zero-argument 規則、enum / delegate、曖昧 family、lower-rank suppression を残してください。
- C# metadata-target resolver coverage は propagation work と安定 rerun を performance contract とします。逆順に保存した 8,000 class の chain では wall-clock threshold を使わず、dependency edge が厳密に `n - 1`、queue visit が `n` であることを維持してください。cross-file partial fan-in、seed を持たない cycle、事前 cancel、後段 update の注入失敗時に先行 row も rollback されること、安定 rerun の trigger audit が write 0 回、破損した derived row の修復が厳密に 1 write であることも残します。
Expand Down
13 changes: 11 additions & 2 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,12 @@ exit `1` with a bounded correction or nearest-command/subcommand suggestion.
Fresh indexes resolve reference edges against symbol identity instead of joining folded
names alone. `references --json` reports `target_symbol_id`, `target_symbol_key`,
`resolution_state`, and `resolution_candidate_count` when available. `resolved` identifies
one definition, `resolved_group` identifies one overload family, and `ambiguous` /
one definition, while `resolved_group` identifies one overload or logical C# partial-type family.
For a partial family, `target_symbol_key` is the stable logical-family identity and
`resolution_candidate_count` remains the number of physical candidate declarations. Those
physical definitions remain available through definition and inspection results. Candidates
from different namespaces/containers, declaration kinds, generic arities, or languages do not
collapse into one family and remain safely ambiguous. `ambiguous` /
`unresolved` keep the edge explicit without letting C# `callers`, `callees`, or `deps`
silently connect it to an unrelated same-named definition. Legacy databases keep the
name-based read fallback until an indexing run refreshes this metadata and stamps its
Expand Down Expand Up @@ -3974,7 +3979,11 @@ release changelog を source of truth とします。全 command の完全な sy
新しい index は、folded name だけを結合せず symbol identity に対して reference edge を
解決します。`references --json` は利用可能な場合に `target_symbol_id`、
`target_symbol_key`、`resolution_state`、`resolution_candidate_count` を返します。
`resolved` は単一定義、`resolved_group` は単一 overload family を示し、`ambiguous` /
`resolved` は単一定義、`resolved_group` は単一 overload family または C# の論理 partial 型 family を
示します。partial family では `target_symbol_key` が安定した論理 family identity となり、
`resolution_candidate_count` は物理 candidate declaration 数のままです。物理定義は definition と
inspect の結果から引き続き参照できます。namespace / container、declaration kind、generic arity、
language が異なる candidate は 1 family に統合せず、安全に曖昧なままにします。`ambiguous` /
`unresolved` は edge を明示したまま、C# の `callers`、`callees`、`deps` が無関係な
同名定義へ暗黙に接続することを防ぎます。legacy DB は、次回の index 実行でこの metadata
を再構築して contract version を記録するまで name-based read fallback を維持します。
Expand Down
25 changes: 25 additions & 0 deletions changelog.d/unreleased/5158.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
category: fixed
issues:
- 5158
affected:
- src/CodeIndex/Database/DbContext.SchemaMetadata.cs
- src/CodeIndex/Database/DbReader.SymbolSearchListQueryBuilder.cs
- src/CodeIndex/Database/DbSymbolReader.Hotspots.cs
- src/CodeIndex/Database/DbWriter.ReferenceGraphRefreshScope.cs
- src/CodeIndex/Database/DbWriter.References.cs
- src/CodeIndex/Database/LogicalPartialSymbolGrouper.cs
- tests/CodeIndex.Tests/FreshReferenceResolutionTests.cs
- tests/CodeIndex.Tests/IndexCommandRunnerUpdateTests.cs
- USER_GUIDE.md
- DEVELOPER_GUIDE.md
- TESTING_GUIDE.md
---

## English

- **C# references now resolve one logical partial-type family (#5158)** — references whose physical candidates all belong to one partial class, struct, record, interface, or generic family persist a stable logical target as `resolved_group`, retain the physical candidate count and definitions, and feed grouped symbol ranking, hotspots, inspect, dependencies, and impact without merging unrelated same-name families.

## 日本語

- **C# reference が単一の論理 partial 型 family へ解決されるようになりました (#5158)** — 物理 candidate がすべて同じ partial class、struct、record、interface、または generic family に属する reference は、安定した論理 target を `resolved_group` として永続化します。物理 candidate 数と定義を保持し、無関係な同名 family を統合せず、grouped symbol ranking、hotspot、inspect、dependency、impact へ参照を反映します。
10 changes: 7 additions & 3 deletions src/CodeIndex/Database/DbContext.SchemaMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,22 @@ public static string BuildIncompleteHotspotFamilyMarkerFingerprint(string? finge
public const string SqlGraphContractVersionMetaKey = "sql_graph_contract_version";
public const int HdlGraphContractVersion = 1;
public const string HdlGraphContractVersionMetaKey = "hdl_graph_contract_version";
// Version 8 (#4914) invalidates C# candidates whose partial family identity did not
// Version 9 (#5158) invalidates references resolved with physical declaration paths
// instead of authoritative logical C# partial-family identities. Version 8 (#4914)
// invalidates C# candidates whose partial family identity did not
// distinguish namespace boundaries from nested-type boundaries. Version 7 (#4914)
// invalidated candidates written before file-local partial families carried source-file
// identity. Version 6 (#4850) previously separated constructor
// callables from logical partial-type families; version 5 (#4846) made Markdown fragment
// resolution document/path-scoped.
// バージョン 8 (#4914) では namespace 境界と nested-type 境界を区別しない partial family
// バージョン 9 (#5158) では、正式な C# logical partial-family identity ではなく
// physical declaration path で解決した reference を無効化する。バージョン 8 (#4914) では
// namespace 境界と nested-type 境界を区別しない partial family
// identity を持つ C# candidate を無効化する。バージョン 7 (#4914) では、file-local partial
// family が source-file identity を持つ前の C# candidate を無効化する。バージョン 6 (#4850) は constructor callable と logical
// partial type family を分離し、バージョン 5 (#4846) は Markdown fragment 解決を
// document/path 内に限定した。
public const int ReferenceIdentityContractVersion = 8;
public const int ReferenceIdentityContractVersion = 9;
public const string ReferenceIdentityContractVersionMetaKey = "reference_identity_contract_version";
public static string GetDynamicReferenceGraphContractVersionMetaKey(string lang) =>
$"dynamic_reference_graph_contract_version_{lang}";
Expand Down
Loading
Loading