Repository navigation
Get overlap warnings ready to go live - #738
anirudhkumar-nanonets wants to merge 7 commits into
Conversation
… follow-ups trail check flags TELEMETRY.md:71 against the Oct 27 learning on Claude's real HOME: a word match on "Claude ... trail ... never" in the new telemetry row, not the same change.
🌱 graft blast radius3 areas changed → 9 areas can be affected. 44 dependent symbols, depth 2. flowchart TB
A0(("Cloud Onboarding<br/>13 symbols"))
A1(("Claude Session Metrics<br/>10 symbols"))
A2(("CLI Team Commands<br/>9 symbols"))
A3(("Notes Storage<br/>4 symbols"))
A4(("Setup Initialization<br/>3 symbols"))
AX(("4 smaller areas<br/>5 symbols"))
classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
class A0,A1,A2,A3,A4 reached;
classDef tail fill:#EEF2F3,stroke:#9AA4A9,stroke-width:1px,color:#3A4247;
class AX tail;
Who knows this code — 2 people across 12 areas
Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no All 44 dependent symbols, grouped by areaCloud Onboarding — 13 symbols in 6 files
Claude Session Metrics — 10 symbols in 10 files
CLI Team Commands — 9 symbols in 1 file
Notes Storage — 4 symbols in 3 files
Setup Initialization — 3 symbols in 3 files
Telemetry Tracking — 2 symbols in 2 files
CLI Skills — 1 symbol in 1 file
Learning Sessions — 1 symbol in 1 file
MCP Tools — 1 symbol in 1 file
Test signal per changed area — 2 ✓ · 1 –Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.
61 test suites also reference this code62 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.
Open the interactive graph → — click an area to see its dependent symbols at file:line. |
trail check flags TELEMETRY.md:71 and hooks.ts:113 against the Oct 27 learning on Claude's real HOME: word matches ("claude ... trail", "trail ... never ... loads"), not the same change.
…e one way trail check flags TELEMETRY.md and hooks.ts lines against the Oct 27 learning on Claude's real HOME (word matches on "Claude ... copy ... project"), and the listNotes line against the Oct 22 learning on filtering inside listNotes: this only changes which checkout listNotes reads, no filter is added.
The issue: in Claude Desktop worktree sessions, overlap warnings never fired, and learnings attached to a file never reached Claude when it opened or edited that file. Where overlap warnings did fire, they warned about branches that were already merged: without
gh, 2 in 3 warnings on this repo were false alarms. And a doc comment Claude added above a function a teammate is changing gave no warning.Why: in a worktree session the hooks take the main checkout as the project (
CLAUDE_PROJECT_DIR), so an edited file came out as.claude/worktrees/<name>/src/...and matched no branch and no learning'stouches. Separately, Trail-Code squash-merges PRs and leaves the branch on GitHub, so git still calls a merged branch open. And Claude's Edit repeats a line or two it doesn't change to anchor the edit, like the}closing the code above; the check counted those as edited and took the smallest symbol they touched.The fix: both hooks now name the file from the checkout it's in. Overlap warnings skip a function whose added lines were already added on main (
git log -S), and they also cover the person's own other open branches, never the one they're on. Three events count what reaches Claude:overlap_warned,overlap_actedandlearnings_on_touch.Moves:
overlap_warnedwithpr=open÷overlap_warnedwithpr≠unknown(split bywhose). Acted =overlap_acted÷overlap_warned.learnings_on_touchwithworktree=true.posthog_event_full_view). Today: 0. None of these events existed (I queried the last 3 days foroverlap%and got 0 rows).ghand from 32% to 93% without it, and none of the 86 real warnings were dropped.What changed
src/notes/home.ts:otherCheckout(project, file)returns the checkoutfileis in when it's another checkout of the same repo (a linked worktree), comparing the shared git dirs by real path. A file in the project's own checkout, outside git, or in another repo (a submodule included) gives null.src/claude/hooks.ts:editOverlapcompares from that checkout, reading the branch list the session start wrote for the project. It usespayloadSessionIdlike the prompt hook.learningsOnTouchnames the file, and reads learnings, from that checkout, so a learning on the worktree's branch counts.src/notes/edit-overlap.ts:landedSincedrops a function when each of the 3 longest lines (12+ characters) the branch added to it was also added on main since the fork. It runs only when both changes land in the same function, at about 7 ms per check.new_stringkeeps fromold_stringat either end (anchors). A comment block directly above a function is part of it (withComment), since Go doc comments and JSDoc sit outside the span the parser gives the function.mine, and the directive says "Your other open branch … also changes …".src/notes/branches.ts: the samegh pr listcall also keeps which branches have an open PR (open), forpr: open | none | unknown.src/claude/overlap-telemetry.ts(new):overlap_warnedfires per warning shown, withprandwhose(teammate or mine).overlap_actedfires once per warning, when a later prompt in that session names the teammate or the branch.learnings_on_touchfires inlearningsOnTouchwithvia(read, edit or command) andworktree(true or false).TELEMETRY.mdandcontract.ts: the three events, all with closed-set values. No names, branches or paths travel.How I found and measured it
withLock()in a Desktop worktree session with trail 0.26.0 installed. Shrish's open Wait instead of crashing when Windows refuses a lock file that's being deleted #682 changes that function. The hook ran and returned the blast radius but no overlap line. Its session and stats files were written under the main checkout. The new worktree tests for both hooks fail without the fix and pass with it.functionOverlaps, as a teammate with no branches of their own, and counted a warning as real when its branch has an open PR (gh pr list):End to end: two people, two isolated machines, real Claude Code
Each person has their own
HOME,.gitconfig, npm prefix with@trailhq/trail-codepacked from this branch, clone, andtrail init -y. Their hooks are wired into their own~/.claude/settings.json. Each also has their own telemetry listener on localhost (GRAFT_POSTHOG_HOST). They share only a bare git remote standing in for GitHub; the macOS keychain folder is linked in soclaudecan sign in.Overlap warnings. Kumar pushed
kumar/backoff, which changesbackoff(). Priya pushedpriya/retries, which changesretries(), then added a worktree.claude -pfrom her main clone, editing the worktree's copy, which is the desktop-app setup. Her reply ended with:claude -pin his clone, editingretries():git diff origin/main...origin/<branch>the warning names before answering./batch/: Priya sentoverlap_warnedwith whose=teammate and with whose=mine, thenoverlap_actedwith whose=teammate after a follow-up prompt named Kumar. Kumar sentoverlap_warnedwith whose=teammate.prwasunknown(nogh), and no event carried names, branches or paths.Learnings on file touch. In Priya's setup, Claude reads her worktree's copy of
src/retry.ts, which a learning on the worktree's branch lists.learningsOnTouchfix): the learning did not reach Claude.learnings_on_touchwas queued with via=read and worktree=true.Live, in Claude Desktop
On 30 Oct I installed this branch's build globally and ran three Desktop worktree sessions on another repo of ours (Go), each asked to add a one-line comment to one function:
git diffit names, and ended with a correct "🔀 trail ·" line about a likely one-line merge conflict. The session recorded it aspr=open,whose=teammate.funcand anchored the Edit on the}closing the struct above. No warning: the edit's lines ran from the struct's last line to thefuncline, and the struct was the smaller symbol. With the anchor and doc-comment fix, replaying that exact Edit warns about the right branch and function, and the other two come out the same.Choices I made
git log -Son the branch's added lines rather than comparing the function's text with main's. Comparing text dropped only 119 of 182 merged-branch warnings, because main often changes a function again after the merge.otherCheckout) serves both hooks. Without it,learningsOnTouchwould read another repo's learnings for a file Claude opened there.Follow-ups (not in this PR)
openlist. That removes the 16 false alarms left withgh.gh, merged branches fill the 30-branch cap and push out real ones (7 here). Run the added-lines check when the list is built.dirtonotesOnTouchfor its stale check. Once both are in, that call should pass the file's checkout. They merge without a conflict.Checks
npm testwith a scratch HOME: 4,132 pass and 3 fail. All three (graft-to-trail,hosts-trail,upkeep-hooks) also fail on unchanged main. In an earlier run,personAtTerminal reads the real process table…inskills-store-held.test.tsfailed once under load; it reads the live process table, passes alone, and this PR doesn't touch it.trail check: 3 conflicts, none of them real.TELEMETRY.md:71andhooks.ts:113are word matches ("Claude … whose", "trail … never … loads") against the Oct 27 learning on Claude's real HOME.hooks.ts:195matches the Oct 22 learning on filtering insidelistNotes; this only changes which checkoutlistNotesreads, and adds no filter.This takes in what was #741, which I closed.
🤖 Generated with Claude Code