Skip to content

fix(serve): suppress query truncation banner when no nodes were cut (#2601) - #2662

Closed
ousamabenyounes wants to merge 1 commit into
Graphify-Labs:v8from
ousamabenyounes:fix/issue-2601
Closed

fix(serve): suppress query truncation banner when no nodes were cut (#2601)#2662
ousamabenyounes wants to merge 1 commit into
Graphify-Labs:v8from
ousamabenyounes:fix/issue-2601

Conversation

@ousamabenyounes

Copy link
Copy Markdown
Contributor

Why

Fix #2601

query printed the truncation banner even when zero whole nodes were cut. _subgraph_to_text renders every NODE line before any EDGE line, so a char-budget overflow whose cut lands past the last node drops only trailing edges — cut_count is 0, yet the banner still fired:

[!] TRUNCATED: showing 91 of 91 nodes (~6000-token budget). The answer may be among the 0 cut nodes ...

The banner's audience is usually an agent, and this false warning is actively harmful: "the answer may be among the 0 cut nodes" teaches the reader to distrust a complete answer, and an agent that follows the banner's own advice issues follow-up context_filter / get_node calls to recover nodes that were never cut — pure wasted round-trips.

What changed

graphify/serve.py — in _subgraph_to_text, when cut_count == 0 return the full output (the complete node set plus all its edges) with no banner. All nodes are shown and every edge connects shown nodes, so it is a complete answer and renders as one — no misleading notice, and no silently-dropped edges (which would repeat the #BUG2 "silence reads as absence" mistake). When a whole node is genuinely cut (cut_count > 0) the banner still fires exactly as before.

The sibling _cut_lines_to_budget is line-oriented and cannot produce cut_count == 0 (an over-budget cut always drops at least one line), so it is intentionally left untouched.

Test verification (RED → GREEN)

New test test_subgraph_to_text_no_banner_when_only_edges_overflow builds a 4-node K4 and picks token_budget=60 so every NODE line fits but the trailing EDGE lines overflow. It asserts all 4 nodes are shown, no TRUNCATED/cut nodes banner, and all 6 edges survive (so a banner-suppressed-but-edge-truncated implementation would still fail).

RED — unmodified v8, new test only:

>       assert "TRUNCATED" not in text and "truncated" not in text
E       AssertionError: assert ('TRUNCATED' not in '[!] TRUNCAT...ific symbol)'
E         'TRUNCATED' is contained here:
E           [!] TRUNCATED: showing 4 of 4 nodes (~60-token budget). The answer may be among the 0 cut nodes ...
FAILED tests/test_serve.py::test_subgraph_to_text_no_banner_when_only_edges_overflow
1 failed

GREEN — with the fix:

tests/test_serve.py::test_subgraph_to_text_no_banner_when_only_edges_overflow PASSED
1 passed

Full local suite

  • pytest tests/ (Python 3.12 & 3.10): 4306 passed, 3 skipped. Two failures are pre-existing on unmodified v8 and unrelated to this change (test_collect_files_skips_hidden picks up local .venv/hidden dirs in the checkout; test_property_normalize_id_agrees_with_its_own_caseless_form is a hypothesis Unicode combining-mark falsifying example). Both reproduce identically on v8 with this diff stashed — iso-baseline, no new failures.
  • tests/test_serve.py: 140 passed. The existing truncation guards (test_subgraph_to_text_truncates, test_subgraph_to_text_seed_survives_truncation, test_subgraph_to_text_truncation_notice_at_top) still pass — the banner is unchanged whenever a node is actually cut.
  • ruff check graphify tests clean; skillgen --check OK (no generated files touched).
  • Minimal diff: one guard in serve.py, one new test, one CHANGELOG entry.

…raphify-Labs#2601)

Nodes render before edges in _subgraph_to_text, so a char-budget overflow
whose cut lands past the last NODE line drops only trailing edges — zero whole
nodes. The banner then falsely read 'showing N of N nodes ... among the 0 cut
nodes', teaching agents to distrust a complete answer and burn narrowing calls.
Return the full output with no banner when cut_count == 0.

Generated by Ora Studio
Vibe coded by ousamabenyounes

Co-Authored-By: Ora Agent <noreply@oratelecom.net>

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.

Formal verification. 1 change(s) tested, no difference found (not proven).


Graphify review — findings

This PR modifies the _subgraph_to_text function in graphify/serve.py to add an early return that skips the truncation banner when a character-budget overflow only trims trailing edges and cuts zero whole nodes. When cut_count == 0, the function now returns the full output without the "showing N of N nodes … among the 0 cut nodes" notice. A corresponding test and a CHANGELOG entry (#2601) are added. The changed-symbol list is large, but the actual diff only touches one code branch in serve.py, one new test, and one changelog line.

Worth a look

  • cut_count==0 returns full output including edges past char budgetgraphify/serve.py:1092 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 699 functions depend on the 496 functions this change touches.

Health — grade A; 10 existing hotspot(s) in the area this change touches (pre-existing, not introduced here):

  • dispatch_command() — 2 callers, 117 callees (high)
  • _query_graph_text() — 18 callers, 8 callees (high)
  • _score_query() — 15 callers, 5 callees (high)
  • _query_terms() — 17 callers, 3 callees (high)
  • run_benchmark() — 16 callers, 3 callees (high)
  • _build_server() — 2 callers, 16 callees (high)
  • _load_graph() — 9 callers, 3 callees (medium)
  • _shortest_path_text() — 5 callers, 4 callees (medium)
  • …and 2 more

Verification — 699 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 549 function(s) in the blast radius were not formally verified this run

Formal verification

No difference found (not proven): No behavior difference found in \_subgraph\_to\_text (not a proof).

The verifier ran both versions of \_subgraph\_to\_text on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.

Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.

Note: An input the sampler did not try could still differ.

@safishamsi

Copy link
Copy Markdown
Collaborator

Shipped in v0.9.41 (graphifyy==0.9.41 on PyPI) (#2601). Credited in the release notes. Thanks @ousamabenyounes!

@safishamsi safishamsi closed this Aug 12, 2026
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.

query prints the TRUNCATED banner when 0 nodes were cut

2 participants