* 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>
This commit is contained in:
54
docs/features/graphify-cli-first-graph-queries.md
Normal file
54
docs/features/graphify-cli-first-graph-queries.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
id: 4836
|
||||
title: Graphify CLI Preferred for Planner and Researcher Graph Queries
|
||||
group: 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 query` emits prose and has
|
||||
no `--json` flag; `gsd-tools graphify query` emits JSON with per-edge
|
||||
confidence tiers and `budget_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.
|
||||
- **`--budget` means 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 `graphify` absent from `PATH` the fallback runs and the injected graph
|
||||
context is byte-identical to before.
|
||||
@@ -13,6 +13,7 @@ group: v1.37.0 Features
|
||||
- REQ-GRAPH-04: `graphify.cjs` falls back to `graph.links` when `graph.edges` is absent so older graph artifacts keep rendering.
|
||||
- REQ-GRAPH-05: Graphify is invoked through `gsd-tools.cjs graphify ...` command handlers.
|
||||
- REQ-GRAPH-06: The knowledge-graph location is configurable via `graphify.graph_path` (issue #1825) so one umbrella-level cross-repo graph can serve multiple sibling projects; `query`/`status`/`diff` read the configured graph (relative to project root), with a byte-identical `.planning/graphs/` default when unset.
|
||||
- REQ-GRAPH-07: `status` reports the resolved graph location as `graph_path` — the same absolute path `query`/`diff` read, after the `graphify.graph_path` override is applied — so a caller shelling out to the `graphify` CLI passes it as `--graph` instead of re-deriving the default location (issue #4836).
|
||||
|
||||
**Configuration:** `graphify.enabled`, `graphify.build_timeout`, `graphify.graph_path`
|
||||
**Reference files:** `commands/gsd/graphify.md`, `bin/lib/graphify.cjs`
|
||||
|
||||
Reference in New Issue
Block a user