diff --git a/CLAUDE.md b/CLAUDE.md index 0331479..d75904c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -84,7 +84,13 @@ a single JSON object, so the formula carries **every** mount as a `prefix → URL` pair — the prefix being the mount's path as the agent sees it from the session's folder, or an empty prefix with the session's own subpath baked into the URL when the session runs inside the mount; emitting only the first mount -hung one project's paths on another project's base URL. Then an +hung one project's paths on another project's base URL. The same context also +names what teammates changed since the last turn ("re-read before editing"), +drained from the **inbound spool** (`internal/store/inbound.go`, a near-copy of +the read spool): `materialize` appends every path it writes or removes, and the +hook drains it *after* its own cycle — a `Result` field would report nothing, +because the daemon has usually materialized the peer's change seconds earlier. +Advisory only: nothing blocks a write. Then an async push on PostToolUse Write/Edit, and `bdrive read-log` on Read/Grep/Bash for the read heatmap. The inline hook commands `internal/agenthooks` writes must stay a fast no-op outside BearDrive folders diff --git a/architecture/cli-sync.md b/architecture/cli-sync.md index beb33e3..662fc27 100644 --- a/architecture/cli-sync.md +++ b/architecture/cli-sync.md @@ -116,9 +116,11 @@ classDiagram +SaveNote / LoadNote +LogRead(rel, session) read spool +PendingReads dedup on path+session + +LogInbound / DrainInbound +Lock() flock } note for Store "internal/store — ~/.bdrive/volumes/mount-id: content-addressed blobs, per-device journal copies, state cache, paused marker (free funcs Paused/SetPaused, no flock)" + note for Store "inbound.jsonl is the read spool's twin, running the other way: materialize appends every path it wrote or removed for a peer, and `sync --hook` drains it into the turn's context (re-read before editing). A spool and not a Result field because the daemon usually materializes the change seconds before the turn starts, so the hook's own cycle sees nothing. Capped, best-effort, never fails a cycle" class Op { +Seq +Lamport +Time +Device diff --git a/cmd/bdrive/cmds.go b/cmd/bdrive/cmds.go index 8f3c0ff..52fb127 100644 --- a/cmd/bdrive/cmds.go +++ b/cmd/bdrive/cmds.go @@ -105,8 +105,10 @@ list in .bdrive/config.json is never pruned against either.`, if err != nil || !ok || syncBlocked(proj) != "" { continue } - if base, ok := runHookSync(cmd, target, sessionID, hookLabel); ok { - links = append(links, hookLinkFor(folder, target, base)) + if h, ok := runHookSync(cmd, target, sessionID, hookLabel); ok { + link := hookLinkFor(folder, target, h.base) + link.paths = h.paths + links = append(links, link) } } emitHookContext(cmd, links) diff --git a/cmd/bdrive/hooksync.go b/cmd/bdrive/hooksync.go index 9b9162a..8832bf9 100644 --- a/cmd/bdrive/hooksync.go +++ b/cmd/bdrive/hooksync.go @@ -9,6 +9,8 @@ import ( "time" "github.com/spf13/cobra" + + "github.com/runbear-io/beardrive/internal/store" ) // `bdrive sync --hook