Skip to content

Branch.head_sha stale after re-indexing an existing project (freezes at creation-time HEAD) #1213

Closed

Description

@HorusScale

Summary

Branch.head_sha in the graph does not update when re-indexing an already-existing project. It stays frozen at whatever commit was HEAD when the project was first created, even though the graph content itself (nodes/edges) updates correctly on re-index.

Environment

  • cbm v0.9.0, linux-amd64 release, SHA-256 verified against checksums.txt
  • Invoked directly via cli (no MCP server auto-install), isolated CBM_CACHE_DIR/CBM_ALLOWED_ROOT against a throwaway git repo

Repro (~5 commands)

  1. Fresh index at commit A:
    cli index_repository --repo-path <repo> --name smoketest
    → MATCH (b:Branch) RETURN b.head_sha = A. Correct.

  2. Advance HEAD to commit B (real commit, e.g. adding a function). Re-index the same project (default mode):
    cli index_repository --repo-path <repo> --name smoketest
    → graph content updates correctly (node/edge counts increase, new function present in the graph).
    → Branch.head_sha still reads A — unchanged.

  3. Advance HEAD to commit C. Re-index explicitly with --mode full:
    → graph content updates again correctly.
    → Branch.head_sha now reads B — one commit behind the re-index that caused it, not C.

  4. Control: delete_project then fresh index_repository (no prior project) at current HEAD:
    → Branch.head_sha correctly matches current HEAD immediately.

So the bug is specific to re-indexing an existing project — both default and --mode full — not to indexing itself.

Why this matters

Branch.head_sha (and index_status, which we separately confirmed reads live git HEAD rather than indexed-state — always "fresh," not useful either) are the two natural surfaces for a caller to answer "is the index actually caught up with the repo?" Neither gives a trustworthy answer in the normal long-lived-project + incremental-watcher-reindex scenario. A caller trusting Branch.head_sha as a freshness signal would see staleness silently understated forever after the first index, even while the watcher is correctly doing its job content-wise.

Suggested area to look

Whatever code path updates the Branch node's head_sha property likely only runs on project creation, not on the re-index/update path that touches node/edge content.

Activity

  1. TheDarkniteFalls commented on Jul 23, 2026

    @TheDarkniteFalls
    Contributor

    I traced this on current main (5e7d3eb): the full structure pass upserts the Branch node from the captured Git context, but both successful incremental paths bypass that update. The changed-file path refreshes affected graph content only, while the no-change path returns without touching the database.

    I can take a focused, test-first fix, subject to one contract check:

    • add a self-contained temporary-Git regression covering A -> B with a tracked source change and B -> C with an empty commit;
    • refresh the existing Branch metadata on every successful incremental indexing invocation, including runs whose indexed file hashes do not change;
    • preserve the Branch node identity and edges, with no MCP schema or index_status changes.

    Should Branch.head_sha mean “HEAD captured at the start of the successful indexing invocation,” matching the current full-index model, or should indexing detect a mid-run HEAD change and refuse/retry so the value is bound to one immutable repository state?

    I would validate the change with the focused pipeline tests, full sanitizer test suite, lint/security gates, and a DCO-signed commit. I use AI-assisted tooling under human review and would disclose that in the PR.

  2. added
    bugSomething isn't working
    priority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.
    on Jul 24, 2026
  3. added this to the 0.9.1-rc milestone on Jul 24, 2026
  4. DeusData commented on Jul 24, 2026

    @DeusData
    Owner

    Thanks for tracing this to the incremental paths. The contract should remain consistent with a full index: Branch.head_sha means the HEAD captured at the start of the successful indexing invocation. Both changed-file and no-change incremental success must update the existing Branch node. Detecting or retrying when HEAD moves during an active run is a stronger snapshot-consistency feature and should be handled separately, not folded into this fix. This is now a high-priority 0.9.1-rc correctness bug under #391.

  5. TheDarkniteFalls commented on Jul 24, 2026

    @TheDarkniteFalls
    Contributor

    Thanks—that resolves the contract. I’ll keep the fix narrowly scoped to refreshing the existing Branch metadata on changed-file and no-change incremental success, with the temporary-Git regression test and no schema, index_status, or mid-run snapshot changes.

    I noticed #1245 also substantially changes incremental indexing and touches the same pipeline. Would this still be useful as a separate focused 0.9.1-rc PR, or would you prefer it coordinated with or held pending that review?

  6. TheDarkniteFalls commented on Aug 21, 2026

    @TheDarkniteFalls
    Contributor

    Quick follow-up on the coordination question: #1245 remains a draft and currently conflicts with main. Would a separate focused PR for the changed-file and no-change Branch.head_sha refresh still be useful, or should #1213 remain held for #1245? I’ll keep implementation on hold until you confirm.

  7. DeusData commented on Sep 25, 2026

    @DeusData
    Owner

    @TheDarkniteFalls, thank you for tracing this to the incremental paths, and I owe you an apology: you asked twice whether to go ahead, and we never answered. @HorusScale, thank you for the tight A→B→C repro!

    The good news is that this is fixed. On v0.11.0 I ran your exact sequence: index at A, commit a real change, re-index; then an empty commit, re-index. Branch.head_sha matched HEAD after every run, including the no-change case. The incremental pipeline was reworked after this was filed and now refreshes the git context on every successful run.

    One thing would still be valuable if you're up for it, @TheDarkniteFalls: the temporary-git regression test you designed (A→B with a changed file, B→C with an empty commit, asserting head_sha) doesn't exist yet. As a small test-only PR it would pin this contract so it can't quietly regress, and we'd be happy to review it quickly. @HorusScale, could you confirm on v0.11.0? Then we'll close this.

  8. added
    awaiting-reporterWaiting on the reporter for info/repro; stale bot will warn then close
    on Sep 25, 2026
  9. TheDarkniteFalls commented on Sep 26, 2026

    @TheDarkniteFalls
    Contributor

    Thanks for confirming the fix and inviting regression coverage. I’ve opened #2359 with the focused test-only extension.

    Current main already includes the empty-commit/run-start refresh test, so this adds the initial-A and tracked-source-change-B assertions before its empty-commit-C step rather than duplicating the fixture. The existing route assertions remain, and there are no production or mid-run snapshot-consistency changes.

    The full local test run passed (8,190 tests, zero failures, ten platform skips), along with the prescribed local lint gates and security checks. Written with OpenAI Codex assistance; details and platform limits are in the PR.

  10. github-actions commented on Sep 26, 2026

    @github-actions

    Thanks for the report! To move this forward we need a bit more so we can reproduce it ourselves:

    • the codebase-memory-mcp --version you're on
    • the exact steps or command you ran
    • a public repo (or a small dummy snippet) that shows the problem — please don't paste proprietary code

    Once that's here we'll pick it straight back up. Heads-up: issues left awaiting-reporter are automatically closed after a few weeks of silence, but a comment reopens the door anytime.

  11. DeusData commented on Sep 27, 2026

    @DeusData
    Owner

    The requested A→B→C regression coverage is on main in 4f7fa84 (PR #2359, thanks to @TheDarkniteFalls). Thank you for the report!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    awaiting-reporterWaiting on the reporter for info/repro; stale bot will warn then closebugSomething isn't workingpriority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.stability/performanceServer crashes, OOM, hangs, high CPU/memoryux/behaviorDisplay bugs, docs, adoption UX

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions