Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save stjordanis/43d8c2dd044599efe096e472141e42f2 to your computer and use it in GitHub Desktop.

Select an option

Save stjordanis/43d8c2dd044599efe096e472141e42f2 to your computer and use it in GitHub Desktop.
FastContext × Claude Code — interleaved outer/inner transcript on the git codebase (local 4B-RL explorer via Ollama, hard functional queries)

FastContext × Claude Code — Interleaved Transcript (git codebase)

Each of the 4 hard git queries run through Claude Code, which was allowed only the mcp__fastcontext__explore tool (built-in search denied; grove removed from the test bench). This shows both layers of the same run: the outer Claude Code orchestration and the inner FastContext (local 4B via Ollama) exploration loop it delegates to.

How to read it

|CC   = Claude Code  (outer harness, Anthropic model orchestrating the tool)
|FC   = FastContext  (inner explorer: local FastContext-1.0-4B-RL Q4, Ollama)
  -> explore(...)        Claude Code calls the MCP tool
     |FC Turn n: LLM ..  one turn of the inner explorer loop (LLM latency + tokens)
     |FC   -> Grep/Read  a read-only tool call inside the explorer (its own latency)
  <- tool_result         what the explorer returned to Claude Code

All timings are measured wall-clock; inner turns come from the MCP server's per-call timing sidecars, outer flow from Claude Code's stream-json.

At a glance

Query FC calls End-to-end Outcome
Q1 recursive/ort merge + rename detection 4 154s FC returned thin/under-cited results across 4 calls (drifted to unrelated files); Claude relayed them with a caveat that they looked unreliable
Q2 interactive-rebase sequencer 1 44s Single FC call found sequencer.c/sequencer.h; Claude relayed citations
Q3 index read/write + cache-tree 3 75s First combined FC call empty → Claude split into 2 focused queries → got citations
Q4 packfile delta create/apply 2 128s First FC call empty → Claude re-queried → second call hit the delta machinery

Q1 — recursive/ort merge + rename detection

User → Claude Code: Use the fastcontext explore tool to find where the recursive/ort three-way merge is implemented and where rename detection during a merge is handled. Report the file:line citations it returns.

Ground truth: merge-ort.c; diffcore-rename.c End-to-end wall clock: 154s · FastContext calls Claude made: 4

|CC  ToolSearch -> load mcp__fastcontext__explore schema (deferred tool)
|CC  <- tool_result: (empty)
|CC  -> explore(query='where is the recursive/ort three-way merge implemented and where is rename detection during a merge handled')
     |FC  Turn 1: LLM 5311ms [p=6039 c=102]
     |FC     -> Grep(pattern=merge-ort|recursive_merge|three_way_merge path=/git mode=files_with_matches) 8ms [ok]
     |FC        obs: git/apply.c / git/merge-ort.c / git/merge-ort-wrappers.c / src/g ...
     |FC     -> Grep(pattern=rename|renamed|detect.*rename|rename.*detect path=/git mode=files_with_matches) 9ms [ok]
     |FC        obs: git/diffcore.h / git/setup.c / git/transport-helper.c / git/ ...
     |FC  Turn 2: LLM 1467ms [p=7378 c=47]
     |FC     -> Read(/git/merge-ort.c) 1ms [ok]
     |FC        obs: ```git/merge-ort.c:1-2000 / 1|/* / 2| * "Ostensibly Recursive's Twin" merge strategy, or "ort" for short. ...
     |FC     -> Read(/git/diffcore-rename.c) 1ms [ok]
     |FC        obs: ```git/diffcore-rename.c:1-1724 / 1|/* / 2| * / 3| * Copyright (C) 2005 Junio C Hamano / 4| */ / 5| / 6|# ...
     |FC  Turn 3: LLM 43752ms [p=27631 c=878]  -> emits <final_answer>
     |FC  => returned to Claude Code (inner wall 50.5s)
|CC  <- tool_result: <final_answer> with citations
|CC  note: The first query focused mostly on rename detection. Let me run a targeted query for the merge-ort/recursive implementation itself.
|CC  -> explore(query='recursive and ort three-way merge strategy main entry point and where merge invokes rename detection (diff_set ...')
     |FC  Turn 1: LLM 1429ms [p=6042 c=90]
     |FC     -> Grep(pattern=diff_setup|detect_rename path=/git mode=content) 10ms [ok]
     |FC        obs: git/diff-no-index.c / 414-	revs->diffopt.prefix = prefix; / 415- / 416-	revs->max_count = -2; / 417:	diff ...
     |FC     -> Grep(pattern=merge_strategy|three_way|recursive path=/git mode=files_with_matches) 8ms [ok]
     |FC        obs: git/notes-utils.c / git/sparse-index.c / git/thread-utils.c / ~/sr ...
     |FC  Turn 2: LLM 2444ms [p=8647 c=62]
     |FC     -> Read(/git/merge-ort.c) 1ms [ok]
     |FC        obs: ```git/merge-ort.c:1-2000 / 1|/* / 2| * "Ostensibly Recursive's Twin" merge strategy, or "ort" for short. ...
     |FC     -> Grep(pattern=detect_rename|diff_setup_done|diff_setup path=/git/diff.c mode=content) 2ms [ok]
     |FC        obs: 53-#define FAST_WORKING_DIRECTORY 1 / 54-#endif / 55- / 56:static int diff_detect_rename_default; / 57-static int diff_i ...
     |FC  Turn 3: LLM 3243ms [p=7113 c=157]
     |FC     -> Read(/git/diff-core.h) 0ms [ok]
     |FC        obs: <system-reminder>Error: git/diff-core.h does not exist</system-reminder>
     |FC     -> Read(/git/diff-core.h) 0ms [ok]
     |FC        obs: <system-reminder>Error: git/diff-core.h does not exist</system-reminder>
     |FC     -> Read(/git/diff-core.h) 0ms [ok]
     |FC        obs: <system-reminder>Error: git/diff-core.h does not exist</system-reminder>
     |FC     -> Read(/git/diff-core.h) 0ms [ok]
     |FC        obs: <system-reminder>Error: git/diff-core.h does not exist</system-reminder>
     |FC  Turn 4: LLM 742ms [p=7382 c=23]
     |FC     -> Glob(pattern=**/diff-core.h) 6ms [ok]
     |FC        obs: No files found
     |FC  Turn 5: LLM 625ms [p=7421 c=23]
     |FC     -> Glob(pattern=**/diff-core*) 8ms [ok]
     |FC        obs: No files found
     |FC  Turn 6: LLM 610ms [p=7460 c=22]
     |FC     -> Glob(pattern=**/diff*) 8ms [ok]
     |FC        obs: git/diffcore-pickaxe.o / git/diffcore.h / git/diff-merges.o / ~/sr ...
     |FC  Turn 7: LLM 5625ms [p=9265 c=256]  -> emits <final_answer>
     |FC  => returned to Claude Code (inner wall 14.8s)
|CC  <- tool_result: <final_answer> with citations
|CC  note: The tool's second answer looks noisy (line numbers beyond a header's length). Let me query specifically for the two merge implementation files.
|CC  -> explore(query='merge-ort.c and merge-recursive.c: the function that performs the three-way merge of trees and the detect_regu ...')
     |FC  Turn 1: LLM 801ms [p=6053 c=48]
     |FC     -> Read(/git/merge-ort.c) 1ms [ok]
     |FC        obs: ```git/merge-ort.c:1-2000 / 1|/* / 2| * "Ostensibly Recursive's Twin" merge strategy, or "ort" for short. ...
     |FC     -> Read(/git/merge-recursive.c) 0ms [ok]
     |FC        obs: <system-reminder>Error: git/merge-recursive.c does not exist</system-reminder>
     |FC  Turn 2: LLM 1258ms [p=6048 c=73]
     |FC     -> Read(git/merge-recursive.c) 0ms [ok]
     |FC        obs: <system-reminder>Error: git/merge-recursive.c does not exist</system-reminder>
     |FC     -> Grep(pattern=notes path=git mode=files_with_matches) 9ms [ok]
     |FC        obs: git/notes-utils.c / git/notes-merge.c / git/refs.c / git/not ...
     |FC  Turn 3: LLM 1222ms [p=6531 c=54]
     |FC     -> Read(git/notes-merge.c) 0ms [ok]
     |FC        obs: ```git/notes-merge.c:1-770 / 1|#define USE_THE_REPOSITORY_VARIABLE / 2|#define DISABLE_SIGN_COMPARE_WARNI ...
     |FC     -> Read(git/notes-merge.h) 0ms [ok]
     |FC        obs: ```git/notes-merge.h:1-87 / 1|#ifndef NOTES_MERGE_H / 2|#define NOTES_MERGE_H / 3| / 4|#include "notes-ut ...
     |FC  Turn 4: LLM 8476ms [p=17533 c=52]
     |FC     -> Read(git/notes-utils.h) 0ms [ok]
     |FC        obs: ```git/notes-utils.h:1-55 / 1|#ifndef NOTES_UTILS_H / 2|#define NOTES_UTILS_H / 3| / 4|#include "notes.h" ...
     |FC     -> Read(git/notes-utils.c) 0ms [ok]
     |FC        obs: ```git/notes-utils.c:1-200 / 1|#define USE_THE_REPOSITORY_VARIABLE / 2| / 3|#include "git-compat-util.h"  ...
     |FC  Turn 5: LLM 16989ms [p=20407 c=574]  -> emits <final_answer>
     |FC  => returned to Claude Code (inner wall 28.8s)
|CC  <- tool_result: <final_answer> with citations
|CC  note: The explore tool drifted to `notes-merge.c` (unrelated). Let me try once more, naming the exact functions.
|CC  -> explore(query='merge_ort_internal merge_start collect_merge_info process_renames detect_and_process_renames in merge-ort.c; m ...')
     |FC  Turn 1: LLM 785ms [p=6055 c=48]
     |FC     -> Read(/git/merge-ort.c) 1ms [ok]
     |FC        obs: ```git/merge-ort.c:1-2000 / 1|/* / 2| * "Ostensibly Recursive's Twin" merge strategy, or "ort" for short. ...
     |FC     -> Read(/git/merge-recursive.c) 0ms [ok]
     |FC        obs: <system-reminder>Error: git/merge-recursive.c does not exist</system-reminder>
     |FC  Turn 2: LLM 1245ms [p=6048 c=73]
     |FC     -> Read(git/merge-recursive.c) 0ms [ok]
     |FC        obs: <system-reminder>Error: git/merge-recursive.c does not exist</system-reminder>
     |FC     -> Grep(pattern=notes path=git mode=files_with_matches) 9ms [ok]
     |FC        obs: git/notes-utils.c / git/notes-merge.c / git/refs.c / git/not ...
     |FC  Turn 3: LLM 1199ms [p=6531 c=54]
     |FC     -> Read(git/notes-merge.c) 1ms [ok]
     |FC        obs: ```git/notes-merge.c:1-770 / 1|#define USE_THE_REPOSITORY_VARIABLE / 2|#define DISABLE_SIGN_COMPARE_WARNI ...
     |FC     -> Read(git/notes-merge.h) 0ms [ok]
     |FC        obs: ```git/notes-merge.h:1-87 / 1|#ifndef NOTES_MERGE_H / 2|#define NOTES_MERGE_H / 3| / 4|#include "notes-ut ...
     |FC  Turn 4: LLM 14662ms [p=17533 c=320]  -> emits <final_answer>
     |FC  => returned to Claude Code (inner wall 17.9s)
|CC  <- tool_result: <final_answer> with citations
|CC  note: I used the `fastcontext` explore tool as requested (four queries). Here are the file:line citations it actually returned — with a caveat: **the tool p ...
|CC  => FINAL ANSWER to user (below)

Claude Code's final answer:

I used the `fastcontext` explore tool as requested (four queries). Here are the file:line citations it actually returned — with a caveat: **the tool performed poorly on this repo and did not cleanly surface the recursive/ort merge implementation.**

## Rename detection during merge
The one solid, relevant citation it returned:

- **`diffcore-rename.c:1-1724`** — core diffcore rename-detection implementation. The tool's own breakdown flagged the useful anchors:
  - `estimate_similarity()` — `diffcore-rename.c:132-214`
  - `find_exact_renames()` — `diffcore-rename.c:326-369`
  - `find_basename_matches()` — `diffcore-rename.c:903-1062`
  - `find_renames()` (inexact/similarity matrix) — `diffcore-rename.c:1130-1157`
  - `diffcore_rename_extended()` (main entry) — `diffcore-rename.c:1380-1718`
  - `diffcore_rename()` (wrapper) — `diffcore-rename.c:1721-1724`

A second query for the merge→rename hook returned citations into **`diffcore.h`** (`DIFF_DETECT_RENAME`, `diff_opt_set_detect_rename`, etc.), but the line numbers it gave (e.g. `5132`, `5747`) are **out of range for that header and are not trustworthy** — treat these as noise.

## Recursive/ort three-way merge
The tool **failed to find this.** Two separate queries that explicitly named `merge-ort.c` / `merge-recursive.c` and their functions (`merge_ort_internal`, `collect_merge_info`, `detect_and_process_renames`, `merge_recursive_internal`, `get_renames`) both drifted to the unrelated **`notes-merge.c:1-770`** and returned only that. So it produced **no valid citation** for the actual recursive/ort merge engine.

---

**Bottom line:** the only reliable citation the explore tool returned is `diffcore-rename.c` (the merge rename-detection machinery). It did not locate `merge-ort.c` or `merge-recursive.c`, and one of its diffcore.h line ranges is clearly bogus. If you want, I can locate the recursive/ort merge and its rename-detection call sites directly with grep — those live in `merge-ort.c` (`detect_and_process_renames`) and `merge-recursive.c` (`get_renames`) — rather than relying on this tool.

Q2 — interactive-rebase sequencer

User → Claude Code: Use the fastcontext explore tool to find where git parses and executes the interactive-rebase todo list (the sequencer): the todo parser and the commit-picking logic. Report the citations it returns.

Ground truth: sequencer.c (parse_insn_line / do_pick_commit); rebase-interactive.c End-to-end wall clock: 44s · FastContext calls Claude made: 1

|CC  ToolSearch -> load mcp__fastcontext__explore schema (deferred tool)
|CC  <- tool_result: (empty)
|CC  -> explore(query='interactive rebase sequencer: todo-list parser and the commit-picking (pick command) logic')
     |FC  Turn 1: LLM 1426ms [p=6039 c=80]
     |FC     -> Grep(pattern=todo-list|todo_list path=/git mode=content) 13ms [ok]
     |FC        obs: git/rebase-interactive.h / 4-struct strbuf; / 5-struct repository; / 6-struct replay_opts; / 7:struct tod ...
     |FC     -> Grep(pattern=pick|interactive.rebase|rebase.sequencer path=/git mode=content) 14ms [ok]
     |FC        obs: git/setup.c / 789- / 790-	if (candidate->worktree_config) { / 791-		/* / 792:		 * pick up core.bare and c ...
     |FC  Turn 2: LLM 2879ms [p=8600 c=88]
     |FC     -> Grep(pattern=pick|todo_list_parse_insn|todo_item|rebase.sequencer path=/git/sequencer.h mode=content) 3ms [ok]
     |FC        obs: 119-	TODO_COMMENT / 120-}; / 121- / 122:struct todo_item { / 123-	enum todo_command command; / 124-	struct commit *commi ...
     |FC     -> Grep(pattern=pick|todo_list|rebase.sequencer path=/git/rebase-interactive.h mode=content) 2ms [ok]
     |FC        obs: 4-struct strbuf; / 5-struct repository; / 6-struct replay_opts; / 7:struct todo_list; / 8- / 9-void append_todo_help(int ...
     |FC  Turn 3: LLM 1979ms [p=9291 c=88]
     |FC     -> Grep(pattern=pick|todo_list_parse_insn|todo_item|rebase.sequencer path=/git/sequencer.c mode=content) 3ms [ok]
     |FC        obs: 61-#define GIT_MAX_LABEL_LENGTH ((NAME_MAX) - (LOCK_SUFFIX_LEN) - 16) / 62- / 63-static const char sign_off_header[] = " ...
     |FC     -> Grep(pattern=pick|todo_list|rebase.sequencer path=/git/rebase-interactive.c mode=content) 3ms [ok]
     |FC        obs: 14-#include "dir.h" / 15-#include "object-name.h" / 16- / 17:static const char edit_todo_list_advice[] = / 18-N_("You ca ...
     |FC  Turn 4: LLM 3374ms [p=11797 c=93]
     |FC     -> Grep(pattern=todo_list_parse_insn|todo_item|pick|rebase.sequencer path=/git/sequencer.c mode=content) 3ms [ok]
     |FC        obs: 61-#define GIT_MAX_LABEL_LENGTH ((NAME_MAX) - (LOCK_SUFFIX_LEN) - 16) / 62- / 63-static const char sign_off_header[] = " ...
     |FC     -> Grep(pattern=todo_list_parse_insn|todo_item|pick|rebase.sequencer path=/git/rebase-interactive.c mode=content) 3ms [ok]
     |FC        obs: 47-		      struct strbuf *buf) / 48-{ / 49-	const char *msg = _("\nCommands:\n" / 50:"p, pick <commit> = use commit\n" / ...
     |FC  Turn 5: LLM 3247ms [p=13704 c=93]
     |FC     -> Grep(pattern=todo_list_parse_insn|todo_item|pick|rebase.sequencer path=/git/sequencer.c mode=content) 3ms [ok]
     |FC        obs: 61-#define GIT_MAX_LABEL_LENGTH ((NAME_MAX) - (LOCK_SUFFIX_LEN) - 16) / 62- / 63-static const char sign_off_header[] = " ...
     |FC     -> Grep(pattern=todo_list_parse_insn|todo_item|pick|rebase.sequencer path=/git/rebase-interactive.c mode=content) 2ms [ok]
     |FC        obs: 47-		      struct strbuf *buf) / 48-{ / 49-	const char *msg = _("\nCommands:\n" / 50:"p, pick <commit> = use commit\n" / ...
     |FC  Turn 6: LLM 3506ms [p=15611 c=93]
     |FC     -> Grep(pattern=todo_list_parse_insn|todo_item|pick|rebase.sequencer path=/git/sequencer.c mode=content) 3ms [ok]
     |FC        obs: 61-#define GIT_MAX_LABEL_LENGTH ((NAME_MAX) - (LOCK_SUFFIX_LEN) - 16) / 62- / 63-static const char sign_off_header[] = " ...
     |FC     -> Grep(pattern=todo_list_parse_insn|todo_item|pick|rebase.sequencer path=/git/rebase-interactive.c mode=content) 3ms [ok]
     |FC        obs: 47-		      struct strbuf *buf) / 48-{ / 49-	const char *msg = _("\nCommands:\n" / 50:"p, pick <commit> = use commit\n" / ...
     |FC  Turn 7: LLM 9646ms [p=17542 c=348]  -> emits <final_answer>
     |FC  => returned to Claude Code (inner wall 26.1s)
|CC  <- tool_result: <final_answer> with citations
|CC  note: The fastcontext explore tool returned these citations for git's interactive-rebase sequencer: /  / ## Todo-list parser /  / - **`sequencer.h:131-150`* ...
|CC  => FINAL ANSWER to user (below)

Claude Code's final answer:

The fastcontext explore tool returned these citations for git's interactive-rebase sequencer:

## Todo-list parser

- **`sequencer.h:131-150`** — Core data structures and parser API: `struct todo_list`, `struct todo_item`, and the function declarations `todo_list_parse_insn_buffer`, `todo_list_write_to_file`, `todo_list_release`, `todo_item_get_arg`, `todo_list_filter_update_refs`.
- **`sequencer.c:1821-1865`** — The `todo_command_info[]` table that maps each todo command to its short/long name (e.g. `TODO_PICK` → `'p'` / `"pick"`). This is the lookup table the parser uses to recognize command keywords.
- **`rebase-interactive.c:106-166`** — `edit_todo_list`: reads the todo file, calls `todo_list_parse_insn_buffer` to parse it, validates the result, and writes it back.
- **`rebase-interactive.c:173-234`** — `todo_list_check`: validates the parsed list (unrecognized commands, bad SHAs).
- **`rebase-interactive.c:236-246`** — `todo_list_check_against_backup`: compares the edited list against the backup.
- **`rebase-interactive.c:47-104`** — `edit_todo_list_advice`: the help text describing valid todo commands.

## Commit-picking (pick) logic

- **`sequencer.c:1108-1118`** — The pick execution path: sets up the cherry-pick of the picked commit (including the fixup/merge-into-previous handling).
- **`sequencer.c:463-468`** — `replay_action_names`: `REPLAY_PICK` → `"cherry-pick"`, linking a pick instruction to the underlying cherry-pick machinery.

**Note:** The tool's citations use a `/git/...` prefix; the actual paths in this repo are at the root (`sequencer.c`, `sequencer.h`, `rebase-interactive.c`). Also worth knowing — the primary parser entry point named in the API, `todo_list_parse_insn_buffer`, is declared in `sequencer.h` but its implementation lives in `sequencer.c` (the explore run surfaced the declaration and the command table rather than the parse-buffer function body itself), if you want to dig into the actual per-line parsing loop next.

Q3 — index read/write + cache-tree

User → Claude Code: Use the fastcontext explore tool to find where the on-disk index (staging area) is read and written, and where the cache-tree is serialized. Report the citations it returns.

Ground truth: read-cache.c (do_read_index / write_index); cache-tree.c End-to-end wall clock: 75s · FastContext calls Claude made: 3

|CC  ToolSearch -> load mcp__fastcontext__explore schema (deferred tool)
|CC  <- tool_result: (empty)
|CC  -> explore(query='where the on-disk index (staging area) is read and written, and where the cache-tree is serialized')
     |FC  Turn 1: LLM 1342ms [p=6043 c=69]  -> EMPTY (parser drop) — inner loop ends
     |FC  => returned to Claude Code (inner wall 1.3s)
|CC  <- tool_result: {"result":""}
|CC  note: The first call returned empty. Let me retry, splitting into more focused queries.
|CC  -> explore(query='where the on-disk index / staging area file is read from disk and written back to disk (read_index, write_inde ...')
     |FC  Turn 1: LLM 675ms [p=6046 c=37]
     |FC     -> Grep(pattern=read_index|write_index path=/git mode=content) 13ms [ok]
     |FC        obs: git/apply.c / 4184-static int read_apply_cache(struct apply_state *state) / 4185-{ / 4186-	if (state->ind ...
     |FC  Turn 2: LLM 1655ms [p=6960 c=71]
     |FC     -> Grep(pattern=read_index_from|write_index|write_index_to path=/git mode=content) 13ms [ok]
     |FC        obs: git/read-cache-ll.h / 277-struct lock_file; / 278-int do_read_index(struct index_state *istate, const cha ...
     |FC     -> Grep(pattern=read_index_from|write_index_to path=/git mode=content) 12ms [ok]
     |FC        obs: git/read-cache-ll.h / 277-struct lock_file; / 278-int do_read_index(struct index_state *istate, const cha ...
     |FC  Turn 3: LLM 2673ms [p=9228 c=83]
     |FC     -> Grep(pattern=read_index_from|write_index|write_index_to path=/git/read-cache-ll.c mode=content) 12ms [ok]
     |FC        obs: git/read-cache-ll.h / 277-struct lock_file; / 278-int do_read_index(struct index_state *istate, const cha ...
     |FC     -> Grep(pattern=read_index_from|write_index|write_index_to path=/git/repository.c mode=content) 2ms [ok]
     |FC        obs: 462-		BUG("repo's index should point back at itself"); / 463-	} / 464- / 465:	res = read_index_from(repo->index, repo->i ...
     |FC  Turn 4: LLM 2244ms [p=10450 c=81]
     |FC     -> Grep(pattern=read_index_from|write_index|write_index_to path=/git/read-cache-ll.c mode=content) 12ms [ok]
     |FC        obs: git/read-cache-ll.h / 277-struct lock_file; / 278-int do_read_index(struct index_state *istate, const cha ...
     |FC     -> Grep(pattern=read_index_from|write_index|write_index_to path=/git/repository.c mode=content) 2ms [ok]
     |FC        obs: 462-		BUG("repo's index should point back at itself"); / 463-	} / 464- / 465:	res = read_index_from(repo->index, repo->i ...
     |FC  Turn 5: LLM 2317ms [p=11661 c=81]
     |FC     -> Grep(pattern=read_index_from|write_index|write_index_to path=/git/read-cache-ll.c mode=content) 11ms [ok]
     |FC        obs: git/read-cache-ll.h / 277-struct lock_file; / 278-int do_read_index(struct index_state *istate, const cha ...
     |FC     -> Grep(pattern=read_index_from|write_index|write_index_to path=/git/repository.c mode=content) 2ms [ok]
     |FC        obs: 462-		BUG("repo's index should point back at itself"); / 463-	} / 464- / 465:	res = read_index_from(repo->index, repo->i ...
     |FC  Turn 6: LLM 2463ms [p=12855 c=81]
     |FC     -> Grep(pattern=read_index_from|write_index|write_index_to path=/git/read-cache-ll.c mode=content) 13ms [ok]
     |FC        obs: git/read-cache-ll.h / 277-struct lock_file; / 278-int do_read_index(struct index_state *istate, const cha ...
     |FC     -> Grep(pattern=read_index_from|write_index|write_index_to path=/git/repository.c mode=content) 2ms [ok]
     |FC        obs: 462-		BUG("repo's index should point back at itself"); / 463-	} / 464- / 465:	res = read_index_from(repo->index, repo->i ...
     |FC  Turn 7: LLM 11656ms [p=14066 c=517]  -> emits <final_answer>
     |FC  => returned to Claude Code (inner wall 23.8s)
|CC  -> explore(query='where the cache-tree is serialized / written into the index extension')
     |FC  Turn 1: LLM 1138ms [p=6032 c=70]
     |FC     -> Grep(pattern=cache-tree path=/git mode=files_with_matches) 12ms [ok]
     |FC        obs: git/read-cache-ll.h / git/revision.c / git/sparse-index.c / src/ ...
     |FC     -> Grep(pattern=cache-tree path=/git mode=content) 12ms [ok]
     |FC        obs: git/read-cache-ll.h / 380-#define ADD_CACHE_SKIP_DFCHECK 4	/* Ok to skip DF conflict checks */ / 381-#def ...
     |FC  Turn 2: LLM 2929ms [p=8177 c=106]
     |FC     -> Grep(pattern=cache_tree_update|cache_tree_fully_valid|cache_tree_free path=/git mode=content) 12ms [ok]
     |FC        obs: git/cache-tree.h / 20-	int subtree_alloc; / 21-	struct cache_tree_sub **down; / 22-}; / 23- / 24-struct c ...
     |FC     -> Grep(pattern=write|serialize|write_tree|write_index|write_cache path=/git/cache-tree.c mode=content) 2ms [ok]
     |FC        obs: 350-	} / 351- / 352-	discard_unused_subtrees(it); / 353- / 354-	/* / 355:	 * Then write out the tree object for this lev ...
     |FC  Turn 3: LLM 3033ms [p=10368 c=95]
     |FC     -> Grep(pattern=write_index_as_tree|write_index_as_tree_internal|write_index_as_tree_ext path=/git/cache-tree.c mode=content) 2ms [ok]
     |FC        obs: 695-			path++; / 696-	} / 697-	return it; / 698-} / 699- / 700:static int write_index_as_tree_internal(struct object_id  ...
     |FC     -> Grep(pattern=cache_tree_update|cache_tree_fully_valid path=/git/cache-tree.c mode=content) 2ms [ok]
     |FC        obs: 231-			it->subtree_nr--; / 232-		} / 233-	} / 234-} / 235- / 236:int cache_tree_fully_valid(struct cache_tree *it) / 237 ...
     |FC  Turn 4: LLM 2889ms [p=11846 c=100]
     |FC     -> Grep(pattern=write_index_as_tree_internal|write_index_as_tree_ext|write_index_as_tree_ext_internal path=/git/cache-tree.c mode=content) 3ms [ok]
     |FC        obs: 695-			path++; / 696-	} / 697-	return it; / 698-} / 699- / 700:static int write_index_as_tree_internal(struct object_id  ...
     |FC     -> Grep(pattern=write_index_as_tree_ext|write_index_as_tree_ext_internal path=/git/cache-tree.c mode=content) 2ms [ok]
     |FC        obs: No matches found
     |FC  Turn 5: LLM 2401ms [p=12368 c=94]
     |FC     -> Grep(pattern=write_index_as_tree_ext|write_index_as_tree_ext_internal path=/git/cache-tree.c mode=content) 2ms [ok]
     |FC        obs: No matches found
     |FC     -> Grep(pattern=write_index_as_tree_ext_internal|write_index_as_tree_ext path=/git/cache-tree.c mode=content) 2ms [ok]
     |FC        obs: No matches found
     |FC  Turn 6: LLM 1824ms [p=12490 c=81]
     |FC     -> Grep(pattern=write_index_as_tree_ext path=/git/cache-tree.c mode=content) 2ms [ok]
     |FC        obs: No matches found
     |FC     -> Grep(pattern=write_index_as_tree_ext_internal path=/git/cache-tree.c mode=content) 2ms [ok]
     |FC        obs: No matches found
     |FC  Turn 7: LLM 7868ms [p=12623 c=376]  -> emits <final_answer>
     |FC  => returned to Claude Code (inner wall 22.1s)
|CC  <- tool_result: <final_answer> with citations
|CC  <- tool_result: <final_answer> with citations
|CC  note: The fastcontext explore tool returned empty on the first (combined) query, so I split it into two focused queries. Here are the citations it reported. ...
|CC  => FINAL ANSWER to user (below)

Claude Code's final answer:

The fastcontext explore tool returned empty on the first (combined) query, so I split it into two focused queries. Here are the citations it reported. Paths are given relative to the repo root (`git/`); the tool prefixed them with `/git/`.

## On-disk index (staging area): read & write

| Citation | What it is |
|---|---|
| `read-cache-ll.h:278-281` | `read_index_from` declaration |
| `read-cache-ll.c:1-100` | `read_index_from` implementation (reads index from disk into memory) |
| `repository.c:453-471` | `repo_read_index` / `repo_refresh_and_write_index` declarations & usage |
| `repository.c:462-468` | Core `read_index_from` call during repo init |
| `apply.c:4184-4190` | `read_apply_cache` reads index via `read_index_from` |
| `builtin/commit.c:419-423` | `read_index_from` + `cache_tree_update` |
| `builtin/commit.c:552-555` | `read_index_from` after `discard_index` |
| `builtin/commit.c:1106-1110` | `read_index_from` after `discard_index` |
| `builtin/history.c:823-829` | `read_index_from` usage |

## Cache-tree serialization

| Citation | What it is |
|---|---|
| `cache-tree.c:545-550` | `cache_tree_write` — serializes cache-tree into a `strbuf` (the index extension write path) |
| `cache-tree.c:475-502` | `cache_tree_update` — recomputes cache-tree from index entries (the "write" side) |
| `cache-tree.c:236-249` | `cache_tree_fully_valid` — validates cache-tree before use |
| `cache-tree.c:700-774` | `write_index_as_tree_internal` — decides cache-tree vs. full index; calls `write_locked_index` |
| `cache-tree.c:752-774` | `write_index_as_tree` — public entry point |
| `cache-tree.h:35-56` | `write_index_as_tree` declaration & flags |
| `write-tree.c:51-56` / `builtin/write-tree.c:51-56` | `write_index_as_tree` usage |

### A caveat worth flagging
The tool pointed `read_index_from`'s implementation at `read-cache-ll.c:1-100`, but in git's actual layout `read-cache-ll.c` is typically a thin header-companion — the real read/write machinery (`do_read_index`, `do_write_index`, `write_locked_index`) lives in `read-cache.c`. It also didn't surface the primary index *writer* (`write_locked_index` / `do_write_index`), only referencing it indirectly through `write_index_as_tree_internal`. If you want the true on-disk write path (including where the cache-tree extension bytes actually get flushed to the index file), I'd recommend a follow-up look at `read-cache.c` — say the word and I'll pull those lines directly.

Q4 — packfile delta create/apply

User → Claude Code: Use the fastcontext explore tool to find where packfile delta compression is implemented: creating a delta and applying/patching a delta. Report the citations it returns.

Ground truth: diff-delta.c (create_delta); patch-delta.c (patch_delta) End-to-end wall clock: 128s · FastContext calls Claude made: 2

|CC  ToolSearch -> load mcp__fastcontext__explore schema (deferred tool)
|CC  <- tool_result: (empty)
|CC  -> explore(query='packfile delta compression: creating/generating a delta between two objects, and applying/patching a delta to  ...')
     |FC  Turn 1: LLM 1524ms [p=6045 c=82]
     |FC     -> Grep(pattern=delta path=/git mode=files_with_matches) 8ms [ok]
     |FC        obs: git/wt-status.c / git/packfile.c / git/repo-settings.c / git ...
     |FC     -> Grep(pattern=delta path=/git mode=files_with_matches) 8ms [ok]
     |FC        obs: git/odb.h / git/repack.h / git/delta-islands.h / git/packfil ...
     |FC  Turn 2: LLM 1893ms [p=6818 c=91]
     |FC     -> Read(/git/delta.h) 1ms [ok]
     |FC        obs: ```git/delta.h:1-114 / 1|#ifndef DELTA_H / 2|#define DELTA_H / 3| / 4|/* opaque object for delta index */ ...
     |FC     -> Read(/git/delta-islands.h) 0ms [ok]
     |FC        obs: ```git/delta-islands.h:1-19 / 1|#ifndef DELTA_ISLANDS_H / 2|#define DELTA_ISLANDS_H / 3| / 4|struct commi ...
     |FC     -> Read(/git/packfile.c) 1ms [ok]
     |FC        obs: ```git/packfile.c:1-2000 / 1|#define DISABLE_SIGN_COMPARE_WARNINGS / 2| / 3|#include "git-compat-util.h"  ...
     |FC     -> Read(/git/apply.c) 1ms [ok]
     |FC        obs: ```git/apply.c:1-2000 / 1|/* / 2| * apply.c / 3| * / 4| * Copyright (C) Linus Torvalds, 2005 / 5| * / 6|  ...
     |FC  Turn 3: LLM 68173ms [p=29528 c=1467]  -> emits <final_answer>
     |FC  => returned to Claude Code (inner wall 71.6s)
|CC  <- tool_result: <final_answer> with citations
|CC  note: The first exploration missed — it surfaced `apply.c`, which is textual patch application (`git apply`), not packfile **binary delta** compression. Let ...
|CC  -> explore(query='binary delta encoding for packfiles: create_delta function that produces a compact delta buffer between source ...')
     |FC  Turn 1: LLM 1534ms [p=6064 c=94]
     |FC     -> Grep(pattern=create_delta|patch_delta path=/git mode=content) 9ms [ok]
     |FC        obs: git/apply.c / 3252-	} / 3253-	switch (fragment->binary_patch_method) { / 3254-	case BINARY_DELTA_DEFLATED ...
     |FC     -> Grep(pattern=delta.*encode|delta.*decode|DeltaOp|DeltaBuffer path=/git mode=content) 9ms [ok]
     |FC        obs: git/diff-delta.c / 151-	entries = (bufsize - 1) / RABIN_WINDOW; / 152-	if (bufsize >= 0xffffffffUL) { / 1 ...
     |FC  Turn 2: LLM 2068ms [p=7335 c=80]
     |FC     -> Read(/git/diff-delta.c) 0ms [ok]
     |FC        obs: ```git/diff-delta.c:319-438 / 319|void * / 320|create_delta(const struct delta_index *index, / 321|	      ...
     |FC     -> Read(/git/diff-delta.c) 0ms [ok]
     |FC        obs: ```git/diff-delta.c:100-199 / 100|	0x7b1c4c87, 0x05a96c8a, 0x2d2fb84c, 0x539a9841, 0x7c2211c0, 0x029731cd ...
     |FC  Turn 3: LLM 3385ms [p=10861 c=70]
     |FC     -> Read(/git/diff-delta.c) 0ms [ok]
     |FC        obs: ```git/diff-delta.c:438-510 / 438|			op = out + outpos++; / 439|			i = 0x80; / 440| / 441|			if (moff & 0 ...
     |FC     -> Read(/git/diff-delta.c) 0ms [ok]
     |FC        obs: ```git/diff-delta.c:199-298 / 199|			entry->entry.val = val; / 200|			entry->next = hash[i]; / 201|			has ...
     |FC  Turn 4: LLM 3214ms [p=12956 c=86]
     |FC     -> Grep(pattern=RABIN_WINDOW|MAX_OP_SIZE|T|RABIN_SHIFT path=/git/diff-delta.h mode=content) 145ms [ok]
     |FC        obs: git/version.c / 3-#include "strbuf.h" / 4-#include "gettext.h" / 5- / 6:#ifndef GIT_VERSION_H / 7-# inclu ...
     |FC     -> Grep(pattern=patch_delta|DeltaOp|DeltaBuffer path=/git/diff-delta.h mode=content) 11ms [ok]
     |FC        obs: git/packfile.c / 1965-			data = NULL; / 1966-		} else { / 1967-			unsigned long sz; / 1968:			data = patc ...
     |FC  Turn 5: LLM 2931ms [p=14823 c=64]
     |FC     -> Read(/git/delta.h) 0ms [ok]
     |FC        obs: ```git/delta.h:1-114 / 1|#ifndef DELTA_H / 2|#define DELTA_H / 3| / 4|/* opaque object for delta index */ ...
     |FC     -> Read(/git/patch-delta.c) 0ms [ok]
     |FC        obs: ```git/patch-delta.c:1-94 / 1|/* / 2| * patch-delta.c: / 3| * recreate a buffer from a source and the del ...
     |FC  Turn 6: LLM 4115ms [p=17172 c=92]
     |FC     -> Grep(pattern=RABIN_WINDOW|RABIN_SHIFT|T|MAX_OP_SIZE path=/git/diff-delta.c mode=content) 3ms [ok]
     |FC        obs: 1-/* / 2- * diff-delta.c: generate a delta between two buffers / 3- * / 4: * This code was greatly inspired by parts of  ...
     |FC     -> Grep(pattern=RABIN_WINDOW|RABIN_SHIFT|T|MAX_OP_SIZE path=/git/diff-delta.c mode=content) 2ms [ok]
     |FC        obs: 1-/* / 2- * diff-delta.c: generate a delta between two buffers / 3- * / 4: * This code was greatly inspired by parts of  ...
     |FC  Turn 7: LLM 10593ms [p=20090 c=313]  -> emits <final_answer>
     |FC  => returned to Claude Code (inner wall 28.0s)
|CC  <- tool_result: <final_answer> with citations
|CC  note: The second exploration hit the target. Here's what the tool found. /  / ## Packfile delta compression /  / The two halves of git's binary delta machin ...
|CC  => FINAL ANSWER to user (below)

Claude Code's final answer:

The second exploration hit the target. Here's what the tool found.

## Packfile delta compression

The two halves of git's binary delta machinery live in dedicated files (paths are repo-relative under `git/`):

**Creating a delta — `diff-delta.c`**
- `diff-delta.c:319-509` — `create_delta()`: produces the compact delta buffer between a source and target blob
- `diff-delta.c:135-298` — `create_delta_index()`: builds the hash index over the source buffer that `create_delta()` uses to find matching runs
- `diff-delta.c:17-24` — `delta_index` struct plus `free_delta_index` / `sizeof_delta_index` declarations
- `diff-delta.c:1-24` — Rabin fingerprint constants (`RABIN_WINDOW`, `RABIN_SHIFT`, the `T` table, `HASH_LIMIT`)

**Applying/patching a delta — `patch-delta.c`**
- `patch-delta.c:15-94` — `patch_delta()`: reconstructs the target buffer from a base buffer plus the delta's copy/insert opcodes

**Public API**
- `delta.h:1-114` — declarations for `create_delta`, `create_delta_index`, `free_delta_index`, `sizeof_delta_index`, `diff_delta`, and `patch_delta`

## Note on the tool run

The first `explore` call misfired — my initial query mentioned "delta/patch" in general terms and it returned `apply.c` (the `git apply` textual-patch parser: fragments, hunk headers, `@@` parsing), which is a *different* subsystem from packfile binary deltas. Re-running with a query that explicitly described `create_delta`/`patch_delta` and the copy/insert opcode model landed on the correct files above. Worth knowing if you use this tool: it's sensitive to whether the query names the binary-delta semantics vs. generic "patch" wording.

What the interleaving reveals

  • Claude Code is an error-correcting orchestrator around a weak explorer. The raw CLI A/B showed a single FC call either working or returning empty. Here, when FC returns empty, Claude Code re-queries and splits the question (Q3: 1 combined → 2 focused; Q4: retry until hit). So end-to-end success is higher than FC-alone — the harness compensates.

  • The cost of that compensation is latency and round-trips. Each retry is a full inner explorer loop (multiple Ollama turns). Q1 took 4 FC calls / ~154s; Q4 ~128s. On a small repo a single call suffices; git-scale hardness turns one logical question into several delegated calls.

  • The inner failure mode is unchanged. Empty inner results are still Ollama's tool-call parser dropping the turn-1 output; Claude Code can't see why, only that it got nothing, so it retries — sometimes productively (Q4), sometimes just relaying thin citations with a caveat (Q1).

  • The outer model adds judgment. In Q1 Claude Code explicitly flagged the returned citations as looking unreliable — a layer of scrutiny the explorer alone does not provide.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment