SurfSense/plans/git-native-kb/02-git-working-tree-backend.md

39 lines
2.8 KiB
Markdown

# Phase 2 — Git-working-tree backend
> Build after Phase 1. Umbrella: [`00-umbrella-plan.md`](00-umbrella-plan.md).
> Replaces the read-side fake (`KBPostgresBackend`) with a backend over the **real git tree**. Agent tools are unchanged.
## Objective
A `GitTreeBackend` implementing deepagents' `BackendProtocol` over the Phase-1 `GitRepoService`, so the agent's `ls/read/write/edit/mv/rm`/`glob`/`grep` operate on real files in the workspace git repo instead of faked-over-Postgres rows.
## Locked model
- **Same tool interface, new backend.** Implement the exact `BackendProtocol` surface `KBPostgresBackend` implements: `als_info`, `aread`, `awrite`, `aedit`, `aglob_info`, `agrep_raw`, `alist_tree_listing` (return the upstream `WriteResult`/`EditResult`/`FileInfo`/`GrepMatch` shapes — no extra fields).
- **Reads hit git; writes stage in the working tree** (commit happens at end of turn — Phase 3). Reuse the same staging/`Command.update` pattern the current wrappers use, but backed by the working tree rather than the `files` cache + Postgres.
- **`path_resolver` retires for flagged workspaces** — virtual `/documents/...` paths become **real repo paths**. Keep `DOCUMENTS_ROOT` as the repo-relative prefix for continuity.
- Selected via the resolver behind `KB_GIT_ENABLED`.
## Work items
1. New `.../filesystem/backends/git_tree.py``GitTreeBackend(workspace_id, runtime)` implementing `BackendProtocol` over `GitRepoService`.
- Map protocol calls → `GitRepoService` primitives (`aread``read_file`, `aglob_info``list_tree`+`fnmatch`, `agrep_raw`→tree scan, etc.).
- Preserve read rendering behavior the agent expects (document text/XML view) so reads never regress.
2. Wire into `.../filesystem/backends/resolver.py::build_backend_resolver`: when `KB_GIT_ENABLED` and `workspace_id is not None`, return `GitTreeBackend(workspace_id, runtime)` instead of `KBPostgresBackend`.
3. Gate `path_resolver`/`kb_postgres` usage behind the flag (keep both paths compilable during rollout).
## Tests
- For a seeded repo, `ls`/`read`/`glob`/`grep` return results **identical** to `KBPostgresBackend` for the same content (golden comparison).
- `read` of a nested path returns file content; `glob("**/*.md")` lists the tree; `grep` respects the existing match caps.
- Resolver returns `GitTreeBackend` only when the flag is on; falls back to `KBPostgresBackend`/`StateBackend` otherwise.
## Out of scope
- End-of-turn commit → Phase 3. Index refresh → Phase 4.
- Desktop-local (`MultiRootLocalFolderBackend`) path — unchanged.
## Open questions
1. Read rendering: serve raw markdown from git vs. reproduce the current rendered-document view (citations). Confirm what the agent contract needs.
2. Whether `grep`/`glob` scan the working tree directly or use git plumbing (`git grep` semantics via dulwich) for large repos.