Skip to content

Generated CLAUDE.md block gates every imperative on an edit, so read-only sessions never invoke the tools (measured 0/9 runs) #3076

Description

@uxl

Area

Documentation / developer experience

Summary

Every imperative in the generated <!-- gitnexus:start --> block is conditioned on an edit, so a read-only task trips none of them and the MCP tools go entirely unused — measured at 0 tool calls across 9 runs.

Context

Verified on 1.6.10 (npm latest). The rendered block carries 7 imperative lines; 6 are explicitly gated on edit / commit / rename:

  • MUST run impact analysis before editing
  • MUST analyze graph changes before committing
  • MUST warn the user ... before proceeding with edits
  • NEVER edit a function, class, or method before ... impact analysis
  • NEVER rename symbols with find-and-replace
  • NEVER commit before ... graph change analysis

The 7th ("never read UNKNOWN as an all-clear") is only reachable once impact has already been run. The read-path guidance is two non-imperative "When exploring ..., use ..." bullets. Nothing imperative attaches to a read-only action.

Measurement. I benchmarked this as one arm of a controlled 27-run comparison on a 274k-LOC repo: three read-only codebase questions (transitive module dependents, top-level functions in a 4,444-line file, a cross-layer trace), 3 repetitions, sonnet, --strict-mcp-config, hooks neutralised identically across arms.

In the GitNexus arm the agent made 0 gitnexus tool calls in 9 of 9 runs — it never even enumerated the tools. All 13 were connected and listed; the block was present in CLAUDE.md. It answered every question with grep. The comparison arm, a different graph tool whose session directive is unconditional rather than edit-gated, was invoked in 8 of 9 runs on identical questions. Same deferred-tool mechanism, same model, opposite outcome — the difference is the framing.

This is a real cost: the index was built and current, and the agent went around it. It also compounds #3073 — the block's prescribed calls omit repo, which cannot work once a second repo is indexed.

Distinct from #2954, which asks where the block is injected; this is about what it says.

Expected behavior

At least one imperative that fires on a read. Something of the shape: "MUST use query/context/impact instead of grep when asked who calls, what breaks, what imports, or how a flow works — the graph has edges, grep has strings."

Actual behavior

Read-only sessions never invoke the tools. 0/9 runs, as above.

Environment

gitnexus 1.6.10 (template text); benchmark arm run against a 1.6.3 index, Claude Code stdio MCP, 13 tools connected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions