Proj/multi repos knowledge sharing#350
Conversation
- Add resolveProject() with priority: flag > direct > linked > walked-up > null - Add workspace-link schema (.brv-workspace.json) and WORKSPACE_LINK_FILE constant - Make status handler resolver-aware with projectRoot, workspaceRoot, resolutionSource, shadowedLink, resolverError fields - Add --verbose flag to brv status for resolution diagnostics - Make prerun hook resolver-aware; auto-init only when no project found - Add minimal brv unlink command and TUI /unlink (resolver-bypass) - Migrate curate/view.ts from findProjectRoot to resolveProject - TUI status now sends cwd in request - Surface broken/malformed workspace link errors as actionable status warnings - Cross-platform path handling (path.sep instead of hardcoded /) - 18 resolver unit tests + updated prerun hook tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…t reassociation Make all entry points (CLI, TUI, MCP) use the canonical resolveProject() resolver so tasks from workspace-linked subdirectories route to the correct project. - CLI: pre-resolve projectPath/workspaceRoot in withDaemonRetry, pass through to query and curate commands - TUI: pass resolved project info from oclif main → startRepl → transport store, use it for daemon registration and reconnect (no raw cwd fallback) - MCP: use resolveProject() for project context resolution with retry-aware association, propagate errors instead of swallowing - TaskRouter: correct fallback order (explicit > fresh cwd resolution > stale registration > raw clientCwd), containment validation, short-circuit for explicit payloads - ClientManager: support reassociation via updateProjectPath() so clients can move between projects after link/unlink - ConnectionCoordinator: handle reassociation (not just first association) - Thread workspaceRoot through transport schemas, task events, and task routing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ding (PR3) Thread workspaceRoot and projectRoot through all three executors so linked workspaces get correct search scoping, path resolution, and cache isolation. - Query executor: derive workspace scope for search, inject scope variable into sandbox for agent follow-up searches, include workspaceRoot in cache fingerprint to prevent cross-workspace cache bleed - Curate executor: use projectRoot (not workspaceRoot) as base directory for post-processing (snapshot, summary propagation, manifest rebuild) since .brv/ lives at projectRoot - Folder-pack executor: resolve relative folderPath from clientCwd (shell semantics), default absent folderPath to workspaceRoot, write temp files to projectRoot - Agent-process: thread projectPath as projectRoot to curate/folder-pack, thread workspaceRoot to all executors - Expose scope in SearchKnowledgeOptions (tools-sdk) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…k slash command (PR4) Adds `brv link [project-root]` oclif command and `/link` TUI slash command to create .brv-workspace.json link files, complementing the existing `brv unlink`. - Auto-detect walks up from cwd looking for nearest .brv/config.json, stopping at .git boundary to prevent cross-repo discovery - Validation guards: shadow (cwd has .brv/), ancestor check, self-link - Idempotent: succeeds silently when already linked to same target - TUI /link canonicalizes explicit paths via realpathSync and sends resolution.projectRoot (not raw arg) to ASSOCIATE_PROJECT - Fix /unlink to skip ASSOCIATE_PROJECT when re-resolution fails, avoiding registration of non-project directories in daemon rooms - Export hasBrvConfig, hasWorkspaceLink, isDescendantOf, isGitRoot from resolve-project.ts for reuse by link command - 26 unit tests covering helpers, link flow, git-boundary stop condition Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 41 cross-module integration tests verifying workspace linking contracts: - link-unlink-lifecycle: resolver state transitions with real filesystem - resolver-to-task-router: workspace threading through task creation - workspace-scoped-execution: search scoping, cache isolation, path defaults - mcp-tool-workspace-resolution: per-call resolution and retry logic - format-status-workspace: workspace fields in status display Update README with workspace linking documentation. Update command tests for workspace-aware payload fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…, and status display (PR6) Cross-project knowledge linking allows a project to read another project's context tree as a read-only source. Adds schema (.brv/knowledge-links.json), multi-source BM25 index with local score boost, source-qualified document IDs, namespaced symbol tree ([alias]:path), three-layer write guard (curate executor, write_file tool, tools.writeFile sandbox), cache fingerprint isolation, and knowledge link status in CLI/TUI output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rmatting (PR6) Adds tests for knowledge-links.json loading/validation, multi-source search index building, and knowledge link status display formatting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s (PR7) Add oclif commands (link-knowledge, unlink-knowledge, list-knowledge-links) and TUI slash commands for cross-project knowledge linking. Surface knowledge link status in brv status with validity and file count display. Fix empty alias validation, malformed file visibility in status/list, and CLI path normalization consistency. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n broken links - StatusHandler now returns the actual client working directory instead of always returning the resolved project root (backward compat fix) - Query fingerprint cache validates knowledge link source keys on each hit, so deleting a linked project within the 30s TTL window correctly invalidates the cache - Added KNOWN LIMITATION doc for workspace-scoped query matching Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Feat/eng 1401
Conflicts: src/oclif/commands/status.ts src/shared/transport/types/dto.ts src/tui/features/commands/definitions/index.ts test/unit/infra/transport/handlers/status-handler.test.ts
# Conflicts: # src/oclif/commands/status.ts # src/oclif/hooks/prerun/validate-brv-config-version.ts # src/oclif/lib/daemon-client.ts # src/server/infra/transport/handlers/status-handler.ts # src/server/infra/transport/transport-connector.ts # src/shared/transport/types/dto.ts # src/tui/features/commands/definitions/index.ts # test/hooks/prerun/validate-brv-config-version.test.ts # test/unit/infra/transport/handlers/status-handler.test.ts
… full vocabulary alignment Rename user-facing commands, on-disk file formats, and internal symbols to eliminate the confusing link vs link-knowledge naming collision. Commands: - brv link → brv worktree add/remove/list - brv link-knowledge → brv source add/remove/list - TUI /link, /unlink → /worktree add/remove/list - TUI /link-knowledge, /unlink-knowledge → /source add/remove/list On-disk files: - .brv-workspace.json → .brv-worktree.json - .brv/knowledge-links.json → .brv/sources.json (top-level key: sources) Internal vocabulary: - WorkspaceLink → WorktreeLink, workspaceRoot → worktreeRoot - KnowledgeLink → Source, KnowledgeSource → SearchOrigin - sourceType: 'linked' → origin: 'shared' (document origin in search) - BrokenWorkspaceLinkError → BrokenWorktreeLinkError - knowledgeLinks DTO field → sources New: - brv worktree list / /worktree list (inspect current link state) - /source add --alias flag (closes CLI/TUI parity gap) - Vocabulary glossary in README
Replace .brv-worktree.json pointer files with a git-style model where
.brv can be either a directory (real project) or a file (pointer to
parent project), matching how git uses .git/ vs .git file for worktrees.
Resolver:
- Walks up from cwd to find nearest .brv (file or directory)
- .brv directory → source: 'direct' (real project)
- .brv file → reads {projectRoot} pointer → source: 'linked'
- Stops at first .brv found, no skip-past behavior
Worktree CRUD (addWorktree, removeWorktree, listWorktrees):
- Parent stores registry in .brv/worktrees/<name>/link.json
- brv worktree add: dual-mode (from parent with path, or from child with auto-detect)
- --force flag backs up existing .brv/ to .brv-backup/ when converting to pointer
- Supports children and siblings, relative and absolute paths
Removed:
- .brv-worktree.json file format
- shadowedLink field (impossible in new model — .brv is one thing or the other)
- worktree-link-schema.ts (replaced by worktrees-schema.ts)
- WORKTREE_LINK_FILE constant
Fixes the UX bug where brv auto-creates .brv/ on first run, blocking
subsequent brv worktree add. Now brv worktree add --force handles this
by backing up and replacing the existing .brv/ with a pointer file.
The oclif init hook tried to mkdir .brv/ when running from a worktree directory, but .brv was already a file (pointer) causing EEXIST error. Now the hook checks isWorktreePointer() and skips auto-init entirely when cwd is a worktree — the project lives at the parent. Also update worktree index.ts description to remove stale .brv-worktree.json reference, and update README accordingly.
Replace direct server imports in both oclif and TUI worktree/source
commands with transport event calls through the daemon, matching the
existing pattern used by status, curate, and query commands.
Transport layer:
- Add worktree-events.ts (worktree:add, worktree:remove, worktree:list)
- Add source-events.ts (source:add, source:remove, source:list)
- Add WorktreeHandler + SourceHandler server-side event handlers
- Register both in feature-handlers.ts
Oclif commands:
- Rewrite worktree/{add,remove,list}.ts to use withDaemonRetry
- Rewrite source/{add,remove,list}.ts to use withDaemonRetry
- Zero server/ imports remaining in any command file
TUI commands:
- Add worktree-api.ts + source-api.ts (apiClient.request wrappers)
- Rewrite all 6 slash commands to use API layer
- Zero server/ imports — respects tui/ import boundary
|
Claude finished @wzlng's task in 3m 37s —— View job PR Review: Multi-Repo Knowledge SharingOverall score: 4/5 — Well-designed, well-tested PR with clean architecture. A few correctness bugs and minor issues worth addressing before merge. SummaryThe git-style Issues Foundbug:
|
- Remove daemon process.cwd() fallback in worktree remove handler; make worktreePath required in WorktreeRemoveRequest - Fix sanitizeWorktreeName collisions (packages/api vs packages-api) by appending numeric suffix when registry entry already exists - Extract duplicated isDescendantOf to path-utils.ts (task-router and resolve-project had divergent implementations) - Throw on invalid --project-root flag instead of silently falling back to cwd-based resolution
|
Claude finished @wzlng's task in 3m 3s —— View job PR Review: Multi-Repo Knowledge SharingOverall score: 4/5 — Four of the six issues from the previous review are fixed. Two remain, plus one new finding on the write guard. The core implementation is solid and the architecture is clean. Previous Review — Status
Suggestions (7–9) acknowledged in code via comments; no changes required before merge. Remaining Issuesissue: Write guard conditional on optional
|
…le paths On macOS, realpathSync throws for non-existent files, falling back to resolve() which preserves symlink prefixes (e.g., /tmp/ vs /private/tmp/). Now canonicalizes the parent directory when the full path doesn't exist, ensuring consistent comparison with the context tree root.
|
Claude finished @wzlng's task in 4m 41s —— View job PR Review: Multi-Repo Knowledge Sharing
Overall score: 4/5 — Two issues from the previous review remain unfixed. The latest commit ( Previous Review — Status Update
Remaining Issuesissue: Write guard conditional on optional
|
…ite-guard Use the cross-platform isDescendantOf from path-utils instead of an inline helper that hardcodes '/' as the path separator.
|
Claude finished @wzlng's task in 1m 51s —— View job PR Review: Multi-Repo Knowledge Sharing
Overall score: 4/5 — Good progress: the Previous Review — Status Update
Remaining Issuesissue: Write guard conditional on optional
|
|
Claude finished @wzlng's task in 4m 24s —— View job PR Review: Multi-Repo Knowledge Sharing
Overall score: 4.5/5 — Three remaining issues from previous review cycles have been implemented as fixes in this review pass. The latest commit ( Previous Review — Status Update
Fixes Applied (commit
|
Multi-Repo Knowledge Sharing
Summary
Adds two capabilities for working across multiple repositories:
brvfrom monorepo subdirectories or sibling checkouts without creating nested.brv/directories. Uses a git-style model where.brvcan be either a directory (real project) or a file (pointer to parent project).Worktree linking (
brv worktree)How it works:
brv worktree addcreates a.brvpointer file in the target directory (like git's.gitfile in worktrees) and a registry entry in the parent's.brv/worktrees/. The resolver walks up from cwd to find the nearest.brv— if it's a file, follows the pointer; if it's a directory, uses it directly.Handles the case where
brvwas already run in the subdirectory (auto-init'd.brv/):--forcebacks up the existing.brv/to.brv-backup/and replaces it with a pointer file.brv worktree removerestores the backup.On-disk layout
Knowledge sources (
brv source)How it works: Adds entries to
.brv/sources.json(local project only — nothing written to the target). Duringbrv query, the search service indexes both the local context tree and all configured sources. Results from sources are tagged withorigin: 'shared'and the source alias. A write guard blocks any curate/write operations to shared source context trees.Architecture
Both features use the daemon transport event pattern:
shared/transport/events/(worktree-events.ts, source-events.ts)server/infra/transport/handlers/process the eventsThe resolver, CRUD operations, and search integration live server-side. The CLI and TUI are thin clients that send events and display results.
Commands
brv worktree add [path]brv worktree remove [path]brv worktree listbrv source add <path> [--alias]brv source remove <alias-or-path>brv source listTUI slash commands mirror the CLI:
/worktree add,/source list, etc.Internal vocabulary
worktree/sourcebrv worktree add,brv source list.brvfile (pointer) /.brv/sources.json{"projectRoot": "/path"}source: 'direct' | 'linked'origin: 'local' | 'shared'Test plan