Files
msd-core/docs/features/knowledge-graph-integration.md
Michel Moreira 76ef60ba25 enhance(#4836): prefer the graphify CLI for planner and researcher graph queries (#4874)
* 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>
2026-09-22 19:59:45 -04:00

2.0 KiB

id, title, group
id title group
121 Knowledge Graph Integration v1.37.0 Features

Purpose: Build, query, and inspect a lightweight knowledge graph of the project in .planning/graphs/. Opt-in per project. Exposed as the /gsd-graphify user-facing command and the gsd-tools.cjs graphify … programmatic verb family. Complements /gsd-map-codebase --query (snapshot-oriented) with a graph-oriented view of nodes and edges across commands, agents, workflows, and phases.

Requirements:

  • REQ-GRAPH-01: Opt-in via graphify.enabled: true in .planning/config.json. When disabled, /gsd-graphify prints an activation hint and stops without writing.
  • REQ-GRAPH-02: Slash-command /gsd-graphify exposes subcommands build, query <term>, status, diff. The programmatic CLI node gsd-tools.cjs graphify … additionally exposes snapshot, which is also invoked automatically as the final step of graphify build.
  • REQ-GRAPH-03: Build runs within the configurable graphify.build_timeout (seconds); exceeding the timeout aborts cleanly without leaving a partial graph.
  • 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