fix(dir-config): route memory reads through .hivemind, not just capture#316
Conversation
`.hivemind` resolved correctly, but only the capture path consumed it — every read path (memory search, proactive recall, the VFS shell) called loadConfig() raw. A routed directory captured to its workspace while reading from the global one, and the SessionStart banner reported the routed identity regardless, so the misrouting presented as success. Route the three read paths through resolveDirConfig, and separate the two concerns the file expresses: - orgId / workspaceId are IDENTITY — reads and writes alike - collect is a CAPTURE switch — writes only collect:false previously short-circuited the whole overlay, silently dropping a workspaceId set alongside it. Splitting them makes "read this workspace, never write to it" expressible, and removes a config field that could be set and quietly ignored. whoami reported raw stored creds, so it misreported inside a routed directory — and, independently of this feature, under HIVEMIND_ORG_ID / HIVEMIND_WORKSPACE_ID as well. It now reports the effective identity for the cwd and discloses whether a .hivemind or the environment overrode the stored values, so it agrees with the banner instead of contradicting it. The resolver was fully unit-tested and correct; nothing asserted that any consumer used it, which is why this shipped green. The added tests drive a real read through the hook and assert the workspace it resolves to — they fail against the unfixed code. The MCP server (src/mcp/server.ts) is still unrouted: it is long-lived per-host and its process.cwd() does not track a session across directories, so it needs a different mechanism and is left for a follow-up.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughDirectory-based identity routing now applies to memory reads and writes, while ChangesDirectory routing and identity reporting
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Command
participant resolveDirConfig
participant DeeplakeApi
participant Memory
Command->>resolveDirConfig: resolve config for working directory
resolveDirConfig-->>Command: effective org and workspace
Command->>DeeplakeApi: create memory client with effective config
DeeplakeApi->>Memory: read or write using routed identity
Memory-->>DeeplakeApi: memory result
DeeplakeApi-->>Command: operation result
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Coverage ReportScope: files changed in this PR. Enforced threshold: 90% per metric (per file via
File Coverage — 7 files changed
Generated for commit cdf71c9. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/commands/whoami.ts`:
- Around line 38-48: The whoami output can pair an environment-selected org ID
with a stale credential-derived org name. In src/commands/whoami.ts lines 38-48,
update the org display in the lines array to show the effective org ID whenever
the environment changed the organization, using envMoved while preserving the
existing name display otherwise. In tests/shared/dir-config-read-routing.test.ts
lines 144-149, add a concrete HIVEMIND_ORG_ID assertion covering this behavior.
In `@src/hooks/pre-tool-use.ts`:
- Around line 328-332: Namespace the cached index used by the read-routing flow
around resolveDirConfig by session, organization, and workspace rather than
session alone, using the effective identity derived from the requested cwd. Add
coverage in tests/shared/dir-config-read-routing.test.ts lines 52-74 that
performs two routed reads in one session with a stateful cache and verifies each
organization/workspace receives its own index.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 98ac96d8-b424-45fa-83c5-0b2cb9d0fe33
📒 Files selected for processing (11)
README.mdsrc/commands/auth-login.tssrc/commands/whoami.tssrc/dir-config.tssrc/hooks/pre-tool-use.tssrc/hooks/recall.tssrc/hooks/session-start.tssrc/shell/deeplake-shell.tstests/claude-code/auth-login-dispatch.test.tstests/shared/dir-config-read-routing.test.tstests/shared/dir-config.test.ts
| // Attribute each override precisely: `config` has already folded the env in, | ||
| // so a diff against `creds` is the env's doing, and a diff between `eff` and | ||
| // `config` is the .hivemind's. | ||
| const envMoved = config.orgId !== creds.orgId || config.workspaceId !== storedWs; | ||
| const dirMoved = !!res.found && | ||
| (eff.orgId !== config.orgId || eff.workspaceId !== config.workspaceId); | ||
|
|
||
| const lines = [ | ||
| `User org: ${eff.orgName ?? eff.orgId}`, | ||
| `Workspace: ${eff.workspaceId}`, | ||
| `API: ${eff.apiUrl}`, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
An environment-selected org can be printed with the stored org’s name. orgId reflects HIVEMIND_ORG_ID, while orgName can still originate from credentials.
src/commands/whoami.ts#L38-L48: display the effective org ID when the environment changed the organization.tests/shared/dir-config-read-routing.test.ts#L144-L149: add a concreteHIVEMIND_ORG_IDassertion.
📍 Affects 2 files
src/commands/whoami.ts#L38-L48(this comment)tests/shared/dir-config-read-routing.test.ts#L144-L149
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/commands/whoami.ts` around lines 38 - 48, The whoami output can pair an
environment-selected org ID with a stale credential-derived org name. In
src/commands/whoami.ts lines 38-48, update the org display in the lines array to
show the effective org ID whenever the environment changed the organization,
using envMoved while preserving the existing name display otherwise. In
tests/shared/dir-config-read-routing.test.ts lines 144-149, add a concrete
HIVEMIND_ORG_ID assertion covering this behavior.
| // Reads are routed by the nearest `.hivemind` exactly like capture is: a | ||
| // directory pinned to another org/workspace must SEE that workspace's memory, | ||
| // not the global one. `collect` is a capture switch and deliberately does not | ||
| // gate reads (see src/dir-config.ts). | ||
| const config = resolveDirConfig(baseConfig, input.cwd ?? process.cwd()).config; |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
Directory routing does not isolate the session index cache. The effective identity changes by cwd, but /index.md remains cached only by session.
src/hooks/pre-tool-use.ts#L328-L332: namespace cached indexes by session, organization, and workspace.tests/shared/dir-config-read-routing.test.ts#L52-L74: test two routed reads in one session using a stateful cache.
📍 Affects 2 files
src/hooks/pre-tool-use.ts#L328-L332(this comment)tests/shared/dir-config-read-routing.test.ts#L52-L74
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/hooks/pre-tool-use.ts` around lines 328 - 332, Namespace the cached index
used by the read-routing flow around resolveDirConfig by session, organization,
and workspace rather than session alone, using the effective identity derived
from the requested cwd. Add coverage in
tests/shared/dir-config-read-routing.test.ts lines 52-74 that performs two
routed reads in one session with a stateful cache and verifies each
organization/workspace receives its own index.
The routing change added an `input.cwd ?? process.cwd()` branch to recall.ts but no test drove it — recall's routing shipped in the previous commit asserted only indirectly, and the per-file branch threshold (90%) caught it at 88.63%. Record the DeeplakeApi ctor args in the existing mock so a test can assert WHICH org/workspace recall searched, then cover the routing cases directly: pinned workspace, org+workspace inherited from an ancestor, collect:false still routing reads, the unrouted default, and the process.cwd() fallback when the payload omits cwd. Branch coverage for recall.ts: 88.63% -> 90.9%.
The bug
A user set
workspaceIdin a.hivemind, opened a session, and still saw the default workspace's files. The file was correct and the feature was installed — reported against v0.7.131, and.hivemindsupport shipped in v0.7.123..hivemindresolved fine. Only the capture path ever consumed it. Every read path calledloadConfig()raw and never looked at.hivemindat all:~/.deeplake/memorysrc/shell/deeplake-shell.ts:62grep/catinterceptionsrc/hooks/pre-tool-use.ts:269src/hooks/recall.ts:201So a routed directory wrote to its workspace and read from the global one.
The banner made it worse.
session-start.ts:342built the disclosure from the overlaid config, printingrouted by /path/.hivemindwhile every readable file still came fromdefault— confirming to the user that their config worked. That's what cost them the debugging time; an honest banner would have made this a sixty-second diagnosis.The fix
Route the three read paths through
resolveDirConfig, and separate the two concerns the file expresses:orgId/workspaceIdare identity — reads and writes alikecollectis a capture switch — writes onlycollect: falsepreviously short-circuited the whole overlay, so{ "collect": false, "workspaceId": "x" }silently droppedworkspaceId— the same dead-config bug in miniature. Splitting them also makes "read a shared workspace, never write to it" expressible. Reads remain authorized by the existing token; nothing new is reachable.hivemind whoamiwas lying tooIf you ask an agent "what workspace am I in?", it runs
whoami. That readloadCredentials()directly, so it reported the global workspace inside a routed directory — while the banner said otherwise, leaving the agent two contradictory sources.This is broken on
mainindependently of.hivemind:whoaminever calledloadConfig(), soHIVEMIND_WORKSPACE_ID=x hivemind whoamimisreports today. It now reports the effective identity for the cwd and discloses whether a.hivemindor the environment overrode the stored values.Why CI stayed green
resolveDirConfigwas thoroughly unit-tested and correct. Nothing asserted that any consumer used it. The bug wasn't in any file — it was in four call sites that didn't exist, which no unit test and no file-level review can see.tests/shared/dir-config-read-routing.test.tstherefore asserts the consumer: it drives a real read through the hook and checks which workspace the backend resolves to. Verified to fail against the unfixed code (the 4 routing assertions fail; the no-op cases pass in both, as they should).Verification
tree-sitter-pythonmissing from the graph extractor, 1 is aflush-memorynetwork timeout that fails identically at baseline.dir-config.test.tsdeliberately flipped (thecollect:falseoverlay short-circuit), rewritten rather than deleted, with the rationale inline.Follow-ups (not in this PR)
src/mcp/server.ts:43). It's long-lived per-host and itsprocess.cwd()won't track a session across directories, so it needs a different mechanism — likely cwd threaded per tool call. Deliberately not half-fixed here..hivemind(workspaces,org list, …). Lower impact since they're about the account rather than the directory, but worth a pass.🤖 Generated with Claude Code
https://claude.ai/code/session_017SDmiDuUn7Wqhi7qdn1p1f
Summary by CodeRabbit
New Features
.hivemindconfig now routes both memory reads and trace writes to the configured workspace/org.whoamioutput for the effective identity, reflecting both environment and directory overrides.Bug Fixes
collect:falseno longer blocks read routing; it only disables capture/writes.Documentation
.hiveminddocumentation with clarified semantics and new routing “recipes,” including notes about auth token behavior.Tests
whoamirouting/capture opt-out messaging.