Skip to content

Make branch-switch refresh converge and keep indexed HEAD provenance consistent #5054

Description

@Widthdom

Summary

Branch-switch refresh can require a full rebuild even after every indexed file matches the current checkout, and different commands can report incompatible freshness states for the same database.

This is a regression/residual of the contracts addressed by:

The observed failures share one root area: indexed HEAD provenance and refresh-mode convergence. They should be fixed in one PR rather than split into competing metadata changes.

Environment

  • cdidx: 1.41.0
  • current HEAD: d444cfdb2c660425afda504b9998977cdf15c89e
  • pre-refresh database full-scan HEAD: 4ec315...
  • previous work-branch tip supplied to changed-between: 8f17f7...

Reproduction sequence

After fetching and switching from an older work branch to current origin/main:

dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll status --check --json

dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll index . \
  --changed-between 8f17f7... d444cfdb... --json

The initial status found two stale files. --changed-between updated only the file changed between the supplied refs; the DB was older than the supplied old ref, so one stale row remained.

After updating the remaining file explicitly, all file contents matched and the latest indexed_head_sha was current, but:

  • status --check remained stale because it used the older full-scan HEAD;
  • map reported head_current for the same DB.

Then:

dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll . --json

scanned all 1,275 paths and skipped all 1,275, but retained the old full-scan stamp and recommended:

cdidx index . --rebuild --yes

Only the 134-second rebuild made every freshness surface agree.

Expected behavior

  • A verified whole-workspace no-op scan must be able to advance the appropriate workspace verification/provenance stamp without rewriting every row.
  • --changed-between should detect when its supplied base does not cover the DB's actual indexed baseline and either reconcile the union or emit a precise warning/recovery command.
  • Status, map, search/query envelopes, MCP, and other readers must expose compatible freshness semantics.
  • Partial updates must never falsely claim full-workspace verification.
  • Failed or rolled-back updates must not advance freshness metadata.

PR scope

Keep this PR to refresh-mode provenance and branch-switch convergence. Do not bundle general indexing performance work.

Implementation guide

  • Define separate stable meanings for the latest committed delta HEAD, last verified whole-workspace HEAD, and any legacy full-scan baseline.
  • Centralize the transaction that updates HEAD provenance after --files, --changed-between, incremental whole-workspace, and rebuild modes.
  • Before executing --changed-between, compare its old ref with the persisted indexed baseline. If coverage is incomplete, compute a safe union or return actionable structured guidance.
  • Allow a complete no-op workspace scan to record verification without pretending rows were rebuilt.
  • Keep legacy DB reads backward compatible and migrate ambiguous metadata conservatively.
  • Use one shared response projection for status/query/MCP freshness fields.
  • Add a bilingual changelog fragment referencing cdidx dot-command does not refresh full-scan HEAD stamp #2809 and Keep query and status indexed-HEAD stamps consistent #4854.

Tests

Add a branch-switch matrix covering:

  • DB baseline equals supplied old ref;
  • DB baseline is older than supplied old ref;
  • divergent branches;
  • no-op full workspace scan;
  • one remaining stale file after changed-between;
  • explicit files update followed by status/map/search/MCP comparisons;
  • cancelled/failed refresh does not advance metadata.

Acceptance criteria

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETPull requests that update .NET codebugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions