Context
Follow-up from PR #182 review (#182 (comment)), item 3.
PR-2 ships TPL_NEIGHBORS_CALLS_NODEFILTER_ROLE_COLLISION per Decision 30 in propose/CALLS-NOISE-AND-RESOLUTION-PROPOSE.md: fires when NodeFilter.role is set, edge_types=['CALLS'], and returned method-kind neighbors are dominantly OTHER (≥75%).
Problem
The common agent mistake is filter.role='SERVICE' (or REPOSITORY) expecting callee stereotype projection. That usually yields empty results (method neighbors are rarely typed SERVICE/REPOSITORY), so the collision hint does not fire when agents need it most.
The existing test (test_neighbors_calls_nodefilter_role_collision_hint) uses role: 'OTHER' to satisfy the dominance threshold — it proves the template wiring, not the SERVICE-misuse case.
Proposed direction
- Also emit the hint when
NodeFilter.role is a stereotype-like value (SERVICE, REPOSITORY, … from VALID_ROLES minus OTHER) and CALLS results are empty (with optional guards so we do not spam unrelated empty queries).
- Optionally suppress the dominance-based hint when
node_role == 'OTHER' (that case is not the naming trap).
- Update / add tests for the SERVICE-misuse path; keep Decision 30 coverage documented in propose or add a short amendment note.
Scope
mcp_hints.py (neighbors_calls_meta_hints)
tests/test_mcp_hints.py
- Optional one-line propose amendment if trigger semantics change materially
Out of scope
- Renaming
NodeFilter.role or EdgeFilter.callee_declaring_role (locked in propose).
Context
Follow-up from PR #182 review (#182 (comment)), item 3.
PR-2 ships
TPL_NEIGHBORS_CALLS_NODEFILTER_ROLE_COLLISIONper Decision 30 inpropose/CALLS-NOISE-AND-RESOLUTION-PROPOSE.md: fires whenNodeFilter.roleis set,edge_types=['CALLS'], and returned method-kind neighbors are dominantlyOTHER(≥75%).Problem
The common agent mistake is
filter.role='SERVICE'(orREPOSITORY) expecting callee stereotype projection. That usually yields empty results (method neighbors are rarely typed SERVICE/REPOSITORY), so the collision hint does not fire when agents need it most.The existing test (
test_neighbors_calls_nodefilter_role_collision_hint) usesrole: 'OTHER'to satisfy the dominance threshold — it proves the template wiring, not the SERVICE-misuse case.Proposed direction
NodeFilter.roleis a stereotype-like value (SERVICE,REPOSITORY, … fromVALID_ROLESminusOTHER) and CALLS results are empty (with optional guards so we do not spam unrelated empty queries).node_role == 'OTHER'(that case is not the naming trap).Scope
mcp_hints.py(neighbors_calls_meta_hints)tests/test_mcp_hints.pyOut of scope
NodeFilter.roleorEdgeFilter.callee_declaring_role(locked in propose).