test(invariant): machine-check the exec_real_git reachability whitelist#22
Merged
Conversation
`exec_real_git` / `exec_with_conflict_guidance` are the shim's terminal passthrough capability — the only two functions handing the caller's argv to real git. Their reachability was auditable by a single-file grep only because main.rs keeps zero `pub` items; this encodes that audit as a syn-based AST invariant so it survives future refactors (decision d-20260706152615194350-1, the agreed alternative to a big-bang module split). The test walks every src/ file's AST and compares ALL references to the two exec fns against an exact whitelist keyed by (file, enclosing fn, structural context — enclosing match-arm variant + guard, or if-condition descriptor; never line numbers). Covered evasions, each with an injection counter-test proven red: bare new call points, crate-qualified calls from sibling modules, `use ... as` alias imports, fn-pointer harvest, macro token-stream smuggling (conservative string scan — the one non-AST check), shadow re-definitions, and silent whitelist rot (removed call sites fail too — the multiset is exact in both directions). End-to-end falsification: injecting a bare `crate::exec_real_git` call into cli.rs on the real tree fails the invariant naming the exact site (`cli.rs :: sneaky_e2e_probe :: call exec_real_git`); reverting restores green. syn was already in the dependency tree (via serde_derive); the dev-dep adds no new crate to the build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sible_match under --all-targets) fugu REJECTED @1437ccc: cargo clippy --all-targets -D warnings fails on the Rename arm nested if. Detection semantics unchanged (8/8 invariant tests still green, incl. the alias counter-test); local gate widened to --all-targets which CI (workspace-only clippy) does not cover. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
crates/agentic-git/tests/exec_reachability_invariant.rs: a syn-based AST invariant test that machine-checks the call-site whitelist of the shim's terminal passthrough capability —exec_real_gitandexec_with_conflict_guidance— plus asyndev-dependency (already in the dep tree transitively via serde_derive; no new crate compiled).Why
Outcome of the adversarial design discussion between claude-agentic-git and fugu (decision
d-20260706152615194350-1): fugu's original finding proposed splitting main.rs into six modules; the debate concluded the opposite — main.rs's zero-pub, single-file layout is an audit asset for a security gate (the "which paths reach exec without passing classify?" question is a one-file grep), and the right investment is a machine-checked guardrail, not a structural split. This PR is that guardrail:src/fails the test until the whitelist is consciously updated in the same PR — the review hook is the point.Whitelisted exec surface (current, verified)
exec_real_gitshim_main@if should_bypass(bypass early path)exec_real_gitshim_main@if is_empty(no-agent early path)exec_real_gitshim_main@ dispatch-armPassthrough(unguarded)exec_real_gitshim_main@ dispatch-armChdirPass(unguarded)exec_real_gitshim_main@ dispatch-armCleanupAndChdirPushPass(unguarded)exec_with_conflict_guidanceshim_main@ dispatch-armChdirPass(guarded byis_conflict_capable)Covered evasions (each with an injection counter-test proven red)
crate::exec_real_git(...)in snapshot.rs/cli.rs)use crate::exec_real_git as rg) — both rename directionslet f = exec_real_git;)Scope boundary (deliberate)
Integration tests under
tests/exec the built binary and cannot link these private fns;agentic-git-corecannot reach them. InternalCommand::new(git)query sites (fixed argv, e.g.current_branch_of) are a different, lower-risk class — not covered.Verification
cargo test -p agentic-git --test exec_reachability_invariant→ 8/8 greenfn sneaky_e2e_probe(args: &[String]) { crate::exec_real_git(args, None); }to cli.rs → invariant FAILED namingcli.rs :: sneaky_e2e_probe :: call exec_real_git @ no-context; reverted → greencargo test --workspace→ 15/15 suites ok, 0 failedcargo clippy --workspace -- -D warnings→ cleancargo package -p agentic-git --allow-dirty(publish gate) → passes🤖 Generated with Claude Code