fix(hooks): every mount gets its own hub link, so agents stop mixing projects up (#105)

A session whose root holds two connected folders got exactly one project's
base URL in its turn context: `bdrive sync --hook` emitted for the first
mount and stopped. Agents then hung the other project's paths on that URL,
producing links to project B carrying project A's path — confidently wrong,
and 404 on arrival.

The context now carries every mount as a `prefix → URL` pair, where the
prefix is the mount's path as the agent sees it from the session's folder.
A session started INSIDE a mount has no prefix to strip, so its own subpath
is baked into the base URL instead — the other half of the same bug, which
made every link from a subdirectory session miss its leading segments.

The formula also now states outright that the URL path is folder-relative
and that a path matching no listed folder is not synced and must not be
linked at all. Encoding is per-segment, `/` left literal (encodePathSegments).

Two more fell out along the way:

- `runHookSync` returns nil on every path by design ("a hook must never
  fail the turn"), so the caller's `err == nil` guard could never be false.
  A first mount that emitted nothing — non-hub remote, session open error —
  still consumed the one emission, and NO mount got a link. It now reports
  whether it produced a URL.
- stdin was read once per mount, so with several mounts only the first got
  its session note stamped. The event JSON is read once per run now.

Single-mount output is unchanged apart from the folder-relative sentence.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Snow Lee (Sungwon)
2026-07-31 15:15:02 +09:00
committed by GitHub
co-authored by Claude Opus 5
parent 1c703c95f8
commit a84fe444f5
5 changed files with 238 additions and 34 deletions
@@ -31,7 +31,9 @@ With no argument, `bdrive url` gives the project home.
:::tip[Agents do this automatically]
The sync hook `bdrive init` registers injects the project's
gated-link formula into the agent's context, so a connected agent appends
`path` [🔗](link) to every synced path it mentions — without being asked. See
`path` [🔗](link) to every synced path it mentions — without being asked. If a
session's root holds several connected folders, each one's URL goes in, so a
path is always linked to the project it actually lives in. See
[Set up with your agent](/start/setup/).
:::