From ec3be9002318ec42d5b2d2a8ab614a697083875e Mon Sep 17 00:00:00 2001 From: Widthdom Date: Wed, 3 Jun 2026 03:03:31 +0900 Subject: [PATCH 1/2] Pin changed-between freshness for #2808 --- changelog.d/unreleased/2808.fixed.md | 15 +++++++++++++++ tests/CodeIndex.Tests/IndexCommandRunnerTests.cs | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 changelog.d/unreleased/2808.fixed.md diff --git a/changelog.d/unreleased/2808.fixed.md b/changelog.d/unreleased/2808.fixed.md new file mode 100644 index 0000000000..3afbc33362 --- /dev/null +++ b/changelog.d/unreleased/2808.fixed.md @@ -0,0 +1,15 @@ +--- +category: fixed +issues: + - 2808 +affected: + - tests/CodeIndex.Tests/IndexCommandRunnerTests.cs +--- + +## English + +- **`status --check` freshness after `--changed-between` is pinned for current HEAD stamps (#2808)** — regression coverage now asserts that a successful `--changed-between` refresh lets `status --check --json` treat the current `indexed_head_sha` as fresh even though the full-scan-only `indexed_head_commit` remains at the prior full scan. + +## 日本語 + +- **`--changed-between` 後の `status --check` freshness を current HEAD stamp として固定しました (#2808)** — `--changed-between` の成功後は full-scan 専用の `indexed_head_commit` が前回 full scan のままでも、`status --check --json` が current `indexed_head_sha` を fresh とみなすことを回帰テストで固定しました。 diff --git a/tests/CodeIndex.Tests/IndexCommandRunnerTests.cs b/tests/CodeIndex.Tests/IndexCommandRunnerTests.cs index f458efe366..8b11327314 100644 --- a/tests/CodeIndex.Tests/IndexCommandRunnerTests.cs +++ b/tests/CodeIndex.Tests/IndexCommandRunnerTests.cs @@ -8662,7 +8662,7 @@ public void RunStatusCheck_AfterCommitScopedRefreshAtHead_DoesNotReportHeadChang } [Fact] - public void RunStatusCheck_AfterChangedBetweenRefreshAtHead_DotCommandRestampsFullScanHead() + public void RunStatusCheck_AfterChangedBetweenRefreshAtHead_TreatsCurrentIndexedHeadShaAsFresh_2808() { var projectRoot = CreateTempProject(); try @@ -8697,10 +8697,13 @@ public void RunStatusCheck_AfterChangedBetweenRefreshAtHead_DotCommandRestampsFu var (statusExitCode, statusJson) = RunStatusAndCaptureJson(["--db", dbPath, "--check", "--json"]); Assert.Equal(CommandExitCodes.Success, statusExitCode); + Assert.Equal(currentHead, statusJson.GetProperty("indexed_head_sha").GetString()); var check = statusJson.GetProperty("workspace_check"); Assert.False(check.GetProperty("head_changed").GetBoolean()); Assert.True(check.GetProperty("matches_workspace").GetBoolean()); Assert.Equal("matched", check.GetProperty("reason").GetString()); + Assert.Equal(initialHead, check.GetProperty("indexed_head_commit").GetString()); + Assert.Equal(currentHead, check.GetProperty("workspace_head_commit").GetString()); var (dotExitCode, dotJson) = RunProgramAndCaptureJson([projectRoot, "--json"]); Assert.Equal(CommandExitCodes.Success, dotExitCode); From 1e57df8b450e8248565d6ae8ffcf797d3b26fc76 Mon Sep 17 00:00:00 2001 From: Widthdom Date: Wed, 3 Jun 2026 03:04:02 +0900 Subject: [PATCH 2/2] Fix hotspot readiness rebuild guidance for #2917 --- README.md | 6 +++-- USER_GUIDE.md | 4 ++-- changelog.d/unreleased/2917.fixed.md | 20 ++++++++++++++++ src/CodeIndex/Cli/QueryCommandRunner.cs | 7 +++++- .../Database/DegradationReasonCodes.cs | 24 +++++++++---------- .../QueryCommandRunnerTests.cs | 20 ++++++++++++++++ tests/CodeIndex.Tests/golden/status.json | 8 +++---- 7 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 changelog.d/unreleased/2917.fixed.md diff --git a/README.md b/README.md index 9acb164791..b8c10797a0 100644 --- a/README.md +++ b/README.md @@ -227,7 +227,8 @@ For MCP `status`, `mcp_session` is session-scoped diagnostic data rather than pe Hotspot-family readiness is tracked by per-language `hotspot_family_version_` metadata introduced with hotspot-family contract -version 2. +version 2. When this readiness is degraded, use +`cdidx index --rebuild` so unchanged rows are restamped too. ## Documentation @@ -490,7 +491,8 @@ MCP `status` の `mcp_session` は永続化された index 状態ではなく、 | `hotspot_family_disabled_at_index_time` | marker fingerprint が利用できない状態で書かれた index。 | hotspot-family readiness は、hotspot-family contract version 2 で導入された -言語別 `hotspot_family_version_` metadata で追跡されます。 +言語別 `hotspot_family_version_` metadata で追跡されます。degraded の場合は +unchanged row も restamp するため `cdidx index --rebuild` を使います。 ## ドキュメント diff --git a/USER_GUIDE.md b/USER_GUIDE.md index f87d2519c5..c686cef41a 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -1061,7 +1061,7 @@ Use these fields as concrete remediation hints: - `fold_ready=false`: `status --json` includes `degraded_reason`, `recommended_action`, and `alternative_action`. Prefer `cdidx backfill-fold`; use a full rebuild as the fallback. For read-only `file:` DB URIs such as `file:///...?...` or `file:codeindex.db?...`, the remediation path is normalized back to a writable filesystem path. - `sql_graph_contract_ready=false`: rerun `cdidx index .` before trusting SQL `references` / `callers` / `deps` / `unused` / `hotspots`. The same readiness pair is mirrored by SQL-backed `inspect --json`, JSON graph/dependency output, and MCP graph/dependency tools. -- `hotspot_family_ready=false`: `hotspots` can still run, but duplicate-name families use a conservative fallback until `cdidx index .` restamps hotspot-family metadata. +- `hotspot_family_ready=false`: `hotspots` can still run, but duplicate-name families use a conservative fallback until `cdidx index . --rebuild` restamps hotspot-family metadata for every indexed row. - `csharp_symbol_name_ready=false`: rerun `cdidx index .` once to rewrite unchanged C# rows to the current canonical operator / conversion-operator / indexer names. - `csharp_metadata_target_ready=false`: `deps` / `impact` metadata-attribute edges fall back to a signature-shape heuristic; rerun `cdidx index .` once so the authoritative resolver stamps whether each C# class is attribute-derived. @@ -3193,7 +3193,7 @@ AI agent の作業開始時はこれを先に実行し、`.cdidx/codeindex.db` - `fold_ready=false`: `degraded_reason`、`recommended_action`、`alternative_action` に従い、まず `cdidx backfill-fold`、必要なら full rebuild を実行します。read-only `file:` DB URI の場合も、対処用 path は writable な filesystem path に正規化されます。 - `sql_graph_contract_ready=false`: unchanged な SQL 行が古い graph contract のまま残っている可能性があります。SQL の `references` / `callers` / `deps` / `unused` / `hotspots` を信頼する前に `cdidx index .` を再実行してください。 -- `hotspot_family_ready=false`: `hotspots` は使えますが、duplicate-name family は保守的 fallback に縮退しうるため、`cdidx index .` で hotspot-family metadata を restamp してください。 +- `hotspot_family_ready=false`: `hotspots` は使えますが、duplicate-name family は保守的 fallback に縮退しうるため、`cdidx index . --rebuild` で全 indexed row の hotspot-family metadata を restamp してください。 - `csharp_symbol_name_ready=false`: `cdidx index .` を 1 回実行し、unchanged な C# 行を現在の canonical operator / conversion operator / indexer 名へ書き換えてください。 - `csharp_metadata_target_ready=false`: `deps` / `impact` の metadata attribute edge 判定がヒューリスティックへフォールバックします。`cdidx index .` を 1 回実行し、各 C# class が attribute 派生かどうかを authoritative resolver で永続化してください。 diff --git a/changelog.d/unreleased/2917.fixed.md b/changelog.d/unreleased/2917.fixed.md new file mode 100644 index 0000000000..aa63b9fe22 --- /dev/null +++ b/changelog.d/unreleased/2917.fixed.md @@ -0,0 +1,20 @@ +--- +category: fixed +issues: + - 2917 +affected: + - src/CodeIndex/Cli/QueryCommandRunner.cs + - src/CodeIndex/Database/DegradationReasonCodes.cs + - tests/CodeIndex.Tests/QueryCommandRunnerTests.cs + - tests/CodeIndex.Tests/golden/status.json + - README.md + - USER_GUIDE.md +--- + +## English + +- **Hotspot-family readiness now recommends a rebuild when unchanged rows may need restamping (#2917)** — `status --json` and `status --explain hotspot_family_ready` now point degraded hotspot-family metadata at `cdidx index --rebuild`, avoiding the previous hint that an incremental refresh could leave unchanged stale rows degraded. + +## 日本語 + +- **hotspot-family readiness が unchanged row の restamp には rebuild を推奨するようになりました (#2917)** — `status --json` と `status --explain hotspot_family_ready` は degraded な hotspot-family metadata に対し `cdidx index --rebuild` を案内するようになり、差分更新では unchanged な stale row が degraded のまま残り得る従来の案内を避けます。 diff --git a/src/CodeIndex/Cli/QueryCommandRunner.cs b/src/CodeIndex/Cli/QueryCommandRunner.cs index 33c1ac9fd1..0a96eb30e8 100644 --- a/src/CodeIndex/Cli/QueryCommandRunner.cs +++ b/src/CodeIndex/Cli/QueryCommandRunner.cs @@ -149,7 +149,7 @@ private sealed record StatusReadinessField( "Hotspot family contract", "cross-file hotspot family grouping is stamped for all supported languages in this index.", "cross-file hotspot grouping may be degraded for one or more languages.", - "Run `cdidx index ` to restamp authoritative hotspot families."), + "Run `cdidx index --rebuild` to restamp authoritative hotspot families for every indexed row."), new( "csharp_symbol_name_ready", "C# symbol-name contract", @@ -7150,6 +7150,7 @@ private static string BuildStatusReadinessRemediation(StatusResult status, Query => fieldName switch { "sql_graph_contract_ready" => $"Run `{BuildSqlGraphContractRepairCommand(status.ProjectRoot, options.DbPath, options.DbPathExplicit)}` before trusting SQL references/callers/deps/unused/hotspots.", + "hotspot_family_ready" => $"Run `{BuildHotspotFamilyRebuildRepairCommand(status.ProjectRoot, options.DbPath, options.DbPathExplicit)}` to restamp authoritative hotspot families for every indexed row.", "csharp_symbol_name_ready" => $"Run `{BuildCSharpCanonicalNameRepairCommand(status.ProjectRoot, options.DbPath, options.DbPathExplicit)}` to upgrade canonical C# symbol names in place.", "fold_ready" => $"Run `{BuildFoldBackfillCommand(options.DbPath, options.DbPathExplicit)}` to restamp folded-name columns in place, or `{BuildFoldRebuildRepairCommand(status.ProjectRoot, options.DbPath, options.DbPathExplicit)}` for a full rebuild.", "csharp_metadata_target_ready" => DegradationReasonCodes.GetMetadata(status.CSharpMetadataTargetDegradedReason ?? DegradationReasonCodes.CSharpMetadataTargetNotReady).RecommendedAction, @@ -7211,6 +7212,7 @@ private static StatusReadinessDegradation BuildStatusReadinessDegradation(string { "fold_ready" => BuildFoldBackfillCommand(options.DbPath, options.DbPathExplicit), "sql_graph_contract_ready" => BuildSqlGraphContractRepairCommand(status.ProjectRoot, options.DbPath, options.DbPathExplicit), + "hotspot_family_ready" => BuildHotspotFamilyRebuildRepairCommand(status.ProjectRoot, options.DbPath, options.DbPathExplicit), "csharp_symbol_name_ready" => BuildCSharpCanonicalNameRepairCommand(status.ProjectRoot, options.DbPath, options.DbPathExplicit), _ => metadata.RecommendedAction, }, @@ -7440,6 +7442,9 @@ private static string BuildSqlGraphContractRepairCommand(DbReader reader, QueryC private static string BuildSqlGraphContractRepairCommand(string? projectRoot, string dbPath, bool dbPathExplicit) => BuildReindexRepairCommand(projectRoot, dbPath, dbPathExplicit); + private static string BuildHotspotFamilyRebuildRepairCommand(string? projectRoot, string dbPath, bool dbPathExplicit) + => BuildReindexRepairCommand(projectRoot, dbPath, dbPathExplicit, rebuild: true); + private static string BuildFoldRebuildRepairCommand(string? projectRoot, string dbPath, bool dbPathExplicit) => BuildReindexRepairCommand(projectRoot, dbPath, dbPathExplicit, rebuild: true); diff --git a/src/CodeIndex/Database/DegradationReasonCodes.cs b/src/CodeIndex/Database/DegradationReasonCodes.cs index c511632d31..a025628876 100644 --- a/src/CodeIndex/Database/DegradationReasonCodes.cs +++ b/src/CodeIndex/Database/DegradationReasonCodes.cs @@ -74,10 +74,10 @@ public static string BuildSqlGraphContractDegradedReason() => $"{SqlGraphContractNotReady} ({GetMetadata(SqlGraphContractNotReady).HumanText})"; public static string BuildHotspotFamilyLanguageDegradedReason(string language) - => $"cross-file hotspot family grouping for '{language}' is degraded; run `cdidx index ` to restamp authoritative hotspot families."; + => $"cross-file hotspot family grouping for '{language}' is degraded; run `cdidx index --rebuild` to restamp authoritative hotspot families for every indexed row."; public static string BuildHotspotFamilyLanguagesDegradedReason(IEnumerable languages) - => $"cross-file hotspot family grouping is degraded for: {string.Join(", ", languages)}; run `cdidx index ` to restamp authoritative hotspot families."; + => $"cross-file hotspot family grouping is degraded for: {string.Join(", ", languages)}; run `cdidx index --rebuild` to restamp authoritative hotspot families for every indexed row."; public static string NormalizeFoldReason(string? foldReadyReason) => foldReadyReason switch @@ -131,28 +131,28 @@ private static DegradationReasonMetadata CreateMetadata(string code) HotspotFamilyNotReady => new( code, "Cross-file hotspot grouping may be degraded for one or more languages.", - "Run `cdidx index ` to restamp authoritative hotspot families.", - "Run `cdidx index --rebuild` for a full rebuild."), + "Run `cdidx index --rebuild` to restamp authoritative hotspot families for every indexed row.", + "Run `cdidx index --files ` only when you can enumerate every file whose hotspot-family rows need restamping."), HotspotFamilySupportNotIndexed => new( code, "Cross-file hotspot grouping is unavailable because this DB predates hotspot-family metadata or lacks the required symbol columns.", - "Run `cdidx index ` to rebuild and stamp authoritative hotspot families.", - "Run `cdidx index --rebuild` for a full rebuild."), + "Run `cdidx index --rebuild` to rebuild and stamp authoritative hotspot families for every indexed row.", + "Create a fresh DB with the current cdidx binary if the existing DB cannot be rebuilt in place."), HotspotFamilyMetadataStale => new( code, "Cross-file hotspot grouping metadata was written by an older hotspot-family contract.", - "Run `cdidx index --files ` or `cdidx index ` to restamp authoritative hotspot families.", - "Run `cdidx index --rebuild` for a full rebuild."), + "Run `cdidx index --rebuild` to restamp authoritative hotspot families for every indexed row.", + "Run `cdidx index --files ` only when you can enumerate every stale file."), HotspotFamilyDisabledAtIndexTime => new( code, "Cross-file hotspot grouping metadata was stamped without marker fingerprints, so authoritative family grouping cannot be trusted.", - "Run `cdidx index ` to rebuild and stamp authoritative hotspot families.", - "Run `cdidx index --rebuild` for a full rebuild."), + "Run `cdidx index --rebuild` to rebuild and stamp authoritative hotspot families for every indexed row.", + "Run `cdidx index --files ` only when you can enumerate every affected file."), HotspotFamilyRowsIncomplete => new( code, "Cross-file hotspot grouping metadata is stamped, but some indexed symbols still lack family keys.", - "Run `cdidx index ` to restamp authoritative hotspot families.", - "Run `cdidx index --rebuild` for a full rebuild."), + "Run `cdidx index --rebuild` to restamp authoritative hotspot families for every indexed row.", + "Run `cdidx index --files ` only when you can enumerate every file with incomplete family keys."), GraphTableMissing => new( code, "Reference / caller / callee / unused counts are degraded to 0 because the symbol_references table is missing.", diff --git a/tests/CodeIndex.Tests/QueryCommandRunnerTests.cs b/tests/CodeIndex.Tests/QueryCommandRunnerTests.cs index 6ff2e8ef71..2bd533e8bd 100644 --- a/tests/CodeIndex.Tests/QueryCommandRunnerTests.cs +++ b/tests/CodeIndex.Tests/QueryCommandRunnerTests.cs @@ -12194,6 +12194,11 @@ public void RunStatus_Json_ReportsHotspotFamilyTrustSignals() Assert.Equal(string.Empty, stderr); Assert.False(json.GetProperty("hotspot_family_ready").GetBoolean()); Assert.Contains("csharp", json.GetProperty("hotspot_family_degraded_reason").GetString()); + var hotspotDegradation = json.GetProperty("readiness_degradations") + .EnumerateArray() + .Single(item => item.GetProperty("field").GetString() == "hotspot_family_ready"); + Assert.Equal("hotspot_family_ready=false", hotspotDegradation.GetProperty("root_cause").GetString()); + Assert.Contains("--rebuild", hotspotDegradation.GetProperty("recommended_action").GetString()); Assert.Contains("DEGRADED", json.GetProperty("summary").GetString()); } finally @@ -30847,6 +30852,21 @@ public void RunStatus_HumanOutput_TranslatesReadinessFields() } } + [Fact] + public void RunStatus_Explain_HotspotFamilyReadyRecommendsRebuild() + { + var (exitCode, stdout, stderr) = CaptureConsole(() => QueryCommandRunner.RunStatus( + ["--explain", "hotspot_family_ready"], + _jsonOptions)); + + Assert.Equal(CommandExitCodes.Success, exitCode); + Assert.Equal(string.Empty, stderr); + Assert.Contains("Hotspot family contract (hotspot_family_ready)", stdout); + Assert.Contains("Remediation:", stdout); + Assert.Contains("cdidx index --rebuild", stdout); + Assert.Contains("every indexed row", stdout); + } + [Fact] public void RunStatus_Explain_PrintsReadinessFieldDescriptionWithoutDatabase() { diff --git a/tests/CodeIndex.Tests/golden/status.json b/tests/CodeIndex.Tests/golden/status.json index a1e3a86416..792e3c6d37 100644 --- a/tests/CodeIndex.Tests/golden/status.json +++ b/tests/CodeIndex.Tests/golden/status.json @@ -92,12 +92,12 @@ "file_issues_data_current": false, "migration_in_progress": false, "hotspot_family_ready": false, - "hotspot_family_degraded_reason": "cross-file hotspot family grouping is degraded (hotspot_family_support_not_indexed=csharp); Run \u0060cdidx index \u003CprojectPath\u003E\u0060 to rebuild and stamp authoritative hotspot families.", + "hotspot_family_degraded_reason": "cross-file hotspot family grouping is degraded (hotspot_family_support_not_indexed=csharp); Run \u0060cdidx index \u003CprojectPath\u003E --rebuild\u0060 to rebuild and stamp authoritative hotspot families for every indexed row.", "language_readiness": { "csharp": { "hotspot_family": { "ready": false, - "degraded_reason": "cross-file hotspot family grouping is degraded (hotspot_family_support_not_indexed=csharp); Run \u0060cdidx index \u003CprojectPath\u003E\u0060 to rebuild and stamp authoritative hotspot families." + "degraded_reason": "cross-file hotspot family grouping is degraded (hotspot_family_support_not_indexed=csharp); Run \u0060cdidx index \u003CprojectPath\u003E --rebuild\u0060 to rebuild and stamp authoritative hotspot families for every indexed row." }, "symbol_name": { "ready": false, @@ -138,8 +138,8 @@ "field": "hotspot_family_ready", "root_cause": "hotspot_family_ready=false", "degraded_reason": "Cross-file hotspot grouping may be degraded for one or more languages.", - "recommended_action": "Run \u0060cdidx index \u003CprojectPath\u003E\u0060 to restamp authoritative hotspot families.", - "alternative_action": "Run \u0060cdidx index \u003CprojectPath\u003E --rebuild\u0060 for a full rebuild." + "recommended_action": "cdidx index --db /.cdidx/codeindex.db --rebuild", + "alternative_action": "Run \u0060cdidx index \u003CprojectPath\u003E --files \u003CchangedFiles\u003E\u0060 only when you can enumerate every file whose hotspot-family rows need restamping." }, { "field": "csharp_symbol_name_ready",