* enhance(#4836): prefer the graphify CLI for planner and researcher graph queries The planner gets one knowledge-graph query per phase and the researcher two or three, and that single shot decides which modules the plan treats as related — and therefore how tasks are ordered into waves. It was spent on the built-in reader, which seeds by case-insensitive substring match over a node's label and description and then expands a hardcoded two hops. The phase "User Authentication" seeds on `author`, `authoring` and `unauthorized` with the same weight as `authenticate`, and when the inflated payload exceeds `--budget` the trimmer drops edges by confidence tier — so the highest-confidence tier can be discarded to fit a payload that bad seeding inflated in the first place. The graphify CLI is already a hard dependency of /gsd-graphify build, and it ranks seeds (IDF weighting, trigram fuzzy matching) and applies context filters before traversal. Both prompts now prefer it and fall back to the built-in reader, branching on `command -v graphify` — the same degradation shape the repo already uses for Context7 to ctx7. Binary presence is a self-satisfying gate: a graph can only exist if the binary built it, so the fallback covers edge cases (a CI checkout with a committed graph, a binary since removed), not the common path. No new config key and no new tool grant — both agents already have Bash. The planner additionally runs `graphify affected`. The reference states its own goal as "which subsystems may be affected by changes in this phase", which is literally reverse traversal by relation; the built-in reader only approximates it with undirected two-hop expansion and has no equivalent verb, so `affected` is skipped on the fallback path. `graphify status` now reports `graph_path`, the resolved absolute graph location, on both the present and the missing branch. The CLI takes the graph location as `--graph`, and the prompts must not re-derive `.planning/graphs/graph.json` for it: that would point the CLI at a non-existent local mirror in exactly the umbrella multi-repo setup `graphify.graph_path` (#1825) exists to serve. For the same reason the presence gate in both prompts is now the `status` call itself rather than a bare `ls` of the default location, which was already blind to the override. Known limit, stated in both prompts rather than implied: the two paths return different shapes. `graphify query` emits prose and has no `--json` flag; the built-in emits JSON with per-edge confidence tiers and budget_met/budget_estimate. `--budget` also counts rendered output on one and estimated payload bytes on the other (#2738) — same flag name, different unit. Both are read by a model and nothing machine-parses the injected block. With graphify absent from PATH the injected context is byte-identical to before. Closes #4836 Emitted-Drift-Ack-Growth: gsd-phase-researcher.md — the CLI-first branch, the reason it is preferred, and the output-shape warning are the deliverable; a pointer to a part would not be read at the decision point. Emitted-Drift-Ack-Growth: gsd-planner.md — one sentence in the load_graph_context step pointer, so it stops naming the default graph path the reference no longer assumes. * docs(#4836): record the CLI-first graph query in the planner and researcher entries * chore(#4836): add changeset fragment * enhance(#4836): name the full domain word in the planner's query-term examples The reference's own example — phase "User Authentication" → term "auth" — is the exact collision the CLI-first path exists to avoid, and it stays a collision whenever the fallback path runs, since that path matches the term as a substring of label and description. * fix(#4836): surface graph_path on the unparseable-graph status branch graphifyStatus() returned graph_path on the exists:true and exists:false outcomes but not on the third, error, outcome (graph.json present but unparseable). The planner/researcher prompts gate CLI-first dispatch on exists, not on this outcome, so a corrupt graph file made them fall through to the CLI-first branch with the literal <graph> placeholder and no real path to substitute. * docs(#4836): note graph_path's trust boundary at the --graph interpolation graph_path is reflected verbatim into a double-quoted --graph argument the agent executes via Bash. It comes from graphify.graph_path, a config surface already trusted elsewhere, so this isn't a new trust boundary -- but it is a new injection site (no --graph flag existed on this call before). One-line caution for anyone hardening this later. --------- Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
3.0 KiB
id, title, group
| id | title | group |
|---|---|---|
| 4836 | Graphify CLI Preferred for Planner and Researcher Graph Queries | v1.7.0 Features |
Purpose: gsd-planner gets one knowledge-graph query per phase and
gsd-phase-researcher gets two or three. That single shot decides which modules
the plan treats as related, and therefore how tasks are ordered into waves. It
was spent on the built-in reader, which seeds by case-insensitive substring
match over a node's label and description and then expands a hardcoded two hops
— so the phase "User Authentication" seeds on author, authoring, and
unauthorized with exactly the same weight as authenticate, and when the
inflated result exceeds --budget the trimmer drops edges by confidence tier.
The graphify CLI, already a hard dependency of /gsd-graphify build, ranks
seeds (IDF weighting, trigram fuzzy matching) and applies context filters before
traversal.
Both prompts now prefer the CLI and fall back to the built-in reader. The
branch is command -v graphify, the same degradation shape the repo already
uses for Context7 → ctx7 in references/research-documentation-lookup.md. No
new config key: a graph.json can only exist if graphify update . ran, which
requires the binary, so binary presence is a self-satisfying gate. The fallback
covers edge cases — a CI checkout with a committed graph, a binary since removed
— not the common path. No new tool grant either: both agents already have
Bash.
The planner additionally runs graphify affected. The reference states its
own goal as "which subsystems may be affected by changes in this phase", which is
literally reverse traversal by relation. The built-in reader only approximates it
with undirected two-hop expansion, and has no equivalent verb, so affected is
skipped on the fallback path.
gsd-tools graphify status now returns graph_path. The CLI takes the graph
location as --graph, and the prompts must not re-derive
.planning/graphs/graph.json for it — that would point the CLI at a
non-existent local mirror in exactly the umbrella multi-repo setup
graphify.graph_path (#1825) exists to serve. status already resolves the
override, so it now reports the absolute path it resolved, on both the
graph-present and the graph-missing branch. For the same reason the presence gate
in both prompts is now the status call itself rather than a bare ls of the
default location.
Known limits:
- The two paths return different shapes.
graphify queryemits prose and has no--jsonflag;gsd-tools graphify queryemits JSON with per-edge confidence tiers andbudget_met/budget_estimate. Both are consumed by a model, and nothing machine-parses this block, but the prompts now say so explicitly instead of implying a stable shape. --budgetmeans different things on the two paths — rendered output on the CLI, estimated payload bytes in the built-in reader (#2738). Same flag name, different unit.- With
graphifyabsent fromPATHthe fallback runs and the injected graph context is byte-identical to before.