fabro/lib/crates
Bryan Helmkamp 7f9b31074c
perf(server): cache bare GitHub clones for automation materialization
Materializing an automation run cloned the full repo fresh into a
tempdir on every click — 5–15s of git activity on the HTTP request
thread, paid in full for every run, then thrown away.

Add a per-`(owner, repo)` bare-clone cache under
`<Storage::cache_dir>/automation-repos/<owner>/<repo>.git`, and replace
the per-call clone+fetch+checkout dance with:

1. `KeyedMutex` lock on `(owner, repo)` so concurrent calls serialize
   per repo and parallelize across repos.
2. If the bare clone is missing, `git clone --bare --depth 1`. Otherwise
   `git worktree prune` to clean up any admin entries leaked by previous
   `TempDir` drops.
3. `git fetch --depth 1 origin <ref>` against the bare clone.
4. `git rev-parse FETCH_HEAD` for the SHA.
5. `git worktree add --detach --force <temp>/repo FETCH_HEAD` into the
   per-call scratch dir, then build the manifest as today.

First run for a repo still pays the clone cost. Every subsequent run
for any ref or automation against that repo pays only the fetch delta
plus a near-free worktree add (~100–500ms).

Corruption recovery: if the bare clone's `HEAD` file is missing or
zero-length after a failure, the cache wipes the directory and retries
once before surfacing `CloneFailed` as before. Auth and network errors
do not trigger a wipe.

Promote `fabro_store::KeyedMutex` and its guard to `pub` so the
server can reuse the existing primitive instead of duplicating it.

Tests:
- `bare_clone_reused_across_calls` seeds a local upstream, runs
  `prepare_worktree` twice, and asserts the bare clone's `objects/`
  tree is identical before and after the second call (i.e., no
  re-clone).
- `bare_clone_recovers_from_corruption` truncates `HEAD` between
  calls and asserts the cache rebuilds and succeeds.
- The existing plan-builder argv/timeout assertions are updated to
  cover the new bare-clone, bare-fetch, worktree-add, worktree-prune,
  and rev-parse FETCH_HEAD plans.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 08:29:58 -04:00
..
build-support fix(build): refresh embedded git sha on branch commits 2026-05-09 14:10:04 -04:00
fabro-acp fix(workflow): capture configured artifacts once (#337) 2026-05-21 10:52:22 -04:00
fabro-agent fix(llm): preserve raw compatible tool arguments (#448) 2026-05-28 11:52:36 -04:00
fabro-api refactor: Remove inbound IP allowlisting (#443) 2026-05-27 22:29:08 -04:00
fabro-auth Replace vague expect/panic messages with invariant-explaining messages (#422) 2026-05-27 10:38:20 -04:00
fabro-automation Add GET/POST /automations/{id}/runs endpoints (#442) 2026-05-27 22:29:29 -04:00
fabro-checkpoint Make git metadata sandbox-native 2026-04-27 21:43:15 -07:00
fabro-cli refactor: Remove inbound IP allowlisting (#443) 2026-05-27 22:29:08 -04:00
fabro-client Add fabro variable CLI namespace for server-managed variables (#434) 2026-05-27 13:57:25 -04:00
fabro-config refactor: Remove inbound IP allowlisting (#443) 2026-05-27 22:29:08 -04:00
fabro-core Replace bare unwrap() with documented expect() across production runtim… (#415) 2026-05-26 17:46:39 -04:00
fabro-dev feat: add [run.agent] fabro_tools opt-in for worker run tools (#348) 2026-05-22 09:41:27 -04:00
fabro-dump Model run sandbox lifecycle explicitly (#431) 2026-05-27 12:48:56 -04:00
fabro-github fix(github): refresh installation tokens during workflows 2026-05-06 07:15:18 -04:00
fabro-graphviz Replace vague expect/panic messages with invariant-explaining messages (#422) 2026-05-27 10:38:20 -04:00
fabro-hooks Add event-sourced todo tools for OpenAI and Anthropic profiles (#353) 2026-05-22 13:44:42 -04:00
fabro-http refactor(static): centralize env var names 2026-04-24 12:29:51 -04:00
fabro-install Add provider-backed sandbox inventory API and rename SandboxProvider to… (#409) 2026-05-25 22:41:57 -04:00
fabro-interview Replace stdin JSONL control pipe with WebSocket worker control bus (#440) 2026-05-27 20:24:25 -04:00
fabro-llm fix(llm): preserve raw compatible tool arguments (#448) 2026-05-28 11:52:36 -04:00
fabro-macros refactor(dev): simplify generated docs tooling 2026-04-24 18:41:00 -04:00
fabro-manifest feat(sandbox): secure daytona snapshot names (#429) 2026-05-27 11:52:35 -04:00
fabro-mcp Add legacy SSE MCP transport support (#386) 2026-05-24 15:29:01 -04:00
fabro-mcp-server feat: Add approve/deny run controls to MCP and CLI (#400) 2026-05-25 15:49:57 -04:00
fabro-model chore(model): update provider default models (#437) 2026-05-27 18:45:51 -04:00
fabro-oauth Replace bare unwrap() with documented expect() across production runtim… (#415) 2026-05-26 17:46:39 -04:00
fabro-options-metadata refactor(dev): simplify generated docs tooling 2026-04-24 18:41:00 -04:00
fabro-proc refactor(static): centralize env var names 2026-04-24 12:29:51 -04:00
fabro-redact refactor(integrations): make chat integrations Slack-only 2026-05-09 11:43:16 -04:00
fabro-sandbox Model run sandbox lifecycle explicitly (#431) 2026-05-27 12:48:56 -04:00
fabro-server perf(server): cache bare GitHub clones for automation materialization 2026-05-29 08:29:58 -04:00
fabro-slack Replace vague expect/panic messages with invariant-explaining messages (#422) 2026-05-27 10:38:20 -04:00
fabro-spa feat(dev): gitignore embedded spa assets 2026-04-26 21:31:11 -04:00
fabro-static refactor: rationalize server secret scopes (vault-only for optional int… (#401) 2026-05-25 17:26:01 -04:00
fabro-store perf(server): cache bare GitHub clones for automation materialization 2026-05-29 08:29:58 -04:00
fabro-telemetry Replace vague expect/panic messages with invariant-explaining messages (#422) 2026-05-27 10:38:20 -04:00
fabro-template feat(template): resolve template error locations (#333) 2026-05-20 20:15:04 -04:00
fabro-test fix(llm): preserve raw compatible tool arguments (#448) 2026-05-28 11:52:36 -04:00
fabro-tool feat: Add approve/deny run controls to MCP and CLI (#400) 2026-05-25 15:49:57 -04:00
fabro-tracker fix(github): refresh installation tokens during workflows 2026-05-06 07:15:18 -04:00
fabro-types refactor: Remove inbound IP allowlisting (#443) 2026-05-27 22:29:08 -04:00
fabro-util Replace vague expect/panic messages with invariant-explaining messages (#422) 2026-05-27 10:38:20 -04:00
fabro-validate fix(graph): support dotted Fabro graph attributes (#324) 2026-05-20 09:31:08 -04:00
fabro-variable feat(server): add variables API (#430) 2026-05-27 11:46:36 -04:00
fabro-vault feat(server): add variables API (#430) 2026-05-27 11:46:36 -04:00
fabro-workflow Replace stdin JSONL control pipe with WebSocket worker control bus (#440) 2026-05-27 20:24:25 -04:00