@drafthq/draft 3.1.5 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/cli/src/hosts/claude-code.js +4 -1
- package/cli/src/installer.js +12 -5
- package/core/shared/graph-query.md +136 -5
- package/integrations/agents/AGENTS.md +136 -5
- package/integrations/copilot/.github/copilot-instructions.md +136 -5
- package/package.json +2 -1
- package/scripts/lib.sh +10 -0
- package/scripts/tools/_graph_queries.sh +102 -0
- package/scripts/tools/cycle-detect.sh +18 -15
- package/scripts/tools/graph-callers.sh +71 -20
- package/scripts/tools/graph-deps.sh +76 -0
- package/scripts/tools/graph-errors.sh +97 -0
- package/scripts/tools/graph-hierarchy.sh +89 -0
- package/scripts/tools/graph-query.sh +124 -0
- package/scripts/tools/graph-risk.sh +81 -0
- package/scripts/tools/graph-search.sh +84 -0
- package/scripts/tools/graph-snapshot.sh +13 -1
- package/scripts/tools/graph-snippet.sh +92 -0
- package/scripts/tools/graph-tests.sh +112 -0
- package/scripts/tools/graph-traces.sh +83 -0
- package/scripts/tools/hotspot-rank.sh +43 -16
- package/scripts/tools/mermaid-from-graph.sh +31 -10
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"name": "draft",
|
|
13
13
|
"source": "./",
|
|
14
14
|
"description": "Context-Driven Development: draft specs and plans before implementation. Structured workflows for features and fixes.",
|
|
15
|
-
"version": "3.
|
|
15
|
+
"version": "3.2.0",
|
|
16
16
|
"author": {
|
|
17
17
|
"name": "mayurpise"
|
|
18
18
|
},
|
|
@@ -56,7 +56,10 @@ module.exports = {
|
|
|
56
56
|
],
|
|
57
57
|
graph: true, // fetch the graph engine at install time (/draft:init also fetches on first use as a fallback)
|
|
58
58
|
done: 'Installed/updated draft. Restart Claude Code (or start a new session), then run /draft:init.',
|
|
59
|
-
|
|
59
|
+
// Shown when the `claude` CLI is absent OR a step fails: the in-session
|
|
60
|
+
// /plugin commands work without the terminal CLI on PATH.
|
|
61
|
+
onFailHint: 'If that failed with "unknown command", your Claude Code is too old for the `claude plugin` command — run "claude update" (or upgrade the app), then re-run.',
|
|
62
|
+
fallbackTitle: 'Run these inside a Claude Code session instead (or put the `claude` CLI on your PATH and re-run):',
|
|
60
63
|
fallback: [
|
|
61
64
|
'/plugin marketplace add drafthq/draft',
|
|
62
65
|
'/plugin marketplace update draft-plugins',
|
package/cli/src/installer.js
CHANGED
|
@@ -5,9 +5,13 @@ const fsx = require('./lib/fsx');
|
|
|
5
5
|
const log = require('./lib/log');
|
|
6
6
|
const { fetchGraph } = require('./lib/graph');
|
|
7
7
|
|
|
8
|
+
// A short ceiling so a wedged `claude --version` can't hang the installer
|
|
9
|
+
// before we even reach the real (separately-timed) install steps.
|
|
10
|
+
const CHECK_TIMEOUT_MS = 10000;
|
|
11
|
+
|
|
8
12
|
function hasBinary(name) {
|
|
9
13
|
// ENOENT on the error means the binary is not on PATH.
|
|
10
|
-
const r = spawnSync(name, ['--version'], { stdio: 'ignore' });
|
|
14
|
+
const r = spawnSync(name, ['--version'], { stdio: 'ignore', timeout: CHECK_TIMEOUT_MS });
|
|
11
15
|
return !(r.error && r.error.code === 'ENOENT');
|
|
12
16
|
}
|
|
13
17
|
|
|
@@ -59,12 +63,14 @@ function install(host, ctx) {
|
|
|
59
63
|
const plan = host.plan(ctx);
|
|
60
64
|
log.step(`Installing Draft -> ${host.label} [${plan.targetSummary}]${ctx.dryRun ? ' (dry run)' : ''}`);
|
|
61
65
|
|
|
62
|
-
// A plan may require an external CLI (e.g. claude). If it's missing,
|
|
63
|
-
// the manual fallback and
|
|
64
|
-
// dry run still shows the
|
|
66
|
+
// A plan may require an external CLI (e.g. claude). If it's missing, say so
|
|
67
|
+
// loudly, print the manual fallback, and exit non-zero — a no-op must never
|
|
68
|
+
// read as success. Only enforced on a real install; a dry run still shows the
|
|
69
|
+
// planned commands.
|
|
65
70
|
if (plan.requires && !ctx.dryRun && !hasBinary(plan.requires)) {
|
|
71
|
+
log.error(`Cannot auto-install: the "${plan.requires}" CLI is not on your PATH. Nothing was installed.`);
|
|
66
72
|
printFallback(plan);
|
|
67
|
-
return
|
|
73
|
+
return 1;
|
|
68
74
|
}
|
|
69
75
|
|
|
70
76
|
// Pre-flight: for file copies, every bundled source must exist and guarded
|
|
@@ -88,6 +94,7 @@ function install(host, ctx) {
|
|
|
88
94
|
const code = execAction(act, ctx);
|
|
89
95
|
if (code !== 0) {
|
|
90
96
|
log.error(`Step failed (exit ${code}): ${act.label || act.cmd}`);
|
|
97
|
+
if (plan.onFailHint) log.error(plan.onFailHint);
|
|
91
98
|
if (plan.fallback) printFallback(plan);
|
|
92
99
|
return code;
|
|
93
100
|
}
|
|
@@ -55,7 +55,7 @@ A single "no" / "list" answer is a halt — fix and re-check before output.
|
|
|
55
55
|
|
|
56
56
|
Use this recipe whenever the user names a concept, feature, or domain term ("in-memory shuffle", "auth flow", "ingest pipeline") and you need to locate the implementing files. **Run it before any filesystem search.**
|
|
57
57
|
|
|
58
|
-
1. **Concept → modules** — query the engine for the package list (`scripts/tools/graph-arch.sh --repo . | jq -r '.packages[].name'`) and cross-reference `draft/.ai-context.md` (module headings). Record the candidate module list.
|
|
58
|
+
1. **Concept → modules** — query the engine for the package list (`scripts/tools/graph-arch.sh --repo . | jq -r '.packages[].name'`) and cross-reference `draft/.ai-context.md` (module headings). Record the candidate module list. For an **intent/concept** name (not an exact symbol), start with semantic search: `scripts/tools/graph-search.sh --repo . --query "<concept>"` returns ranked candidate symbols directly.
|
|
59
59
|
2. **Concept → symbols/callers** — for a named function, run `scripts/tools/graph-callers.sh --repo . --symbol <name>` to find call sites, and `scripts/tools/graph-impact.sh --repo . --symbol <name>` for transitive dependents. These are the authoritative structural answers.
|
|
60
60
|
3. **Modules → risk ranking** — rank with `scripts/tools/hotspot-rank.sh --repo . [--top N]`. High-fanIn symbols are the most likely entry points for impact.
|
|
61
61
|
4. **Concept → public API** — for API-shaped concepts, read the engine's `.routes` (`get_architecture` output, detected HTTP/gRPC/GraphQL routes) for matching service surface.
|
|
@@ -102,12 +102,76 @@ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$HOME/.claude/plugins/draft}/scripts/tools"
|
|
|
102
102
|
|
|
103
103
|
| Wrapper | Graph mode | Behavior on missing graph |
|
|
104
104
|
|---|---|---|
|
|
105
|
-
| `bash "$DRAFT_TOOLS/hotspot-rank.sh" [--top N]
|
|
106
|
-
| `bash "$DRAFT_TOOLS/cycle-detect.sh"` |
|
|
107
|
-
| `bash "$DRAFT_TOOLS/mermaid-from-graph.sh" [--diagram module-deps\|proto-map]` |
|
|
105
|
+
| `bash "$DRAFT_TOOLS/hotspot-rank.sh" [--top N]` | complexity-weighted hotspots | Emits `{hotspots:[],source:"unavailable"}` and exits 2 |
|
|
106
|
+
| `bash "$DRAFT_TOOLS/cycle-detect.sh"` | call cycles | Emits `{cycles:[],source:"unavailable"}` and exits 2 |
|
|
107
|
+
| `bash "$DRAFT_TOOLS/mermaid-from-graph.sh" [--diagram module-deps\|co-change\|proto-map]` | diagram text | Emits an empty mermaid block and exits 2 |
|
|
108
|
+
| `bash "$DRAFT_TOOLS/graph-callers.sh" --symbol N [--transitive[=N]] [--prod-only] [--qualified]` | callers | `{callers:[],status:"unavailable",source:"unavailable"}`, exit 2 |
|
|
109
|
+
| `bash "$DRAFT_TOOLS/graph-snippet.sh" --qualified N` | verified source + caller/callee counts | `{status:"unavailable",source:"unavailable"}`, exit 2 |
|
|
110
|
+
| `bash "$DRAFT_TOOLS/graph-search.sh" --query "STR" [--limit N]` | semantic/ranked search | `{results:[],source:"unavailable"}`, exit 2 |
|
|
111
|
+
| `bash "$DRAFT_TOOLS/graph-tests.sh" (--symbol N \| --untested)` | test→symbol coverage | `{tests:[]/untested:[],source:"unavailable"}`, exit 2 |
|
|
112
|
+
| `bash "$DRAFT_TOOLS/graph-deps.sh" [--file PATH]` | real IMPORTS graph | `{imports:[],source:"unavailable"}`, exit 2 |
|
|
113
|
+
| `bash "$DRAFT_TOOLS/graph-hierarchy.sh" [--symbol N \| --derived N]` | INHERITS tree | `{edges:[],source:"unavailable"}`, exit 2 |
|
|
114
|
+
| `bash "$DRAFT_TOOLS/graph-errors.sh" (--symbol N \| --type N)` | RAISES/THROWS | `{raises:[]/raisers:[],source:"unavailable"}`, exit 2 |
|
|
115
|
+
| `bash "$DRAFT_TOOLS/graph-risk.sh" [--min-complexity N]` | pre-computed risk flags | `{risky:[],source:"unavailable"}`, exit 2 |
|
|
116
|
+
| `bash "$DRAFT_TOOLS/graph-query.sh" (--cypher STR \| --tool NAME --json '{...}')` | generic read-only passthrough | `{source:"unavailable"}`, exit 2 |
|
|
117
|
+
| `bash "$DRAFT_TOOLS/graph-traces.sh" ingest --file F --experimental` | runtime traces (experimental write) | `{source:"unavailable"}`, exit 2 |
|
|
108
118
|
|
|
109
119
|
For lower-level modes, call the engine directly: `codebase-memory-mcp cli <tool> '<json>'` (see the tool list in [bin/README.md](../../bin/README.md)).
|
|
110
120
|
|
|
121
|
+
### Capability wrappers & dialect limits (graph-tooling-v2)
|
|
122
|
+
|
|
123
|
+
All Cypher lives in `scripts/tools/_graph_queries.sh` (the single source of query
|
|
124
|
+
truth). Wrappers are thin arg-parse → builder → fail-loud JSON. Three contracts
|
|
125
|
+
matter when consuming them:
|
|
126
|
+
|
|
127
|
+
**Fail-loud status.** Symbol-scoped wrappers (`graph-callers`, `graph-snippet`,
|
|
128
|
+
`graph-tests --symbol`, `graph-hierarchy --symbol/--derived`, `graph-errors`)
|
|
129
|
+
emit a `status` field that distinguishes the three real outcomes — never read a
|
|
130
|
+
bare `[]` as a confirmed true negative:
|
|
131
|
+
|
|
132
|
+
| `status` | Meaning |
|
|
133
|
+
|---|---|
|
|
134
|
+
| `ok` | node found, edges returned |
|
|
135
|
+
| `no-edges` | node exists but has no matching edge (a *real* negative) |
|
|
136
|
+
| `no-match` | the named symbol was not found at all (check the name / try `--qualified`) |
|
|
137
|
+
| `unavailable` | engine could not be resolved (exit 2) |
|
|
138
|
+
|
|
139
|
+
**Verified engine param shapes** (engine v0.8.x — the runtime source of truth is
|
|
140
|
+
`get_graph_schema`; do not hardcode a property set):
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
get_code_snippet '{"project":P,"qualified_name":"pkg.Mod.Class.method"}' # → source + callers/callees counts + transitive_loop_depth
|
|
144
|
+
search_graph '{"project":P,"query":"order submission to broker","limit":5}' # → {results:[{name,qualified_name,label,file_path,rank}]}
|
|
145
|
+
trace_path '{"project":P,"function_name":"submit_order","depth":3,"direction":"both"}' # depth-bounded caller EXPANDER, not an A→B pathfinder
|
|
146
|
+
detect_changes '{"project":P}' # → {changed_files, changed_count, impacted_symbols, depth}
|
|
147
|
+
get_graph_schema '{"project":P}' # → {node_labels:[{label,count,properties}], edge_types:[{type,count}]}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Cypher dialect — keep queries inside the SAFE set:**
|
|
151
|
+
|
|
152
|
+
- ✅ SAFE: fixed-length patterns, single/multi-hop explicit patterns, `=`, `<`,
|
|
153
|
+
`STARTS WITH`, `NOT x STARTS WITH`, `AND`, `OR`, relationship-type alternation
|
|
154
|
+
`[:A|B]`, simple `count(x)`.
|
|
155
|
+
- ❌ UNSAFE (rejected or silently empty): `coalesce()`, `<>` / `!=` / `<=` / `>=`,
|
|
156
|
+
`NOT EXISTS(...)`, `NOT (pattern)`, `WITH`-grouping aggregation, multi-pattern
|
|
157
|
+
joins. `graph-query.sh --cypher` returns the engine's raw error, not a silent
|
|
158
|
+
empty — but the builders never emit these forms.
|
|
159
|
+
|
|
160
|
+
**Caveats consumers must respect:**
|
|
161
|
+
|
|
162
|
+
- **`--prod-only` is best-effort.** It filters `is_test=false AND NOT file_path
|
|
163
|
+
STARTS WITH 'tests/'`. `is_test` is partially populated by the engine, so test
|
|
164
|
+
helpers/mocks can leak through. Treat it as a heuristic, not a guarantee.
|
|
165
|
+
- **`--transitive` uses the `trace_path` expander** (a depth-bounded caller
|
|
166
|
+
expansion from one symbol), not a from→to pathfinder. "Path between A and B"
|
|
167
|
+
still needs an explicit fixed-length `graph-query.sh --cypher` pattern.
|
|
168
|
+
- **Honest caps.** `cycle-detect`, `graph-deps`, `graph-risk`, `graph-tests
|
|
169
|
+
--untested` cap their output and report `"truncated": true` when the cap is
|
|
170
|
+
hit — results are a sample, not exhaustive.
|
|
171
|
+
- **`graph-tests --untested`** is a set difference (exported symbols minus TESTS
|
|
172
|
+
targets) because the dialect has no anti-join; coverage depends on the engine
|
|
173
|
+
resolving test→symbol links, which varies by language/framework.
|
|
174
|
+
|
|
111
175
|
## Pre-Check
|
|
112
176
|
|
|
113
177
|
Verify graph data exists before any graph operation:
|
|
@@ -196,13 +260,80 @@ scripts/tools/mermaid-from-graph.sh --repo . --diagram proto-map # detected
|
|
|
196
260
|
|
|
197
261
|
Emits a ready-to-inject ` ```mermaid ``` ` block on the fly (computed live by the engine), or an empty stub (exit 2) when the engine is unavailable. Diagrams are generated at the moment of use — they are never committed.
|
|
198
262
|
|
|
263
|
+
### Snippet — verified source + caller/callee counts
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
scripts/tools/graph-snippet.sh --repo . --qualified <pkg.Mod.Class.method>
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Output: `{qualified_name, file, start_line, end_line, callers, callees, transitive_loop_depth, complexity, code, status, source}`. Prefer this over grep+Read when you have a qualified name — it returns the engine's attributed source plus pre-computed counts.
|
|
270
|
+
|
|
271
|
+
### Search — semantic / ranked symbol lookup
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
scripts/tools/graph-search.sh --repo . --query "auth token refresh" [--limit N]
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Output: `{query, results[{name, qualified_name, label, file, rank}], total, source}`. Use when the user names an **intent/concept** rather than an exact symbol — this is the first move in the Concept-to-Files recipe.
|
|
278
|
+
|
|
279
|
+
### Tests — coverage edges and untested surface
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
scripts/tools/graph-tests.sh --repo . --symbol <name> # tests covering a symbol
|
|
283
|
+
scripts/tools/graph-tests.sh --repo . --untested # exported symbols with no TESTS edge
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Output: `{symbol, tests[{test,file}], status, source}` or `{untested[{symbol,file}], total, truncated, source}`. Feeds coverage gaps for `init`/`testing-strategy`/`coverage`.
|
|
287
|
+
|
|
288
|
+
### Deps — real module/file import graph
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
scripts/tools/graph-deps.sh --repo . [--file PATH]
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Output: `{imports[{src,dst}], total, truncated, source}` from actual `IMPORTS` edges (self-imports filtered). This is the auto-derived dependency graph behind `mermaid-from-graph.sh --diagram module-deps` and `architecture.md §9`.
|
|
295
|
+
|
|
296
|
+
### Hierarchy — class inheritance
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
scripts/tools/graph-hierarchy.sh --repo . [--symbol <Class> | --derived <Base>]
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Output: `{edges[{child,parent}], status, source}`. `--derived` gives the blast radius of changing a base class.
|
|
303
|
+
|
|
304
|
+
### Errors — error-propagation paths
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
scripts/tools/graph-errors.sh --repo . --symbol <name> # what it raises/throws
|
|
308
|
+
scripts/tools/graph-errors.sh --repo . --type <ErrType> # who raises/throws that type
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Output: `{symbol, raises[...], status, source}` or `{type, raisers[...], status, source}`. `--type` drives fail-closed audits.
|
|
312
|
+
|
|
313
|
+
### Risk — pre-computed risk hotspots
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
scripts/tools/graph-risk.sh --repo . [--min-complexity N]
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Output: `{risky[{symbol, file, complexity, flags}], total, truncated, source}` from the engine's pre-computed flags (`unguarded_recursion`, `recursion_in_loop`, `alloc_in_loop`, `linear_scan_in_loop`). High-signal input for `bughunt`/`deep-review` — the engine already found these.
|
|
320
|
+
|
|
321
|
+
### Generic — read-only escape hatch (all 20 edges / ~30 properties)
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
scripts/tools/graph-query.sh --repo . --cypher 'MATCH (f)-[:WRITES]->(v) RETURN f.name, v.name LIMIT 50'
|
|
325
|
+
scripts/tools/graph-query.sh --repo . --tool get_graph_schema --json '{}'
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Unlocks any edge type or node property without a purpose-built wrapper. Write verbs are rejected; stay inside the SAFE dialect set (above). Emits raw engine JSON.
|
|
329
|
+
|
|
199
330
|
### Indexing / refreshing the gate marker
|
|
200
331
|
|
|
201
332
|
```bash
|
|
202
333
|
scripts/tools/graph-snapshot.sh --repo .
|
|
203
334
|
```
|
|
204
335
|
|
|
205
|
-
Indexes the repo into the engine and writes the `draft/graph/schema.yaml` gate marker. It writes **no** graph data. Run during `/draft:init` and `/draft:graph`, or whenever the index should be refreshed.
|
|
336
|
+
Indexes the repo into the engine and writes the `draft/graph/schema.yaml` gate marker (now including the `detect_changes` delta: `changed_files`/`impacted_symbols`). It writes **no** graph data. Run during `/draft:init` and `/draft:graph`, or whenever the index should be refreshed.
|
|
206
337
|
|
|
207
338
|
## Finding the Engine (Resolution + Usage Report)
|
|
208
339
|
|
|
@@ -16899,7 +16899,7 @@ A single "no" / "list" answer is a halt — fix and re-check before output.
|
|
|
16899
16899
|
|
|
16900
16900
|
Use this recipe whenever the user names a concept, feature, or domain term ("in-memory shuffle", "auth flow", "ingest pipeline") and you need to locate the implementing files. **Run it before any filesystem search.**
|
|
16901
16901
|
|
|
16902
|
-
1. **Concept → modules** — query the engine for the package list (`scripts/tools/graph-arch.sh --repo . | jq -r '.packages[].name'`) and cross-reference `draft/.ai-context.md` (module headings). Record the candidate module list.
|
|
16902
|
+
1. **Concept → modules** — query the engine for the package list (`scripts/tools/graph-arch.sh --repo . | jq -r '.packages[].name'`) and cross-reference `draft/.ai-context.md` (module headings). Record the candidate module list. For an **intent/concept** name (not an exact symbol), start with semantic search: `scripts/tools/graph-search.sh --repo . --query "<concept>"` returns ranked candidate symbols directly.
|
|
16903
16903
|
2. **Concept → symbols/callers** — for a named function, run `scripts/tools/graph-callers.sh --repo . --symbol <name>` to find call sites, and `scripts/tools/graph-impact.sh --repo . --symbol <name>` for transitive dependents. These are the authoritative structural answers.
|
|
16904
16904
|
3. **Modules → risk ranking** — rank with `scripts/tools/hotspot-rank.sh --repo . [--top N]`. High-fanIn symbols are the most likely entry points for impact.
|
|
16905
16905
|
4. **Concept → public API** — for API-shaped concepts, read the engine's `.routes` (`get_architecture` output, detected HTTP/gRPC/GraphQL routes) for matching service surface.
|
|
@@ -16946,12 +16946,76 @@ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$HOME/.claude/plugins/draft}/scripts/tools"
|
|
|
16946
16946
|
|
|
16947
16947
|
| Wrapper | Graph mode | Behavior on missing graph |
|
|
16948
16948
|
|---|---|---|
|
|
16949
|
-
| `bash "$DRAFT_TOOLS/hotspot-rank.sh" [--top N]
|
|
16950
|
-
| `bash "$DRAFT_TOOLS/cycle-detect.sh"` |
|
|
16951
|
-
| `bash "$DRAFT_TOOLS/mermaid-from-graph.sh" [--diagram module-deps\|proto-map]` |
|
|
16949
|
+
| `bash "$DRAFT_TOOLS/hotspot-rank.sh" [--top N]` | complexity-weighted hotspots | Emits `{hotspots:[],source:"unavailable"}` and exits 2 |
|
|
16950
|
+
| `bash "$DRAFT_TOOLS/cycle-detect.sh"` | call cycles | Emits `{cycles:[],source:"unavailable"}` and exits 2 |
|
|
16951
|
+
| `bash "$DRAFT_TOOLS/mermaid-from-graph.sh" [--diagram module-deps\|co-change\|proto-map]` | diagram text | Emits an empty mermaid block and exits 2 |
|
|
16952
|
+
| `bash "$DRAFT_TOOLS/graph-callers.sh" --symbol N [--transitive[=N]] [--prod-only] [--qualified]` | callers | `{callers:[],status:"unavailable",source:"unavailable"}`, exit 2 |
|
|
16953
|
+
| `bash "$DRAFT_TOOLS/graph-snippet.sh" --qualified N` | verified source + caller/callee counts | `{status:"unavailable",source:"unavailable"}`, exit 2 |
|
|
16954
|
+
| `bash "$DRAFT_TOOLS/graph-search.sh" --query "STR" [--limit N]` | semantic/ranked search | `{results:[],source:"unavailable"}`, exit 2 |
|
|
16955
|
+
| `bash "$DRAFT_TOOLS/graph-tests.sh" (--symbol N \| --untested)` | test→symbol coverage | `{tests:[]/untested:[],source:"unavailable"}`, exit 2 |
|
|
16956
|
+
| `bash "$DRAFT_TOOLS/graph-deps.sh" [--file PATH]` | real IMPORTS graph | `{imports:[],source:"unavailable"}`, exit 2 |
|
|
16957
|
+
| `bash "$DRAFT_TOOLS/graph-hierarchy.sh" [--symbol N \| --derived N]` | INHERITS tree | `{edges:[],source:"unavailable"}`, exit 2 |
|
|
16958
|
+
| `bash "$DRAFT_TOOLS/graph-errors.sh" (--symbol N \| --type N)` | RAISES/THROWS | `{raises:[]/raisers:[],source:"unavailable"}`, exit 2 |
|
|
16959
|
+
| `bash "$DRAFT_TOOLS/graph-risk.sh" [--min-complexity N]` | pre-computed risk flags | `{risky:[],source:"unavailable"}`, exit 2 |
|
|
16960
|
+
| `bash "$DRAFT_TOOLS/graph-query.sh" (--cypher STR \| --tool NAME --json '{...}')` | generic read-only passthrough | `{source:"unavailable"}`, exit 2 |
|
|
16961
|
+
| `bash "$DRAFT_TOOLS/graph-traces.sh" ingest --file F --experimental` | runtime traces (experimental write) | `{source:"unavailable"}`, exit 2 |
|
|
16952
16962
|
|
|
16953
16963
|
For lower-level modes, call the engine directly: `codebase-memory-mcp cli <tool> '<json>'` (see the tool list in [bin/README.md](../../bin/README.md)).
|
|
16954
16964
|
|
|
16965
|
+
### Capability wrappers & dialect limits (graph-tooling-v2)
|
|
16966
|
+
|
|
16967
|
+
All Cypher lives in `scripts/tools/_graph_queries.sh` (the single source of query
|
|
16968
|
+
truth). Wrappers are thin arg-parse → builder → fail-loud JSON. Three contracts
|
|
16969
|
+
matter when consuming them:
|
|
16970
|
+
|
|
16971
|
+
**Fail-loud status.** Symbol-scoped wrappers (`graph-callers`, `graph-snippet`,
|
|
16972
|
+
`graph-tests --symbol`, `graph-hierarchy --symbol/--derived`, `graph-errors`)
|
|
16973
|
+
emit a `status` field that distinguishes the three real outcomes — never read a
|
|
16974
|
+
bare `[]` as a confirmed true negative:
|
|
16975
|
+
|
|
16976
|
+
| `status` | Meaning |
|
|
16977
|
+
|---|---|
|
|
16978
|
+
| `ok` | node found, edges returned |
|
|
16979
|
+
| `no-edges` | node exists but has no matching edge (a *real* negative) |
|
|
16980
|
+
| `no-match` | the named symbol was not found at all (check the name / try `--qualified`) |
|
|
16981
|
+
| `unavailable` | engine could not be resolved (exit 2) |
|
|
16982
|
+
|
|
16983
|
+
**Verified engine param shapes** (engine v0.8.x — the runtime source of truth is
|
|
16984
|
+
`get_graph_schema`; do not hardcode a property set):
|
|
16985
|
+
|
|
16986
|
+
```bash
|
|
16987
|
+
get_code_snippet '{"project":P,"qualified_name":"pkg.Mod.Class.method"}' # → source + callers/callees counts + transitive_loop_depth
|
|
16988
|
+
search_graph '{"project":P,"query":"order submission to broker","limit":5}' # → {results:[{name,qualified_name,label,file_path,rank}]}
|
|
16989
|
+
trace_path '{"project":P,"function_name":"submit_order","depth":3,"direction":"both"}' # depth-bounded caller EXPANDER, not an A→B pathfinder
|
|
16990
|
+
detect_changes '{"project":P}' # → {changed_files, changed_count, impacted_symbols, depth}
|
|
16991
|
+
get_graph_schema '{"project":P}' # → {node_labels:[{label,count,properties}], edge_types:[{type,count}]}
|
|
16992
|
+
```
|
|
16993
|
+
|
|
16994
|
+
**Cypher dialect — keep queries inside the SAFE set:**
|
|
16995
|
+
|
|
16996
|
+
- ✅ SAFE: fixed-length patterns, single/multi-hop explicit patterns, `=`, `<`,
|
|
16997
|
+
`STARTS WITH`, `NOT x STARTS WITH`, `AND`, `OR`, relationship-type alternation
|
|
16998
|
+
`[:A|B]`, simple `count(x)`.
|
|
16999
|
+
- ❌ UNSAFE (rejected or silently empty): `coalesce()`, `<>` / `!=` / `<=` / `>=`,
|
|
17000
|
+
`NOT EXISTS(...)`, `NOT (pattern)`, `WITH`-grouping aggregation, multi-pattern
|
|
17001
|
+
joins. `graph-query.sh --cypher` returns the engine's raw error, not a silent
|
|
17002
|
+
empty — but the builders never emit these forms.
|
|
17003
|
+
|
|
17004
|
+
**Caveats consumers must respect:**
|
|
17005
|
+
|
|
17006
|
+
- **`--prod-only` is best-effort.** It filters `is_test=false AND NOT file_path
|
|
17007
|
+
STARTS WITH 'tests/'`. `is_test` is partially populated by the engine, so test
|
|
17008
|
+
helpers/mocks can leak through. Treat it as a heuristic, not a guarantee.
|
|
17009
|
+
- **`--transitive` uses the `trace_path` expander** (a depth-bounded caller
|
|
17010
|
+
expansion from one symbol), not a from→to pathfinder. "Path between A and B"
|
|
17011
|
+
still needs an explicit fixed-length `graph-query.sh --cypher` pattern.
|
|
17012
|
+
- **Honest caps.** `cycle-detect`, `graph-deps`, `graph-risk`, `graph-tests
|
|
17013
|
+
--untested` cap their output and report `"truncated": true` when the cap is
|
|
17014
|
+
hit — results are a sample, not exhaustive.
|
|
17015
|
+
- **`graph-tests --untested`** is a set difference (exported symbols minus TESTS
|
|
17016
|
+
targets) because the dialect has no anti-join; coverage depends on the engine
|
|
17017
|
+
resolving test→symbol links, which varies by language/framework.
|
|
17018
|
+
|
|
16955
17019
|
## Pre-Check
|
|
16956
17020
|
|
|
16957
17021
|
Verify graph data exists before any graph operation:
|
|
@@ -17040,13 +17104,80 @@ scripts/tools/mermaid-from-graph.sh --repo . --diagram proto-map # detected
|
|
|
17040
17104
|
|
|
17041
17105
|
Emits a ready-to-inject ` ```mermaid ``` ` block on the fly (computed live by the engine), or an empty stub (exit 2) when the engine is unavailable. Diagrams are generated at the moment of use — they are never committed.
|
|
17042
17106
|
|
|
17107
|
+
### Snippet — verified source + caller/callee counts
|
|
17108
|
+
|
|
17109
|
+
```bash
|
|
17110
|
+
scripts/tools/graph-snippet.sh --repo . --qualified <pkg.Mod.Class.method>
|
|
17111
|
+
```
|
|
17112
|
+
|
|
17113
|
+
Output: `{qualified_name, file, start_line, end_line, callers, callees, transitive_loop_depth, complexity, code, status, source}`. Prefer this over grep+Read when you have a qualified name — it returns the engine's attributed source plus pre-computed counts.
|
|
17114
|
+
|
|
17115
|
+
### Search — semantic / ranked symbol lookup
|
|
17116
|
+
|
|
17117
|
+
```bash
|
|
17118
|
+
scripts/tools/graph-search.sh --repo . --query "auth token refresh" [--limit N]
|
|
17119
|
+
```
|
|
17120
|
+
|
|
17121
|
+
Output: `{query, results[{name, qualified_name, label, file, rank}], total, source}`. Use when the user names an **intent/concept** rather than an exact symbol — this is the first move in the Concept-to-Files recipe.
|
|
17122
|
+
|
|
17123
|
+
### Tests — coverage edges and untested surface
|
|
17124
|
+
|
|
17125
|
+
```bash
|
|
17126
|
+
scripts/tools/graph-tests.sh --repo . --symbol <name> # tests covering a symbol
|
|
17127
|
+
scripts/tools/graph-tests.sh --repo . --untested # exported symbols with no TESTS edge
|
|
17128
|
+
```
|
|
17129
|
+
|
|
17130
|
+
Output: `{symbol, tests[{test,file}], status, source}` or `{untested[{symbol,file}], total, truncated, source}`. Feeds coverage gaps for `init`/`testing-strategy`/`coverage`.
|
|
17131
|
+
|
|
17132
|
+
### Deps — real module/file import graph
|
|
17133
|
+
|
|
17134
|
+
```bash
|
|
17135
|
+
scripts/tools/graph-deps.sh --repo . [--file PATH]
|
|
17136
|
+
```
|
|
17137
|
+
|
|
17138
|
+
Output: `{imports[{src,dst}], total, truncated, source}` from actual `IMPORTS` edges (self-imports filtered). This is the auto-derived dependency graph behind `mermaid-from-graph.sh --diagram module-deps` and `architecture.md §9`.
|
|
17139
|
+
|
|
17140
|
+
### Hierarchy — class inheritance
|
|
17141
|
+
|
|
17142
|
+
```bash
|
|
17143
|
+
scripts/tools/graph-hierarchy.sh --repo . [--symbol <Class> | --derived <Base>]
|
|
17144
|
+
```
|
|
17145
|
+
|
|
17146
|
+
Output: `{edges[{child,parent}], status, source}`. `--derived` gives the blast radius of changing a base class.
|
|
17147
|
+
|
|
17148
|
+
### Errors — error-propagation paths
|
|
17149
|
+
|
|
17150
|
+
```bash
|
|
17151
|
+
scripts/tools/graph-errors.sh --repo . --symbol <name> # what it raises/throws
|
|
17152
|
+
scripts/tools/graph-errors.sh --repo . --type <ErrType> # who raises/throws that type
|
|
17153
|
+
```
|
|
17154
|
+
|
|
17155
|
+
Output: `{symbol, raises[...], status, source}` or `{type, raisers[...], status, source}`. `--type` drives fail-closed audits.
|
|
17156
|
+
|
|
17157
|
+
### Risk — pre-computed risk hotspots
|
|
17158
|
+
|
|
17159
|
+
```bash
|
|
17160
|
+
scripts/tools/graph-risk.sh --repo . [--min-complexity N]
|
|
17161
|
+
```
|
|
17162
|
+
|
|
17163
|
+
Output: `{risky[{symbol, file, complexity, flags}], total, truncated, source}` from the engine's pre-computed flags (`unguarded_recursion`, `recursion_in_loop`, `alloc_in_loop`, `linear_scan_in_loop`). High-signal input for `bughunt`/`deep-review` — the engine already found these.
|
|
17164
|
+
|
|
17165
|
+
### Generic — read-only escape hatch (all 20 edges / ~30 properties)
|
|
17166
|
+
|
|
17167
|
+
```bash
|
|
17168
|
+
scripts/tools/graph-query.sh --repo . --cypher 'MATCH (f)-[:WRITES]->(v) RETURN f.name, v.name LIMIT 50'
|
|
17169
|
+
scripts/tools/graph-query.sh --repo . --tool get_graph_schema --json '{}'
|
|
17170
|
+
```
|
|
17171
|
+
|
|
17172
|
+
Unlocks any edge type or node property without a purpose-built wrapper. Write verbs are rejected; stay inside the SAFE dialect set (above). Emits raw engine JSON.
|
|
17173
|
+
|
|
17043
17174
|
### Indexing / refreshing the gate marker
|
|
17044
17175
|
|
|
17045
17176
|
```bash
|
|
17046
17177
|
scripts/tools/graph-snapshot.sh --repo .
|
|
17047
17178
|
```
|
|
17048
17179
|
|
|
17049
|
-
Indexes the repo into the engine and writes the `draft/graph/schema.yaml` gate marker. It writes **no** graph data. Run during `draft init` and `draft graph`, or whenever the index should be refreshed.
|
|
17180
|
+
Indexes the repo into the engine and writes the `draft/graph/schema.yaml` gate marker (now including the `detect_changes` delta: `changed_files`/`impacted_symbols`). It writes **no** graph data. Run during `draft init` and `draft graph`, or whenever the index should be refreshed.
|
|
17050
17181
|
|
|
17051
17182
|
## Finding the Engine (Resolution + Usage Report)
|
|
17052
17183
|
|
|
@@ -16899,7 +16899,7 @@ A single "no" / "list" answer is a halt — fix and re-check before output.
|
|
|
16899
16899
|
|
|
16900
16900
|
Use this recipe whenever the user names a concept, feature, or domain term ("in-memory shuffle", "auth flow", "ingest pipeline") and you need to locate the implementing files. **Run it before any filesystem search.**
|
|
16901
16901
|
|
|
16902
|
-
1. **Concept → modules** — query the engine for the package list (`scripts/tools/graph-arch.sh --repo . | jq -r '.packages[].name'`) and cross-reference `draft/.ai-context.md` (module headings). Record the candidate module list.
|
|
16902
|
+
1. **Concept → modules** — query the engine for the package list (`scripts/tools/graph-arch.sh --repo . | jq -r '.packages[].name'`) and cross-reference `draft/.ai-context.md` (module headings). Record the candidate module list. For an **intent/concept** name (not an exact symbol), start with semantic search: `scripts/tools/graph-search.sh --repo . --query "<concept>"` returns ranked candidate symbols directly.
|
|
16903
16903
|
2. **Concept → symbols/callers** — for a named function, run `scripts/tools/graph-callers.sh --repo . --symbol <name>` to find call sites, and `scripts/tools/graph-impact.sh --repo . --symbol <name>` for transitive dependents. These are the authoritative structural answers.
|
|
16904
16904
|
3. **Modules → risk ranking** — rank with `scripts/tools/hotspot-rank.sh --repo . [--top N]`. High-fanIn symbols are the most likely entry points for impact.
|
|
16905
16905
|
4. **Concept → public API** — for API-shaped concepts, read the engine's `.routes` (`get_architecture` output, detected HTTP/gRPC/GraphQL routes) for matching service surface.
|
|
@@ -16946,12 +16946,76 @@ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$HOME/.claude/plugins/draft}/scripts/tools"
|
|
|
16946
16946
|
|
|
16947
16947
|
| Wrapper | Graph mode | Behavior on missing graph |
|
|
16948
16948
|
|---|---|---|
|
|
16949
|
-
| `bash "$DRAFT_TOOLS/hotspot-rank.sh" [--top N]
|
|
16950
|
-
| `bash "$DRAFT_TOOLS/cycle-detect.sh"` |
|
|
16951
|
-
| `bash "$DRAFT_TOOLS/mermaid-from-graph.sh" [--diagram module-deps\|proto-map]` |
|
|
16949
|
+
| `bash "$DRAFT_TOOLS/hotspot-rank.sh" [--top N]` | complexity-weighted hotspots | Emits `{hotspots:[],source:"unavailable"}` and exits 2 |
|
|
16950
|
+
| `bash "$DRAFT_TOOLS/cycle-detect.sh"` | call cycles | Emits `{cycles:[],source:"unavailable"}` and exits 2 |
|
|
16951
|
+
| `bash "$DRAFT_TOOLS/mermaid-from-graph.sh" [--diagram module-deps\|co-change\|proto-map]` | diagram text | Emits an empty mermaid block and exits 2 |
|
|
16952
|
+
| `bash "$DRAFT_TOOLS/graph-callers.sh" --symbol N [--transitive[=N]] [--prod-only] [--qualified]` | callers | `{callers:[],status:"unavailable",source:"unavailable"}`, exit 2 |
|
|
16953
|
+
| `bash "$DRAFT_TOOLS/graph-snippet.sh" --qualified N` | verified source + caller/callee counts | `{status:"unavailable",source:"unavailable"}`, exit 2 |
|
|
16954
|
+
| `bash "$DRAFT_TOOLS/graph-search.sh" --query "STR" [--limit N]` | semantic/ranked search | `{results:[],source:"unavailable"}`, exit 2 |
|
|
16955
|
+
| `bash "$DRAFT_TOOLS/graph-tests.sh" (--symbol N \| --untested)` | test→symbol coverage | `{tests:[]/untested:[],source:"unavailable"}`, exit 2 |
|
|
16956
|
+
| `bash "$DRAFT_TOOLS/graph-deps.sh" [--file PATH]` | real IMPORTS graph | `{imports:[],source:"unavailable"}`, exit 2 |
|
|
16957
|
+
| `bash "$DRAFT_TOOLS/graph-hierarchy.sh" [--symbol N \| --derived N]` | INHERITS tree | `{edges:[],source:"unavailable"}`, exit 2 |
|
|
16958
|
+
| `bash "$DRAFT_TOOLS/graph-errors.sh" (--symbol N \| --type N)` | RAISES/THROWS | `{raises:[]/raisers:[],source:"unavailable"}`, exit 2 |
|
|
16959
|
+
| `bash "$DRAFT_TOOLS/graph-risk.sh" [--min-complexity N]` | pre-computed risk flags | `{risky:[],source:"unavailable"}`, exit 2 |
|
|
16960
|
+
| `bash "$DRAFT_TOOLS/graph-query.sh" (--cypher STR \| --tool NAME --json '{...}')` | generic read-only passthrough | `{source:"unavailable"}`, exit 2 |
|
|
16961
|
+
| `bash "$DRAFT_TOOLS/graph-traces.sh" ingest --file F --experimental` | runtime traces (experimental write) | `{source:"unavailable"}`, exit 2 |
|
|
16952
16962
|
|
|
16953
16963
|
For lower-level modes, call the engine directly: `codebase-memory-mcp cli <tool> '<json>'` (see the tool list in [bin/README.md](../../bin/README.md)).
|
|
16954
16964
|
|
|
16965
|
+
### Capability wrappers & dialect limits (graph-tooling-v2)
|
|
16966
|
+
|
|
16967
|
+
All Cypher lives in `scripts/tools/_graph_queries.sh` (the single source of query
|
|
16968
|
+
truth). Wrappers are thin arg-parse → builder → fail-loud JSON. Three contracts
|
|
16969
|
+
matter when consuming them:
|
|
16970
|
+
|
|
16971
|
+
**Fail-loud status.** Symbol-scoped wrappers (`graph-callers`, `graph-snippet`,
|
|
16972
|
+
`graph-tests --symbol`, `graph-hierarchy --symbol/--derived`, `graph-errors`)
|
|
16973
|
+
emit a `status` field that distinguishes the three real outcomes — never read a
|
|
16974
|
+
bare `[]` as a confirmed true negative:
|
|
16975
|
+
|
|
16976
|
+
| `status` | Meaning |
|
|
16977
|
+
|---|---|
|
|
16978
|
+
| `ok` | node found, edges returned |
|
|
16979
|
+
| `no-edges` | node exists but has no matching edge (a *real* negative) |
|
|
16980
|
+
| `no-match` | the named symbol was not found at all (check the name / try `--qualified`) |
|
|
16981
|
+
| `unavailable` | engine could not be resolved (exit 2) |
|
|
16982
|
+
|
|
16983
|
+
**Verified engine param shapes** (engine v0.8.x — the runtime source of truth is
|
|
16984
|
+
`get_graph_schema`; do not hardcode a property set):
|
|
16985
|
+
|
|
16986
|
+
```bash
|
|
16987
|
+
get_code_snippet '{"project":P,"qualified_name":"pkg.Mod.Class.method"}' # → source + callers/callees counts + transitive_loop_depth
|
|
16988
|
+
search_graph '{"project":P,"query":"order submission to broker","limit":5}' # → {results:[{name,qualified_name,label,file_path,rank}]}
|
|
16989
|
+
trace_path '{"project":P,"function_name":"submit_order","depth":3,"direction":"both"}' # depth-bounded caller EXPANDER, not an A→B pathfinder
|
|
16990
|
+
detect_changes '{"project":P}' # → {changed_files, changed_count, impacted_symbols, depth}
|
|
16991
|
+
get_graph_schema '{"project":P}' # → {node_labels:[{label,count,properties}], edge_types:[{type,count}]}
|
|
16992
|
+
```
|
|
16993
|
+
|
|
16994
|
+
**Cypher dialect — keep queries inside the SAFE set:**
|
|
16995
|
+
|
|
16996
|
+
- ✅ SAFE: fixed-length patterns, single/multi-hop explicit patterns, `=`, `<`,
|
|
16997
|
+
`STARTS WITH`, `NOT x STARTS WITH`, `AND`, `OR`, relationship-type alternation
|
|
16998
|
+
`[:A|B]`, simple `count(x)`.
|
|
16999
|
+
- ❌ UNSAFE (rejected or silently empty): `coalesce()`, `<>` / `!=` / `<=` / `>=`,
|
|
17000
|
+
`NOT EXISTS(...)`, `NOT (pattern)`, `WITH`-grouping aggregation, multi-pattern
|
|
17001
|
+
joins. `graph-query.sh --cypher` returns the engine's raw error, not a silent
|
|
17002
|
+
empty — but the builders never emit these forms.
|
|
17003
|
+
|
|
17004
|
+
**Caveats consumers must respect:**
|
|
17005
|
+
|
|
17006
|
+
- **`--prod-only` is best-effort.** It filters `is_test=false AND NOT file_path
|
|
17007
|
+
STARTS WITH 'tests/'`. `is_test` is partially populated by the engine, so test
|
|
17008
|
+
helpers/mocks can leak through. Treat it as a heuristic, not a guarantee.
|
|
17009
|
+
- **`--transitive` uses the `trace_path` expander** (a depth-bounded caller
|
|
17010
|
+
expansion from one symbol), not a from→to pathfinder. "Path between A and B"
|
|
17011
|
+
still needs an explicit fixed-length `graph-query.sh --cypher` pattern.
|
|
17012
|
+
- **Honest caps.** `cycle-detect`, `graph-deps`, `graph-risk`, `graph-tests
|
|
17013
|
+
--untested` cap their output and report `"truncated": true` when the cap is
|
|
17014
|
+
hit — results are a sample, not exhaustive.
|
|
17015
|
+
- **`graph-tests --untested`** is a set difference (exported symbols minus TESTS
|
|
17016
|
+
targets) because the dialect has no anti-join; coverage depends on the engine
|
|
17017
|
+
resolving test→symbol links, which varies by language/framework.
|
|
17018
|
+
|
|
16955
17019
|
## Pre-Check
|
|
16956
17020
|
|
|
16957
17021
|
Verify graph data exists before any graph operation:
|
|
@@ -17040,13 +17104,80 @@ scripts/tools/mermaid-from-graph.sh --repo . --diagram proto-map # detected
|
|
|
17040
17104
|
|
|
17041
17105
|
Emits a ready-to-inject ` ```mermaid ``` ` block on the fly (computed live by the engine), or an empty stub (exit 2) when the engine is unavailable. Diagrams are generated at the moment of use — they are never committed.
|
|
17042
17106
|
|
|
17107
|
+
### Snippet — verified source + caller/callee counts
|
|
17108
|
+
|
|
17109
|
+
```bash
|
|
17110
|
+
scripts/tools/graph-snippet.sh --repo . --qualified <pkg.Mod.Class.method>
|
|
17111
|
+
```
|
|
17112
|
+
|
|
17113
|
+
Output: `{qualified_name, file, start_line, end_line, callers, callees, transitive_loop_depth, complexity, code, status, source}`. Prefer this over grep+Read when you have a qualified name — it returns the engine's attributed source plus pre-computed counts.
|
|
17114
|
+
|
|
17115
|
+
### Search — semantic / ranked symbol lookup
|
|
17116
|
+
|
|
17117
|
+
```bash
|
|
17118
|
+
scripts/tools/graph-search.sh --repo . --query "auth token refresh" [--limit N]
|
|
17119
|
+
```
|
|
17120
|
+
|
|
17121
|
+
Output: `{query, results[{name, qualified_name, label, file, rank}], total, source}`. Use when the user names an **intent/concept** rather than an exact symbol — this is the first move in the Concept-to-Files recipe.
|
|
17122
|
+
|
|
17123
|
+
### Tests — coverage edges and untested surface
|
|
17124
|
+
|
|
17125
|
+
```bash
|
|
17126
|
+
scripts/tools/graph-tests.sh --repo . --symbol <name> # tests covering a symbol
|
|
17127
|
+
scripts/tools/graph-tests.sh --repo . --untested # exported symbols with no TESTS edge
|
|
17128
|
+
```
|
|
17129
|
+
|
|
17130
|
+
Output: `{symbol, tests[{test,file}], status, source}` or `{untested[{symbol,file}], total, truncated, source}`. Feeds coverage gaps for `init`/`testing-strategy`/`coverage`.
|
|
17131
|
+
|
|
17132
|
+
### Deps — real module/file import graph
|
|
17133
|
+
|
|
17134
|
+
```bash
|
|
17135
|
+
scripts/tools/graph-deps.sh --repo . [--file PATH]
|
|
17136
|
+
```
|
|
17137
|
+
|
|
17138
|
+
Output: `{imports[{src,dst}], total, truncated, source}` from actual `IMPORTS` edges (self-imports filtered). This is the auto-derived dependency graph behind `mermaid-from-graph.sh --diagram module-deps` and `architecture.md §9`.
|
|
17139
|
+
|
|
17140
|
+
### Hierarchy — class inheritance
|
|
17141
|
+
|
|
17142
|
+
```bash
|
|
17143
|
+
scripts/tools/graph-hierarchy.sh --repo . [--symbol <Class> | --derived <Base>]
|
|
17144
|
+
```
|
|
17145
|
+
|
|
17146
|
+
Output: `{edges[{child,parent}], status, source}`. `--derived` gives the blast radius of changing a base class.
|
|
17147
|
+
|
|
17148
|
+
### Errors — error-propagation paths
|
|
17149
|
+
|
|
17150
|
+
```bash
|
|
17151
|
+
scripts/tools/graph-errors.sh --repo . --symbol <name> # what it raises/throws
|
|
17152
|
+
scripts/tools/graph-errors.sh --repo . --type <ErrType> # who raises/throws that type
|
|
17153
|
+
```
|
|
17154
|
+
|
|
17155
|
+
Output: `{symbol, raises[...], status, source}` or `{type, raisers[...], status, source}`. `--type` drives fail-closed audits.
|
|
17156
|
+
|
|
17157
|
+
### Risk — pre-computed risk hotspots
|
|
17158
|
+
|
|
17159
|
+
```bash
|
|
17160
|
+
scripts/tools/graph-risk.sh --repo . [--min-complexity N]
|
|
17161
|
+
```
|
|
17162
|
+
|
|
17163
|
+
Output: `{risky[{symbol, file, complexity, flags}], total, truncated, source}` from the engine's pre-computed flags (`unguarded_recursion`, `recursion_in_loop`, `alloc_in_loop`, `linear_scan_in_loop`). High-signal input for `bughunt`/`deep-review` — the engine already found these.
|
|
17164
|
+
|
|
17165
|
+
### Generic — read-only escape hatch (all 20 edges / ~30 properties)
|
|
17166
|
+
|
|
17167
|
+
```bash
|
|
17168
|
+
scripts/tools/graph-query.sh --repo . --cypher 'MATCH (f)-[:WRITES]->(v) RETURN f.name, v.name LIMIT 50'
|
|
17169
|
+
scripts/tools/graph-query.sh --repo . --tool get_graph_schema --json '{}'
|
|
17170
|
+
```
|
|
17171
|
+
|
|
17172
|
+
Unlocks any edge type or node property without a purpose-built wrapper. Write verbs are rejected; stay inside the SAFE dialect set (above). Emits raw engine JSON.
|
|
17173
|
+
|
|
17043
17174
|
### Indexing / refreshing the gate marker
|
|
17044
17175
|
|
|
17045
17176
|
```bash
|
|
17046
17177
|
scripts/tools/graph-snapshot.sh --repo .
|
|
17047
17178
|
```
|
|
17048
17179
|
|
|
17049
|
-
Indexes the repo into the engine and writes the `draft/graph/schema.yaml` gate marker. It writes **no** graph data. Run during `draft init` and `draft graph`, or whenever the index should be refreshed.
|
|
17180
|
+
Indexes the repo into the engine and writes the `draft/graph/schema.yaml` gate marker (now including the `detect_changes` delta: `changed_files`/`impacted_symbols`). It writes **no** graph data. Run during `draft init` and `draft graph`, or whenever the index should be refreshed.
|
|
17050
17181
|
|
|
17051
17182
|
## Finding the Engine (Resolution + Usage Report)
|
|
17052
17183
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drafthq/draft",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Context-Driven Development for AI coding agents — install Draft into Claude Code, Cursor, Codex, or opencode.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"draft": "cli/bin/draft.js"
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
26
|
"test": "bash tests/test-cli.sh",
|
|
27
|
+
"version": "bash scripts/sync-version.sh && git add .claude-plugin/plugin.json .claude-plugin/marketplace.json web/index.html",
|
|
27
28
|
"prepublishOnly": "bash scripts/build-integrations.sh"
|
|
28
29
|
},
|
|
29
30
|
"repository": {
|
package/scripts/lib.sh
CHANGED
|
@@ -161,6 +161,16 @@ TOOLS=(
|
|
|
161
161
|
"graph-impact.sh"
|
|
162
162
|
"graph-callers.sh"
|
|
163
163
|
"graph-arch.sh"
|
|
164
|
+
# graph-tooling-v2: generic passthrough + purpose-built capability wrappers
|
|
165
|
+
"graph-query.sh"
|
|
166
|
+
"graph-snippet.sh"
|
|
167
|
+
"graph-search.sh"
|
|
168
|
+
"graph-tests.sh"
|
|
169
|
+
"graph-deps.sh"
|
|
170
|
+
"graph-hierarchy.sh"
|
|
171
|
+
"graph-errors.sh"
|
|
172
|
+
"graph-risk.sh"
|
|
173
|
+
"graph-traces.sh"
|
|
164
174
|
"validate-frontmatter.sh"
|
|
165
175
|
# Foundations hygiene/verification tools
|
|
166
176
|
"check-graph-usage-report.sh"
|