diff --git a/plans/git-native-kb/02-git-working-tree-backend.md b/plans/git-native-kb/02-git-working-tree-backend.md new file mode 100644 index 000000000..36ef75ed8 --- /dev/null +++ b/plans/git-native-kb/02-git-working-tree-backend.md @@ -0,0 +1,39 @@ +# 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.