You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Honesty Rules don't cover empty results, so query / path returning nothing reads as "absent from the codebase" rather than "absent from the graph" #2672
graphify/skill.md:707-713 lists five Honesty Rules. All five constrain what the agent may assert — inventing edges, hiding cohesion scores, skipping warnings. None constrain what the agent may conclude from nothing:
- Never invent an edge. If unsure, use AMBIGUOUS.
- Never skip the corpus check warning.
- Always show token cost in the report.
- Never hide cohesion scores behind symbols - show the raw number.
- Never run HTML viz on a graph with more than 5,000 nodes without warning the user.
So when graphify path "A" "B" finds no route, or query traverses to nothing, the natural report is "there is no connection between A and B" — a claim about the codebase. What was actually established is narrower: this graph holds no such path. Those differ whenever the graph is incomplete, which is often and by design:
code is indexed structurally by AST, prose semantically by LLM — a relationship that exists only in prose is absent from a code-only corpus, which is the common /graphify . case
a chunk whose subagent failed is warned about, then omitted from the graph (skill.md Step B3)
the user's wording may simply not match the graph's vocabulary — the query flow already acknowledges this by expanding the question against the graph's own terms first
Every one of those makes an empty result mean "not extracted", not "not there". The user cannot distinguish them from the report.
There is a second, sharper version of the same problem: an empty result and a broken command are indistinguishable on stdout. If the traversal errors, or a lookup runs against a wrong path, the output is also nothing — and "nothing" is exactly the conclusion being tested, so a broken instrument reads as a confirmed finding.
Proposed change
Add two rules to the ## Honesty Rules list:
- Never turn an empty traversal into an absence claim. "No path found" and "no
matching node" mean *not in this graph* — which is a claim about the
extraction, not about the corpus. Report the scope you actually searched
("nothing in the graph connects X to Y; the graph covers N of M files, and
code is indexed structurally while prose is indexed semantically") and name
the likelier explanation: a wording mismatch against the graph's vocabulary,
a file type that was skipped, or a genuinely absent relationship.
- Never trust an empty result from a command whose failure also prints nothing.
When a query, traversal, or lookup returns nothing and that emptiness is the
answer being sought, prove the instrument works first — check the exit
status, or run it against a node you already know exists. A broken command
and a true negative are indistinguishable on stdout, and the broken one
reads as a confirmed finding.
The first rule is cheap to satisfy: the file counts it asks for are already in .graphify_detect.json and the report, so it is a phrasing requirement rather than new work.
Scope
## Honesty Rules is present in all 16graphify/skill*.md variants (verified against v8 at 26128ab), and the tools/skillgen/expected/ fixtures track them.
This is a rules/wording change with no code impact, so it may be simpler to land than the companion issue — but it has the same 16-variant propagation question, which is why this is an issue and not a PR.
Verified / not verified
Verified: the Honesty Rules block verbatim, and its presence in all 16 variants, against v8 at 26128ab.
Verified: the incompleteness sources cited above are each described in skill.md itself (Step 3 AST/semantic split, Step 2 skipped_sensitive, Step B3 chunk-failure warning, the query vocab-expansion note).
Not verified: a reproduced case of a user acting on a false absence. The argument is that the rules permit it, not that a specific incident occurred.
Problem
graphify/skill.md:707-713lists five Honesty Rules. All five constrain what the agent may assert — inventing edges, hiding cohesion scores, skipping warnings. None constrain what the agent may conclude from nothing:So when
graphify path "A" "B"finds no route, orquerytraverses to nothing, the natural report is "there is no connection between A and B" — a claim about the codebase. What was actually established is narrower: this graph holds no such path. Those differ whenever the graph is incomplete, which is often and by design:/graphify .casedetectskips sensitive files (detect(): sensitive-file filter silently drops any path containing 'token', 'secret', 'password'… #2106) and unsupported typesskill.mdStep B3)Every one of those makes an empty result mean "not extracted", not "not there". The user cannot distinguish them from the report.
There is a second, sharper version of the same problem: an empty result and a broken command are indistinguishable on stdout. If the traversal errors, or a lookup runs against a wrong path, the output is also nothing — and "nothing" is exactly the conclusion being tested, so a broken instrument reads as a confirmed finding.
Proposed change
Add two rules to the
## Honesty Ruleslist:The first rule is cheap to satisfy: the file counts it asks for are already in
.graphify_detect.jsonand the report, so it is a phrasing requirement rather than new work.Scope
## Honesty Rulesis present in all 16graphify/skill*.mdvariants (verified againstv8at26128ab), and thetools/skillgen/expected/fixtures track them.This is a rules/wording change with no code impact, so it may be simpler to land than the companion issue — but it has the same 16-variant propagation question, which is why this is an issue and not a PR.
Verified / not verified
v8at26128ab.skill.mditself (Step 3 AST/semantic split, Step 2skipped_sensitive, Step B3 chunk-failure warning, the query vocab-expansion note).