Skip to content

feat(hook): show the graph nodes behind a nudged call, and tighten its wording (companion of Graphify-Labs/graphify#4368) - #15

Closed
andrebrait wants to merge 4 commits into
v8from
feat/nudge-hints-v8
Closed

andrebrait wants to merge 4 commits into
v8from
feat/nudge-hints-v8

Conversation

@andrebrait

Copy link
Copy Markdown
Member

Companion PR (review-only)

Companion of Graphify-Labs#4368 (same head, same upstream base v8 = 7536dc0, identical diff), opened on our fork so our review bots can access it.

Follow-up to Graphify-Labs#3443, which shipped in 0.9.87. That PR decides when the soft nudge fires. This one changes what a firing nudge says: in our downstream build, agents still treated it as noise within the budget. The change was first offered to Graphify-Labs#3443's branch as L4XB#1, but Graphify-Labs#3443 landed without it, so it is proposed here directly on v8.

What changes

  • Call-specific hint. A firing nudge, and the strict-mode deny, ends with a command built from the call and up to five matching graph nodes with file and line:
    Start with: `graphify explain "load_config()"`
    What the graph already has for this call:
    - load_config() (src/app.py L10)
    
    For a search, the terms come from the Grep pattern or the pattern argument of grep/rg/ag/ack. Value-taking flags such as -t/-g/-A are skipped, find/fd are excluded because they match file names, and a grep fed by a pipe is excluded because it filters output, not code. For a read, the hint lists the file's symbols in line order. An exact label match suggests explain; anything else suggests query. Terms shorter than 5 characters only match exactly, so src does not list every path.
  • Cheap and fail-safe. The hint scans graph.json labels directly instead of loading the query stack, which cost about 1.5 s per hook call on a 15k-node graph. Measured: 0.3–0.5 s on 3k–15k-node graphs. Graphs over 24 MiB, a malformed graph, no match, or any error all return the unchanged nudge. Graph text is sanitised to one line with no control characters or backticks and a capped length, because graph.json is repository content.
  • Narrower wording. "…or to modify/debug specific lines" excused nearly every targeted read. The nudge and the deny now allow raw reads only once the exact file and lines are known.
  • Always-on rule. The Claude, AGENTS.md and Gemini blocks now say to query "before your first grep, search or source-file read for a codebase question", to put the rule in every subagent prompt that explores code, and to read raw files only for lines the graph or an earlier read already located. This is recorded as a sanctioned skillgen edit (_QUERY_FIRST_EDIT) next to _GRAPH_DIFF_EDIT. The Kiro and Antigravity blocks use different sentences and are unchanged.

Why: in session logs, the nudge got 28–41 deliveries per session against 0–2 graphify calls, and the model's reasoning never mentioned it. On a real repo, rg 'stripHiddenWrappers' now gets graphify explain "stripHiddenWrappers()" plus its file and line.

Tests: new cases in tests/test_hook_guard.py and tests/test_hook_strict.py cover hint content and ranking, the 5-node cap, flag parsing, path-only and short-term non-matches, hostile labels, malformed and oversized graphs, and the deny hint. All skillgen guards pass (--check, --always-on-roundtrip, --audit-coverage, --monolith-roundtrip), and the hook, install-string and skillgen tests pass (236).

@github-actions

Copy link
Copy Markdown

Thanks for the pull request, @andrebrait. A maintainer will review it soon.

Want to talk it through while it is in review? Come join us on our Discord server. For longer-form discussion there is also GitHub Discussions.

A couple of things that speed up review: make sure the test suite passes on Python 3.10 and 3.13, and that the change keeps extraction deterministic.

@andrebrait

Copy link
Copy Markdown
Member Author

@codex review

@andrebrait

Copy link
Copy Markdown
Member Author

@coderabbitai review

…s wording

Agents treated the soft nudge as noise: it was the same placeholder text on
every call, and "or to modify/debug specific lines" excused nearly any
targeted read. A firing nudge (and the strict-mode deny) now carries:

- a command built from the call: `graphify explain "<symbol>"` when the
  searched word is a node label, `graphify query "<terms>"` otherwise, or
  `graphify explain "<file>"` for a read;
- up to five matching graph nodes with file and line, so the nudge shows
  what the graph already knows instead of only asking for it.

The lookup scans graph.json labels and paths directly (0.1-0.5 s on 3k-15k
node graphs; the full query stack costs ~1.5 s per hook call), skips graphs
over 32 MiB, and falls back to the plain nudge on any failure or no match.

The escape clause now allows raw reads only once the exact file and lines
are known, and the always-on rule names the moment to query: before the
first grep, search or source-file read.
Sanitise graph text before it reaches the hint (one line, no control
characters or backticks, capped length), skip the graph parse when the call
has nothing to look up, isolate hint failures so they can never cost the
nudge or the strict deny, skip value-taking flags (rg -t/-g, -A/-B/-C...)
and file-name searches (find/fd), drop declaration keywords from terms,
match labels only (no source-path tier, short terms exact-only), resolve a
relative read target against the project root, and align the strict deny's
wording with the narrowed nudge.
… raw reads

The always-on blocks now tell the assistant to pass the rule to every
subagent that explores code (a fresh subagent may never see a nudge before
it starts reading) and to read raw files only for lines the graph or an
earlier read already located, matching the hook's narrowed wording.
A grep fed by a pipe filters that command's output, not the code, so its
pattern is not a graph lookup the agent skipped.
@andrebrait

Copy link
Copy Markdown
Member Author

@codex review

@andrebrait

Copy link
Copy Markdown
Member Author

@coderabbitai review

@andrebrait

Copy link
Copy Markdown
Member Author

Upstream shipped Graphify-Labs#4368 in v0.9.89 (cherry-picked as ae2035e..ae334f9), so this review-only copy is no longer needed.

@andrebrait andrebrait closed this Oct 13, 2026
@andrebrait
andrebrait deleted the feat/nudge-hints-v8 branch October 13, 2026 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant