Skip to content

fix: detect edge index changes by ref object ID - #1

Open
mparrett wants to merge 1 commit into
nnunley:mainfrom
mparrett:fix/edge-index-timestamp-comparison
Open

mparrett wants to merge 1 commit into
nnunley:mainfrom
mparrett:fix/edge-index-timestamp-comparison

Conversation

@mparrett

@mparrett mparrett commented Aug 4, 2026 •

Copy link
Copy Markdown

Why

ensure_edge_index_current refreshes the derived dependency graph at refs/notes/dep-graph before deps, ready, and topo run. It decides which issues to re-parse by comparing each note ref's commit date against a last_rebuilt_from marker.

e98395e fixed the timezone half of that comparison. The remaining problem is that a commit date does not say when a ref changed locally. A note arriving by fetch or import keeps the date it was written with, which can predate the marker, so its dependency headers are skipped permanently. hooks/post-merge fetches issue notes on every pull, so this is the ordinary sync path rather than a corner case. Reproduced on current main, with a backdated commit standing in for a fetched note:

$ git issue dep rebuild
$ GIT_COMMITTER_DATE=2020-01-01T00:00:00Z git issue update <c> --relates-to=<b>
$ git issue show <c> | grep '^relates_to'
relates_to: <b>
$ git issue deps
No dependency edges found.

A date cursor also never notices a ref that disappears, so a deleted issue's edges stay in the index until dep rebuild.

What

Snapshot issue ref object IDs in a refs blob beside the existing edges blob, and re-parse the refs whose ID moved. An object ID changes whenever a ref does, however it moved and whatever date it carries. Refs that have disappeared have their edges dropped.

The snapshot lives in a sibling blob rather than in the edges text, so existing readers of the index are unaffected. An index with no snapshot reads as "everything changed" and rebuilds in full, so an existing index heals on first read and there is no migration step.

Verification

Two regression tests in tests/test_deps.sh: a backdated header edit, and a deleted note ref. Both fail on main and pass on this branch. The shell suites under make test-all pass; the Emacs suite was not run.

Rebased onto b823d9c. The earlier TZ-pinned test is dropped, since e98395e covers that case.

🤖 Generated with Claude Code

@mparrett
mparrett force-pushed the fix/edge-index-timestamp-comparison branch from b353dba to 5e015cf Compare August 4, 2026 04:50
@mparrett

Copy link
Copy Markdown
Author

@nnunley Thanks again for sharing your project. I have a few bug fixes if you're interested. This is the first.

@nnunley

nnunley commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Awesome. Glad you're trying it out and finding gaps.

ensure_edge_index_current decides which issues to re-parse by comparing
each note ref's commit date against a wall-clock marker. A commit date
does not say when a ref changed locally. A note arriving by fetch or
import keeps the date it was written with, which can predate the marker,
so its dependency headers are skipped permanently. The post-merge hook
fetches issue notes on every pull, so this is the ordinary sync path
rather than a corner case. Normalizing dates to UTC (e98395e) fixed the
offset comparison but cannot fix this.

A date cursor also never notices a ref that disappears, so a deleted
issue's edges stay in the index until a full rebuild.

Snapshot issue ref object IDs in a sibling blob of the edge index and
re-parse the refs whose ID moved. Object IDs change whenever a ref does,
however it moved and whatever date it carries. Refs that disappeared
have their edges dropped. An index with no snapshot reads as "everything
changed" and rebuilds in full, so an older index heals on first read
with no migration step.

Two regression tests cover it: an edit backdated with GIT_COMMITTER_DATE,
and a deleted note ref. Both fail against the date cursor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mparrett
mparrett force-pushed the fix/edge-index-timestamp-comparison branch from 5e015cf to 5fd91c9 Compare October 10, 2026 23:14
@mparrett

Copy link
Copy Markdown
Author

@nnunley I rebased this onto current main. You fixed the timezone part in e98395e, so I narrowed the PR to the remaining:

Notes that come in through a pull keep their original commit date. If that date is earlier than the index's last refresh, the dependencies in those notes never reach deps/ready/topo.

For example: a teammate adds X blocks Y, you pull, and Y still shows as ready. The fix here tracks note object IDs instead of dates, and it also drops edges for deleted issues. Repro and tests are in the description.Let me know if you'd prefer to solve this differently.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants