Key Technical Challenges
Drifts, concurrency, and cross-platform hooks
Building an attribution blamer means solving several problems in Git's plumbing layer. Here are the three hardest ones and how ghost handles them.
1. Line Range Drift
When a file grows (new code inserted above), every existing line shifts downward. But ghost notes store fixed line numbers like 5-12,18. Without correction, these ranges point to the wrong lines after the first insert.
Ghost solves this by using git blame --line-porcelain, which reports the original commit and line number for each line of the file, not its current position. The blamer resolves each noted range through blame history — it follows the line back to the commit that last modified it, checks whether that commit has a ghost note, and only then attributes the line. This means ranges stay accurate through rebases, merges, and upstream changes.
2. Concurrent Agent Sessions
If two agents edit the same file in overlapping sessions, their line ranges can collide. For example, Claude Code writes lines 10-20 and Cursor writes lines 15-25 — who owns line 18?
The post-commit merger uses a timestamp-based resolution: sessions are ordered by ts_end, and overlapping ranges are split so each line belongs to the session that touched it last. This last-write-wins model is simple, deterministic, and works without human intervention. The tradeoff is that if agents are truly concurrent (same second), the tiebreaker is arbitrary — but in practice, agent edits are serialized by the filesystem anyway.
3. Notes Ref Distribution
Git stores notes locally under refs/notes/, but it does not push them to the remote by default. If notes stay local, CI can't read them during audit.
The ghost install script configures two additional push refs:
$ git config --add remote.origin.push refs/notes/ghost $ git config --add remote.origin.push refs/notes/ghost-verified
These ensure both note refs are published alongside commits on every git push. If a push fails for either ref, the CI auditor will flag those commits as unverified — which is the correct failure mode. Missing notes always look like ghost wasn't running, never like a silent pass.
There is a fourth challenge worth noting: Windows compatibility. The checkpoint binary uses popen() to run git commands, which behaves differently on Windows (non-WSL). Path separators, line endings, and shell quoting all need platform-aware handling in the C++ layer.