fix(hook): bound soft nudges per agent (companion of Graphify-Labs/graphify#3893) - #12
Open
andrebrait wants to merge 2 commits into
Open
andrebrait wants to merge 2 commits into
andrebrait wants to merge 2 commits into
Conversation
|
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. |
The PreToolUse guard re-injected the MANDATORY read/search nudge on every qualifying Read/Glob/Grep/Bash call with no cap and no check whether the agent had just queried the graph. Only the opt-in strict deny was capped. One project measured 8,348 injections (~651k tokens) for 339 graphify calls, several times the cost of every query they were asking for. Skip the soft nudge while the query stamp is fresh (the agent is already oriented) and cap it at GRAPHIFY_HOOK_NUDGE_CAP nudges per session (default 5, 0 disables), counted in a per-session marker next to the strict-mode ones. Calls without a session id are uncounted, the guard still fails open, and the shared marker GC now runs on both paths. Fixes Graphify-Labs#3435
Subagents start with an empty context, but Claude Code gives them the parent's session_id; keying the nudge budget on session_id alone let a parent exhaust a subagent's budget. Key it on session_id plus a hash of agent_id when present. The query stamp is project-wide and cannot say which agent queried, so it no longer silences an agent's first nudge; it silences later ones. The stale-graph notice now draws on the same budget instead of firing on every read of an edited file.
andrebrait
force-pushed
the
fix/per-agent-hook-nudges
branch
from
September 29, 2026 12:01
17a2822 to
158f035
Compare
This branch has not been deployed
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.
Companion of Graphify-Labs#3893 for CI and bot review; same head (
fix/per-agent-hook-nudges) and base (v8, synced to upstreamd6eaa8a). Review discussion that affects the change is mirrored upstream.What does this PR do?
Carries Graphify-Labs#3443 by @L4XB onto the current
v8base, preserving its commit authorship and message, then adds one follow-up commit that closes three gaps found while running it downstream. Refs Graphify-Labs#3435, Graphify-Labs#3756, Graphify-Labs#2984.Relationship to Graphify-Labs#3443
v8. It is an integration candidate, not a claim of original authorship; maintainers can merge whichever shape is easiest, and this can be closed if the follow-up lands in fix(hook): bound the soft read/search nudge per session Graphify-Labs/graphify#3443 directly.The follow-up
session_idand are distinguished only byagent_id(hooks reference). Keying the counter onsession_idalone lets the parent exhaust the budget before a subagent, which starts with an empty context, sees a nudge. The marker is now keyed onsession_idplus a 16-character SHA-256 prefix ofagent_idwhen present, so long ids cannot truncate two agents into one key.last_query_stampis project-wide and cannot say which agent ranquery/explain/path. Each agent's first nudge now fires regardless of the stamp; the stamp silences the later ones. Calls without asession_idkeep the stamp-only behavior._READ_NUDGE_STALEfired on every read of a file edited after the last build. It now draws on the same per-agent budget._nudge_allowedtakes the hook payload instead of a session id so it can readagent_id. The strict-mode deny is unchanged.Type of change
Verification & Invariants
Invariants: each agent (session, or subagent within it) sees its first nudge; after that, nudges stop while the query stamp is fresh and after
GRAPHIFY_HOOK_NUDGE_CAPper agent; the strict deny still fires at most once per session; any marker error fails open.test_fresh_query_stamp_suppresses_denychanges accordingly: with a fresh stamp there is still no deny, the session's first nudge fires, and the second read is silent. New tests cover per-agent budgets (including 64-character session ids), a subagent's first nudge after the parent queried, the stamp without asession_id, and the stale notice sharing the budget. They were run red against Graphify-Labs#3443 alone before the follow-up.Known limitation (inherited from Graphify-Labs#3443): the counter is an unlocked read-modify-write, so concurrent hook processes for the same agent can exceed the cap slightly. They cannot suppress an agent's first nudge.
How was this tested?
Also deployed downstream and checked live under Oh My Pi: after
graphify query, the parent session's next grep was silent, and a freshly spawned subagent still received its first nudge, with separate markers undergraphify-out/cache/hook_sessions/.Graphify-specific checklist
uv run python -m tools.skillgen --bless) when changing their source fragments. (Not applicable.)