Generated report
Dev Log: 2026-06-27
The session opened on a nasty little failure mode. You rebase. The post-rewrite hook quietly remaps your ledger entries to new commit SHAs. You move on. Somewhere later — a fresh clone, a teammate pulling — the rewritten commits show up as having no ledger entries at all, because the relink was never committed and origin still points at the orphaned anchors.
That's the bug we walked into, and it set the tone for everything that followed.
The first instinct was to make the hook auto-commit its relink. Tempting, and wrong. The hook runs mid-rebase, mid-pull --rebase — squarely inside a git operation the user is driving. Sneaking a commit into someone else's in-flight history rewrite is the kind of "help" that earns a tool a permanent uninstall. So we went the other way: warn loudly on stderr, let the human decide. The hook now tracks what it remapped and tells you. A test pins the behavior down — runs the hook, asserts the remap, asserts the warning, asserts silence when nothing matched.
Then CI went red, and the warning we just shipped became the warning we couldn't reach.
The hook used read -d — bash-only. macOS /bin/sh is bash-in-POSIX-mode and accepts it. Debian's /bin/sh is dash and emphatically does not. So the hook had been silently bailing out on Linux for who knows how long, and the new test was the first thing honest enough to surface it. Reproduced locally by symlinking sh to dash, swapped find -print0 for newline-delimited find (entry paths can't contain newlines, so this is safe), and added a comment in the hook banning bash-isms outright. The footgun gets a sign on it.
But there was a deeper problem hiding behind both fixes: the people who already installed the hook would never get either of them. Hook installation skips when a timbers section is already present. The dash fix, the relink warning — neither could reach existing repos, and nothing in the tool would tell you your hook had gone stale.
So doctor learned a new trick. It compares the installed post-rewrite section against what the generator would produce right now, and warns on drift. doctor --fix regenerates it — remove the timbers section, append a fresh one, preserve everything else. No version stamps, no hash markers to bump. The generator function itself is the source of truth; if it changes, drift appears automatically. Scoped just to post-rewrite, because pre- and post-commit are thin shims that don't carry logic worth rotting.
The last thread was smaller but worth pulling. The compact prime --hook output — the default session-start injection agents actually see — was missing the commit → log → push ordering rule. The full prime had it. MCP had it. The compact one didn't, which meant a downstream agent nearly deleted its own local copy of the rule, assuming prime carried it fleet-wide. It does now, with a test that would have caught the omission in the first place.
The pattern across all four: a fix isn't shipped until the path that delivers it is also shipped.
That's the takeaway worth keeping. A generator improvement doesn't reach users whose install predates it. A protocol rule doesn't reach agents reading the compact path. A silent hook failure doesn't reach anyone at all. Every one of these bugs was, underneath, a delivery gap masquerading as a code bug — the fix existed somewhere, just not where it needed to be.
doctor --fix closes the upgrade gap for hooks going forward, but it only helps people who run doctor. The relink warning helps only people whose shell can execute the hook. The compact prime fix helps only sessions that start fresh after this lands. None of these are total solutions. They're the honest ones available.
It feels like solid ground, but the kind of solid ground you reach by noticing you were standing on a trapdoor. Worth defending.
Written with AI assistance from session logs.