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

41 lines
3.6 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/glob/grep`/structure comes from the **real git tree** instead of the `path_resolver` + DB folder walk — **without regressing `read_file`'s chunk-level citations** (see [`00c-shared-contract.md`](00c-shared-contract.md) C2).
## 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).
- **Structure from git; `read_file` content still renders from chunks (v1).** `als_info`/`aglob_info`/`alist_tree_listing`/existence read the git working tree. But `read_file` today renders XML from `Chunk` rows and registers `[n]` citations (`aload_document``render_full_document`) — v1 **keeps that render path** (sourced from the derived chunks, one-way from git) so citations don't regress. `grep` may scan working-tree source directly (its matches are already coarse `<chunk-match>` snippets). See C2.
- **Writes stage in the working tree** (commit at end of turn — Phase 3). Reuse the current staging/`Command.update` pattern, backed by the working tree rather than the `files` cache.
- **`path_resolver` path computation retires for flagged workspaces** — folder walk + collision suffixing is replaced by real repo paths (filename rules still reused, C1). 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`.
- Structure calls → `GitRepoService` primitives (`als_info`/`alist_tree_listing``list_tree`, `aglob_info``list_tree`+`fnmatch`, `agrep_raw`→working-tree scan).
- `read_file`/`aread`/`aedit` existence + content: **reuse the existing chunk-render path** (`aload_document`/`render_full_document`) so `[n]` citations are unchanged in v1.
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`/`glob`/`grep`/`list_tree` return results **identical** to `KBPostgresBackend` for the same content (golden comparison).
- `read_file` of a nested path returns the rendered document view and registers the **same `[n]` citations** as the Postgres backend (no citation regression).
- 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.
- **Raw-git-blob reads with per-document citations** — deferred (C2); revisit with the `raw/`+`wiki/` content model.
## Resolved (see [`00c-shared-contract.md`](00c-shared-contract.md))
- **Read rendering:** structure from git, `read_file` content keeps the chunk-render + citation path in v1 (C2).
- **glob/grep source:** working-tree scan via `GitRepoService` (dulwich plumbing optimization deferred).