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
17 changes: 17 additions & 0 deletions DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2241,6 +2241,15 @@ case-sensitive; unknown values use the versioned `E010_USAGE_ERROR` command
error when JSON is requested, and discovery runs before query or database
access.

For `impact`, the `file_impacts` collection derives its allowed leaves from
`FileDependencyResult`: `result_kind`, `source_path`, `target_path`,
`source_db`, `target_db`, `reference_count`, `ranking_score`, `symbols`, and
`evidence`. Compact file-impact rows retain `source_path`, `target_path`,
`reference_count`, and `result_kind`, so every non-empty row remains
self-identifying. The ambiguous `file_impacts.path` and `file_impacts.file`
aliases are rejected; callers and definitions keep their established path
aliases.

`inspect` keeps a dedicated typed schema in the same registry because its
established JSON bundle is not a shared bounded-response envelope. It accepts
top-level groups and exactly one `collection.field` level for definitions,
Expand Down Expand Up @@ -6222,6 +6231,14 @@ help はすべてこのレジストリを参照します。field 名は大文字
値で JSON が要求されている場合は versioned `E010_USAGE_ERROR` command error を
返します。発見処理は query や database access より先に実行します。

`impact` の `file_impacts` collection では、許可する leaf を
`FileDependencyResult` から導出します。対象は `result_kind`、`source_path`、
`target_path`、`source_db`、`target_db`、`reference_count`、`ranking_score`、
`symbols`、`evidence` です。compact な file-impact row は `source_path`、
`target_path`、`reference_count`、`result_kind` を保持するため、空でない各 row を
一意に識別できます。曖昧な `file_impacts.path` と `file_impacts.file` alias は拒否し、
callers と definitions では既存の path alias を維持します。

`inspect` は従来の JSON bundle を shared bounded-response envelope に変更しないため、
同じレジストリ内に専用の typed schema を持ちます。top-level group に加え、definitions、
nearby symbols、references、callers、callees では 1 階層だけの `collection.field` を
Expand Down
2 changes: 2 additions & 0 deletions TESTING_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Use the full suite by default. Use targeted filters only while iterating locally

## Test Stack

- Issue #5156 file-impact projection coverage belongs in `QueryCommandRunnerImpactTests.cs` and `ProjectionFieldRegistryIssue4836Tests.cs`. Reuse one non-empty two-dependent fixture across full JSON, compact identity, both endpoint leaves, every supported `FileDependencyResult` leaf, typed rejection of the ambiguous `file_impacts.path` alias, cursor paging, and UTF-8 byte bounds. Keep the inactive zero-result collection assertion in `JsonEnvelopeWrapperIssue4585Tests.cs` on a real file-impact leaf.
- Issue #5130 keeps the commit-diff timeout regression focused on `diff-tree`: its fake git must echo the commit being verified by `rev-parse --verify <ref>^{commit}`, then the test must confirm the timed-out child process is reaped. Keep production single-commit validation strict.
- Issue #5128 compact graph zero-result coverage belongs in `JsonEnvelopeWrapperIssue4585Tests.cs`. Keep `callees` aligned with `references` and `callers` by asserting an empty compact location envelope and zero returned/total cardinality both with and without explicit `--fields`, while reusing the graph-ready bounded-response fixture.
- Issue #5098 inspect projection coverage belongs in `QueryCommandRunnerInspectTests.cs`. Keep one graph-ready partial-type fixture covering canonical and alias selectors, multiple leaves across collections, parent-over-child precedence, stable row order, empty arrays, compact truncation, byte bounds, body paging/recovery, partial-family metadata, queryless catalog discovery, and typed unknown parent/leaf errors. `ConsoleUiTests.cs` separately pins the `<csv|list>` usage, nested-field help text, and examples.
Expand Down Expand Up @@ -1132,6 +1133,7 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests"

## テストスタック

- Issue #5156 の file-impact projection coverage は `QueryCommandRunnerImpactTests.cs` と `ProjectionFieldRegistryIssue4836Tests.cs` が担当します。full JSON、compact row identity、両 endpoint leaf、対応する全 `FileDependencyResult` leaf、曖昧な `file_impacts.path` alias の型付き拒否、cursor paging、UTF-8 byte 上限を、空でない 2 dependent の fixture 1 つで共有してください。`JsonEnvelopeWrapperIssue4585Tests.cs` の inactive な 0 件 collection assertion は、実在する file-impact leaf を指定したまま維持します。
- Issue #5130 の commit-diff timeout regression は `diff-tree` に焦点を維持します。fake git は `rev-parse --verify <ref>^{commit}` で検証対象の commit を返し、テストでは timeout した子プロセスが reap されることを確認してください。本番の single-commit validation は厳格なままにします。
- Issue #5128 の compact graph 0件 coverage は `JsonEnvelopeWrapperIssue4585Tests.cs` が担当します。graph-ready な bounded-response fixture を再利用し、明示的な `--fields` の有無の両方で、`callees` が `references` / `callers` と同様に空の compact location envelope と返却件数・総件数0を維持することを検証してください。
- Issue #5098 の inspect projection coverage は `QueryCommandRunnerInspectTests.cs` が担当します。graph-ready な partial type fixture 1つで canonical / alias selector、collection をまたぐ複数 leaf、parent の child に対する優先、安定した row 順、空配列、compact truncation、byte 上限、body paging / recovery、partial-family metadata、query 不要の catalog discovery、未知 parent / leaf の型付き error を維持してください。`ConsoleUiTests.cs` では `<csv|list>` usage、nested-field help text、例を別途固定します。
Expand Down
20 changes: 20 additions & 0 deletions changelog.d/unreleased/5156.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
category: fixed
issues:
- 5156
affected:
- src/CodeIndex/Cli/ProjectionFieldRegistry.cs
- tests/CodeIndex.Tests/JsonEnvelopeWrapperIssue4585Tests.cs
- tests/CodeIndex.Tests/QueryCommandRunnerImpactTests.cs
- tests/CodeIndex.Tests/ProjectionFieldRegistryIssue4836Tests.cs
- DEVELOPER_GUIDE.md
- TESTING_GUIDE.md
---

## English

- **Impact file-hint projections now preserve both endpoint paths (#5156)** — compact `file_impacts` rows retain `source_path`, `target_path`, `reference_count`, and `result_kind`; explicit projections accept the real `FileDependencyResult` fields, while the ambiguous `file_impacts.path` alias is rejected instead of returning an empty object.

## 日本語

- **impact の file hint projection が両 endpoint path を保持するようになりました (#5156)** — compact な `file_impacts` row は `source_path`、`target_path`、`reference_count`、`result_kind` を保持し、明示的な projection は実際の `FileDependencyResult` field を受け付けます。曖昧な `file_impacts.path` alias は空 object を返さず拒否します。
13 changes: 6 additions & 7 deletions src/CodeIndex/Cli/ProjectionFieldRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -492,11 +492,7 @@ private static ProjectionCommandFieldSchema CreateLanguagesSchema()
private static ProjectionCommandFieldSchema CreateImpactSchema()
{
var callerFields = GetJsonFieldNames<ImpactResult>().ToArray();
var fileImpactFields = new[]
{
"result_kind", "path", "lang", "depth", "reference_count", "reference_kind",
"reference_kinds", "reference_kind_counts",
};
var fileImpactFields = GetJsonFieldNames<FileDependencyResult>().ToArray();
var definitionFields = new[]
{
"api_version", "path", "symbol_id", "lang", "kind", "sub_kind", "name", "line",
Expand All @@ -507,12 +503,15 @@ private static ProjectionCommandFieldSchema CreateImpactSchema()
};
return Create(
"impact",
["path", "caller_name", "callee_name", "depth", "first_line", "reference_count", "result_kind"],
[
"path", "source_path", "target_path", "caller_name", "callee_name", "depth", "first_line",
"reference_count", "result_kind",
],
builder => builder
.Fields(callerFields.Concat(fileImpactFields).Concat(definitionFields).Distinct(StringComparer.Ordinal))
.Alias("file", "path")
.Collection("callers", callerFields, pathAlias: true)
.Collection("file_impacts", fileImpactFields, pathAlias: true)
.Collection("file_impacts", fileImpactFields)
.Collection("definitions", definitionFields, pathAlias: true));
}

Expand Down
2 changes: 1 addition & 1 deletion tests/CodeIndex.Tests/JsonEnvelopeWrapperIssue4585Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ public void Impact_InactiveProjectedCollectionHasAuthoritativeZeroTotal_Issue458
MarkGraphAndFoldReady(dbPath);

var (exitCode, stdout, stderr) = CaptureConsole(() => ProgramRunner.Run(
["impact", "Run", "--db", dbPath, "--fields", "file_impacts.path", "--limit", "1", "--max-json-bytes", "4096"],
["impact", "Run", "--db", dbPath, "--fields", "file_impacts.source_path", "--limit", "1", "--max-json-bytes", "4096"],
_jsonOptions,
"1.0.0-test"));

Expand Down
33 changes: 33 additions & 0 deletions tests/CodeIndex.Tests/ProjectionFieldRegistryIssue4836Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public sealed class ProjectionFieldRegistryIssue4836Tests
[Theory]
[InlineData("search", "path")]
[InlineData("references", "resolution_state")]
[InlineData("impact", "file_impacts.source_path")]
[InlineData("map", "languages.lang")]
[InlineData("status", "workspace_check.unindexed_files_omitted_count")]
public void FieldsList_DiscoversCommandSpecificSchemaWithoutRunningQuery_Issue4836(
Expand Down Expand Up @@ -40,6 +41,7 @@ public void FieldsList_DiscoversCommandSpecificSchemaWithoutRunningQuery_Issue48
[Theory]
[InlineData("search")]
[InlineData("references")]
[InlineData("impact")]
[InlineData("map")]
public void UnknownFields_ReturnTypedJsonUsageErrorBeforeQueryExecution_Issue4836(string command)
{
Expand Down Expand Up @@ -349,6 +351,36 @@ public void RegistryAliasesAndNestedCollections_AreMachineDiscoverable_Issue4836
Assert.Equal("top_files", nestedAlias["collection"]!.GetValue<string>());
}

[Fact]
public void ImpactFileDependencyFields_MatchRuntimeModelAndRejectAmbiguousPathAlias_Issue5156()
{
string[] expectedFields =
[
"result_kind", "source_path", "target_path", "source_db", "target_db",
"reference_count", "ranking_score", "symbols", "evidence",
];
var discovery = ProjectionFieldRegistry.CreateDiscoveryDocument("impact");
var validFields = discovery["valid_fields"]!.AsArray()
.Select(field => field!.GetValue<string>())
.ToHashSet(StringComparer.Ordinal);

foreach (var field in expectedFields)
{
var qualifiedField = $"file_impacts.{field}";
Assert.Contains(qualifiedField, validFields);
Assert.True(
ProjectionFieldRegistry.TryValidate("impact", [qualifiedField], out var error),
error?.Message);
}

Assert.Contains("source_path", ProjectionFieldRegistry.GetCompactFields("impact")!);
Assert.Contains("target_path", ProjectionFieldRegistry.GetCompactFields("impact")!);
Assert.False(ProjectionFieldRegistry.TryValidate("impact", ["file_impacts.path"], out var pathError));
Assert.NotNull(pathError);
Assert.DoesNotContain("file_impacts.path", validFields);
Assert.DoesNotContain("file_impacts.file", validFields);
}

[Fact]
public void EveryDiscoveredProjectionField_ValidatesFromTheSameRegistry_Issue4836()
{
Expand Down Expand Up @@ -532,6 +564,7 @@ public void EarlyProjectionRegistryResponses_HonorMaxJsonBytes_Issue4836(string
[Theory]
[InlineData("search")]
[InlineData("references")]
[InlineData("impact")]
[InlineData("map")]
public void CommandHelp_DirectsFieldsUsersToRegistryDiscovery_Issue4836(string command)
{
Expand Down
Loading
Loading