From ea5fbec9114f792a58a1a4f684855bd0a0c12db1 Mon Sep 17 00:00:00 2001 From: CREDO23 Date: Fri, 24 Jul 2026 19:33:59 +0200 Subject: [PATCH] plans: fix phase 2 read contract to chunk-rendered --- .../02-git-working-tree-backend.md | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/plans/git-native-kb/02-git-working-tree-backend.md b/plans/git-native-kb/02-git-working-tree-backend.md index 36ef75ed8..5ea3ceade 100644 --- a/plans/git-native-kb/02-git-working-tree-backend.md +++ b/plans/git-native-kb/02-git-working-tree-backend.md @@ -5,35 +5,37 @@ ## 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. +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). -- **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. +- **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 `` 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`. - - 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. + - 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`/`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. +- 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. -## Open questions +## Resolved (see [`00c-shared-contract.md`](00c-shared-contract.md)) -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. +- **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).