@drafthq/draft 3.7.2 → 5.0.1
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 +6 -3
- package/.claude-plugin/plugin.json +4 -2
- package/.cursor-plugin/plugin.json +4 -2
- package/LICENSE +1 -1
- package/README.md +7 -7
- package/bin/README.md +14 -13
- package/cli/src/cli.js +2 -2
- package/cli/src/installer.js +4 -2
- package/cli/src/lib/cursor-registry.js +2 -2
- package/cli/src/lib/graph.js +2 -1
- package/core/shared/condensation.md +8 -7
- package/core/shared/draft-context-loading.md +1 -1
- package/core/shared/graph-query.md +31 -23
- package/core/templates/architecture.md +1 -1
- package/integrations/agents/AGENTS.md +43 -34
- package/integrations/copilot/.github/copilot-instructions.md +43 -34
- package/package.json +7 -3
- package/scripts/fetch-memory-engine.sh +44 -11
- package/scripts/lib.sh +1 -1
- package/scripts/tools/_graph_queries.sh +28 -12
- package/scripts/tools/_lib.sh +38 -29
- package/scripts/tools/check-repo-size.sh +5 -1
- package/scripts/tools/cycle-detect.sh +11 -7
- package/scripts/tools/graph-callers.sh +1 -1
- package/scripts/tools/graph-impact.sh +63 -35
- package/scripts/tools/graph-init.sh +5 -10
- package/scripts/tools/graph-preflight.sh +6 -3
- package/scripts/tools/graph-query.sh +8 -7
- package/scripts/tools/graph-snapshot.sh +13 -24
- package/scripts/tools/graph-traces.sh +2 -2
- package/scripts/tools/hotspot-rank.sh +10 -1
- package/scripts/tools/mermaid-from-graph.sh +1 -1
- package/scripts/tools/okf-emit-catalog.sh +3 -0
- package/scripts/tools/okf-render-views.sh +6 -4
- package/scripts/tools/okf-validate.sh +5 -0
- package/scripts/tools/resolve-tools.sh +5 -3
- package/scripts/tools/scan-markers.sh +9 -1
- package/scripts/tools/verify-graph-binary.sh +14 -2
- package/skills/draft/intent-mapping.md +1 -1
- package/skills/implement/SKILL.md +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "draft-plugins",
|
|
3
3
|
"owner": {
|
|
4
|
-
"name": "
|
|
4
|
+
"name": "Mayur Pise",
|
|
5
|
+
"email": "mayur@getdraft.dev",
|
|
5
6
|
"url": "https://github.com/mayurpise"
|
|
6
7
|
},
|
|
7
8
|
"metadata": {
|
|
@@ -12,9 +13,11 @@
|
|
|
12
13
|
"name": "draft",
|
|
13
14
|
"source": "./",
|
|
14
15
|
"description": "Context-Driven Development: draft specs and plans before implementation. Structured workflows for features and fixes.",
|
|
15
|
-
"version": "
|
|
16
|
+
"version": "5.0.1",
|
|
16
17
|
"author": {
|
|
17
|
-
"name": "
|
|
18
|
+
"name": "Mayur Pise",
|
|
19
|
+
"email": "mayur@getdraft.dev",
|
|
20
|
+
"url": "https://github.com/mayurpise"
|
|
18
21
|
},
|
|
19
22
|
"homepage": "https://github.com/drafthq/draft",
|
|
20
23
|
"license": "MIT",
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "draft",
|
|
3
3
|
"description": "Context-Driven Development: draft specs and plans before implementation. Structured workflows for features and fixes.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "5.0.1",
|
|
5
5
|
"author": {
|
|
6
|
-
"name": "
|
|
6
|
+
"name": "Mayur Pise",
|
|
7
|
+
"email": "mayur@getdraft.dev",
|
|
8
|
+
"url": "https://github.com/mayurpise"
|
|
7
9
|
},
|
|
8
10
|
"homepage": "https://github.com/drafthq/draft",
|
|
9
11
|
"license": "MIT",
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
"name": "draft",
|
|
3
3
|
"displayName": "Draft",
|
|
4
4
|
"description": "Context-Driven Development: draft specs and plans before implementation. Structured workflows for features and fixes.",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "5.0.1",
|
|
6
6
|
"skills": "./skills/",
|
|
7
7
|
"agents": "./core/agents/",
|
|
8
8
|
"author": {
|
|
9
|
-
"name": "
|
|
9
|
+
"name": "Mayur Pise",
|
|
10
|
+
"email": "mayur@getdraft.dev",
|
|
11
|
+
"url": "https://github.com/mayurpise"
|
|
10
12
|
},
|
|
11
13
|
"homepage": "https://github.com/drafthq/draft",
|
|
12
14
|
"license": "MIT",
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -68,12 +68,12 @@ Each host installs the way that host actually loads extensions — no manual ste
|
|
|
68
68
|
|
|
69
69
|
| Host | `draft install …` | What it does |
|
|
70
70
|
|------|-------------------|--------------|
|
|
71
|
-
| **Claude Code** | `claude-code` | Registers the plugin via `claude plugin marketplace add` + `claude plugin install` (user scope). Restart Claude Code. |
|
|
72
|
-
| **Cursor** | `cursor` | Copies the plugin into `~/.cursor/plugins/local/draft/`, writes `.cursor-plugin/plugin.json`, registers `draft@draft-plugins` in Cursor's plugin registry, and enables it. Restart Cursor (or Developer: Reload Window). Existing installs upgrade with `draft install cursor --force`. |
|
|
73
|
-
| **Codex** | `codex` | Writes `./AGENTS.md`, which Codex reads automatically. |
|
|
74
|
-
| **opencode** | `opencode` | Writes `./AGENTS.md` + `~/.agents/skills/draft/`, both auto-discovered. |
|
|
71
|
+
| **Claude Code** | `claude-code` | Registers the plugin via `claude plugin marketplace add` + `claude plugin install` (default `--global` / user scope). Restart Claude Code. |
|
|
72
|
+
| **Cursor** | `cursor` | Default `--global`. Copies the plugin into `~/.cursor/plugins/local/draft/`, writes `.cursor-plugin/plugin.json`, registers `draft@draft-plugins` in Cursor's plugin registry, and enables it. Restart Cursor (or Developer: Reload Window). Existing installs upgrade with `draft install cursor --force`. |
|
|
73
|
+
| **Codex** | `codex` | Default `--project`. Writes `./AGENTS.md`, which Codex reads automatically. |
|
|
74
|
+
| **opencode** | `opencode` | Default `--project`. Writes `./AGENTS.md` + `~/.agents/skills/draft/`, both auto-discovered. |
|
|
75
75
|
|
|
76
|
-
Flags: `--global` / `--project` to pick scope, `--dry-run` to preview, `--force` to overwrite, `--no-graph` to skip the graph-engine fetch.
|
|
76
|
+
Flags: `--global` / `--project` to pick scope (`--global` is the default for `claude-code` and `cursor`; `--project` is the default for `codex` and `opencode`), `--dry-run` to preview, `--force` to overwrite, `--no-graph` to skip the graph-engine fetch.
|
|
77
77
|
|
|
78
78
|
Then, in Claude Code (after restarting):
|
|
79
79
|
|
|
@@ -164,7 +164,7 @@ The graph powers `/draft:graph` and `/draft:impact`, enriches `/draft:bughunt` a
|
|
|
164
164
|
|
|
165
165
|
### Deterministic helper tools
|
|
166
166
|
|
|
167
|
-
Skills also call into **shell helpers** under `scripts/tools/` for mechanical work — git metadata, file classification, test-framework detection, hotspot ranking, freshness checks, ADR indexing, and live graph queries (`graph-callers.sh`, `graph-impact.sh`, `hotspot-rank.sh`, `cycle-detect.sh`, `mermaid-from-graph.sh`). All emit JSON or markdown
|
|
167
|
+
Skills also call into **shell helpers** under `scripts/tools/` for mechanical work — git metadata, file classification, test-framework detection, hotspot ranking, freshness checks, ADR indexing, and live graph queries (`graph-callers.sh`, `graph-impact.sh`, `hotspot-rank.sh`, `cycle-detect.sh`, `mermaid-from-graph.sh`). All emit JSON or markdown and follow a uniform exit-code contract. Graph wrappers fail loud: shapeless `{}` (no `.rows` array) is `source:"unavailable"` with a non-zero exit, not a measured empty result.
|
|
168
168
|
|
|
169
169
|
---
|
|
170
170
|
|
|
@@ -270,7 +270,7 @@ Each layer narrows the solution space. By the time AI writes code, decisions are
|
|
|
270
270
|
|
|
271
271
|
---
|
|
272
272
|
|
|
273
|
-
<p align="center">MIT License · Graph engine: <a href="https://github.com/DeusData/codebase-memory-mcp" target="_blank" rel="noopener noreferrer">codebase-memory-mcp</a> by <a href="https://github.com/DeusData" target="_blank" rel="noopener noreferrer">DeusData</a></p>
|
|
273
|
+
<p align="center">MIT License · Created & maintained by <a href="https://www.linkedin.com/in/mayurpise/" target="_blank" rel="noopener noreferrer">Mayur Pise</a> · Graph engine: <a href="https://github.com/DeusData/codebase-memory-mcp" target="_blank" rel="noopener noreferrer">codebase-memory-mcp</a> by <a href="https://github.com/DeusData" target="_blank" rel="noopener noreferrer">DeusData</a></p>
|
|
274
274
|
|
|
275
275
|
<p align="center">
|
|
276
276
|
<strong>Credits:</strong> Inspired by <a href="https://github.com/gemini-cli-extensions/conductor">gemini-cli-extensions/conductor</a>
|
package/bin/README.md
CHANGED
|
@@ -17,7 +17,7 @@ This installs the binary to the **Draft-managed location**:
|
|
|
17
17
|
~/.cache/draft/bin/codebase-memory-mcp
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
The fetch script picks the right release archive for the host OS/arch, verifies its SHA-256 against the
|
|
20
|
+
The fetch script picks the right release archive for the host OS/arch, verifies its SHA-256 (against hashes pinned in the script for the default version, else against the release's `checksums.txt`), extracts it, and installs it there. An existing install is kept only when its version matches the requested one, so a pin bump upgrades it. Downloads pin `curl --proto '=https' --proto-redir '=https'` so a compromised redirect cannot downgrade to HTTP. `draft install claude-code` / `draft install cursor` run this automatically (best-effort, network-gated); skip it with `--no-graph`.
|
|
21
21
|
|
|
22
22
|
## Resolution order
|
|
23
23
|
|
|
@@ -39,10 +39,10 @@ Set `DRAFT_MEMORY_DISABLE=1` to force the engine off. All graph-backed skills an
|
|
|
39
39
|
## How tools use it
|
|
40
40
|
|
|
41
41
|
Shell helpers under `scripts/tools/` drive the engine via its CLI
|
|
42
|
-
(`codebase-memory-mcp cli <tool
|
|
42
|
+
(`codebase-memory-mcp cli <tool>`, JSON args on stdin) and shape results into Draft's
|
|
43
43
|
contracts — see `hotspot-rank.sh`, `cycle-detect.sh`, `mermaid-from-graph.sh`,
|
|
44
44
|
and `verify-graph-binary.sh`. The shared wrappers (`memory_cli`,
|
|
45
|
-
`memory_ensure_index`, `
|
|
45
|
+
`memory_ensure_index`, `memory_index_bounded`) live in `_lib.sh`.
|
|
46
46
|
|
|
47
47
|
## Snapshot artifacts
|
|
48
48
|
|
|
@@ -50,9 +50,9 @@ and `verify-graph-binary.sh`. The shared wrappers (`memory_cli`,
|
|
|
50
50
|
|
|
51
51
|
| Artifact | Content |
|
|
52
52
|
|----------|---------|
|
|
53
|
-
| `schema.yaml` | Engine
|
|
53
|
+
| `schema.yaml` | Engine metadata and point-of-index node/edge counts (gates graph use). No machine- or run-specific fields, so it only changes when the engine or the codebase does. |
|
|
54
54
|
|
|
55
|
-
Structural graph data (architecture, hotspots, module deps, service routes) is queried **live** from the `codebase-memory-mcp` engine — either via the wrapper scripts under `scripts/tools/` (`graph-callers.sh`, `graph-impact.sh`, `hotspot-rank.sh`, `cycle-detect.sh`, `mermaid-from-graph.sh`) or
|
|
55
|
+
Structural graph data (architecture, hotspots, module deps, service routes) is queried **live** from the `codebase-memory-mcp` engine — either via the wrapper scripts under `scripts/tools/` (`graph-callers.sh`, `graph-impact.sh`, `hotspot-rank.sh`, `cycle-detect.sh`, `mermaid-from-graph.sh`), or, for any other read-only engine tool, `graph-query.sh --tool <name> --json '{...}'`.
|
|
56
56
|
|
|
57
57
|
## Offline / air-gapped distributions
|
|
58
58
|
|
|
@@ -68,22 +68,23 @@ Draft's differentiator depends on a binary published by a third party ([DeusData
|
|
|
68
68
|
|
|
69
69
|
| Property | Status |
|
|
70
70
|
|---|---|
|
|
71
|
-
| Version pinned | Yes — `DEFAULT_VERSION` in `scripts/fetch-memory-engine.sh`. Bumps are deliberate commits, never floating. `CMM_VERSION` overrides per-install. |
|
|
72
|
-
| SHA-256 verified | Yes
|
|
73
|
-
| Missing checksum | **
|
|
71
|
+
| Version pinned | Yes — `DEFAULT_VERSION` in `scripts/fetch-memory-engine.sh`. Bumps are deliberate commits, never floating. `CMM_VERSION` overrides per-install. An install at another version is replaced on the next fetch, and `verify-graph-binary.sh` / `graph-preflight.sh` warn when the resolved engine (e.g. one on `$PATH`) is off-pin. |
|
|
72
|
+
| SHA-256 verified | Yes. The default version's four platform archives are checked against hashes **pinned in the script** (a replaced release asset fails even if the release's own `checksums.txt` agrees). Other versions are checked against the release's `checksums.txt` when it lists the archive. A **mismatch is always fatal.** |
|
|
73
|
+
| Missing checksum | Applies only to non-default versions: **warns and installs by default.** Set `DRAFT_STRICT_VERIFY=1` to make an unverifiable download fatal instead. |
|
|
74
74
|
| Signature / attestation | **No.** There is no code signing or SLSA provenance today. Verification is checksum-only. |
|
|
75
75
|
| Source available | Yes — the engine is open source at [DeusData/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp). |
|
|
76
76
|
| Reproducible build | Not verified by Draft. We check the archive matches the publisher's checksum, not that the checksum matches the source. |
|
|
77
77
|
|
|
78
|
-
Be explicit about the residual risk: a checksum proves the download matches what the publisher released. It does not prove the publisher released what the source says.
|
|
78
|
+
Be explicit about the residual risk: a pinned checksum proves the download matches what the publisher released when Draft pinned it. It does not prove the publisher released what the source says.
|
|
79
79
|
|
|
80
80
|
### What the engine does at runtime
|
|
81
81
|
|
|
82
82
|
- Reads the repository you point it at and writes a SQLite graph under its own cache.
|
|
83
|
-
- Runs entirely locally. No API key, no telemetry endpoint, no outbound calls during indexing or querying.
|
|
84
|
-
-
|
|
83
|
+
- Runs entirely locally as Draft invokes it (`cli` mode). No API key, no telemetry endpoint, no outbound calls during indexing or querying — verified under `strace` for `index_repository` and queries on 0.9.0 (zero `connect()` calls, no spawned `curl`).
|
|
84
|
+
- The binary does embed an update checker (`api.github.com/.../releases/latest`) and `update` / `install` subcommands for its own MCP-server workflow. Draft never runs the server or those subcommands.
|
|
85
|
+
- Draft uses the network exactly once, in `fetch-memory-engine.sh`, to download the release archive.
|
|
85
86
|
|
|
86
|
-
Draft invokes it only through `codebase-memory-mcp cli <tool
|
|
87
|
+
Draft invokes it only through `codebase-memory-mcp cli <tool>` with JSON args on stdin (see `_lib.sh:memory_cli`). It is never given credentials and never writes into your source tree.
|
|
87
88
|
|
|
88
89
|
### If you cannot run an unvetted binary
|
|
89
90
|
|
|
@@ -97,7 +98,7 @@ Three supported postures, in increasing strictness:
|
|
|
97
98
|
|
|
98
99
|
The dependency is bounded by design, which is what makes this survivable:
|
|
99
100
|
|
|
100
|
-
- **The interface is small.** Draft consumes a documented CLI (`cli <tool
|
|
101
|
+
- **The interface is small.** Draft consumes a documented CLI (`cli <tool>`, JSON on stdin), not a library. The entire coupling lives in `scripts/tools/_lib.sh` (`memory_cli`, `memory_ensure_index`, `memory_index_bounded`) and `_graph_queries.sh`. Swapping engines means reimplementing those, not rewriting skills.
|
|
101
102
|
- **Skills never call the engine directly.** They call `graph-*.sh` wrappers, all of which already fail loud with `source: "unavailable"`. An engine that disappears degrades the product; it does not break it.
|
|
102
103
|
- **Pinning buys time.** A stalled upstream keeps working at the pinned version; only new language support would be lost.
|
|
103
104
|
- **The graph contract is replaceable.** The queries are ordinary Cypher-shaped structural lookups (callers, callees, fan-in, cycles, routes) over a tree-sitter/LSP index — reproducible on another indexer.
|
package/cli/src/cli.js
CHANGED
|
@@ -47,8 +47,8 @@ Usage:
|
|
|
47
47
|
Hosts: ${hosts.map((h) => h.id).join(', ')}
|
|
48
48
|
|
|
49
49
|
Flags:
|
|
50
|
-
--global Install to the user-level location (default for cursor)
|
|
51
|
-
--project Install into the current project (default for
|
|
50
|
+
--global Install to the user-level location (default for claude-code, cursor)
|
|
51
|
+
--project Install into the current project (default for codex, opencode)
|
|
52
52
|
--dry-run Print planned writes without touching disk
|
|
53
53
|
--no-graph Skip the knowledge-graph engine fetch
|
|
54
54
|
--force Overwrite an existing target
|
package/cli/src/installer.js
CHANGED
|
@@ -15,9 +15,11 @@ const CHECK_TIMEOUT_MS = 10000;
|
|
|
15
15
|
const USE_SHELL = process.platform === 'win32';
|
|
16
16
|
|
|
17
17
|
function hasBinary(name) {
|
|
18
|
-
//
|
|
18
|
+
// Windows `.cmd` shims (shell: true) report a missing binary as status 127
|
|
19
|
+
// with no `error`. Treat any spawn error or non-zero status as absent.
|
|
19
20
|
const r = spawnSync(name, ['--version'], { stdio: 'ignore', timeout: CHECK_TIMEOUT_MS, shell: USE_SHELL });
|
|
20
|
-
|
|
21
|
+
if (r.error) return false;
|
|
22
|
+
return r.status === 0;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
// Per-step ceiling so a stalled network op (e.g. the `git clone` behind
|
|
@@ -78,7 +78,7 @@ function registerCursorPlugin(opts) {
|
|
|
78
78
|
// --- installed_plugins.json: merge our key, preserve installedAt on upgrade. ---
|
|
79
79
|
const ip = readJson(paths.ipPath, { version: 2, plugins: {} });
|
|
80
80
|
if (typeof ip.version !== 'number') ip.version = 2;
|
|
81
|
-
if (!ip.plugins || typeof ip.plugins !== 'object') ip.plugins = {};
|
|
81
|
+
if (!ip.plugins || typeof ip.plugins !== 'object' || Array.isArray(ip.plugins)) ip.plugins = {};
|
|
82
82
|
const existing = Array.isArray(ip.plugins[PLUGIN_KEY]) ? ip.plugins[PLUGIN_KEY][0] : null;
|
|
83
83
|
const installedAt = existing && existing.installedAt ? existing.installedAt : now;
|
|
84
84
|
ip.plugins[PLUGIN_KEY] = [
|
|
@@ -93,7 +93,7 @@ function registerCursorPlugin(opts) {
|
|
|
93
93
|
|
|
94
94
|
// --- settings.json: flip our enabledPlugins flag, preserve everything else. ---
|
|
95
95
|
const settings = readJson(paths.settingsPath, {});
|
|
96
|
-
if (!settings.enabledPlugins || typeof settings.enabledPlugins !== 'object') {
|
|
96
|
+
if (!settings.enabledPlugins || typeof settings.enabledPlugins !== 'object' || Array.isArray(settings.enabledPlugins)) {
|
|
97
97
|
settings.enabledPlugins = {};
|
|
98
98
|
}
|
|
99
99
|
settings.enabledPlugins[PLUGIN_KEY] = true;
|
package/cli/src/lib/graph.js
CHANGED
|
@@ -14,7 +14,8 @@ function fetchGraph() {
|
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
16
|
log.note('Fetching knowledge-graph engine (best-effort)...');
|
|
17
|
-
const
|
|
17
|
+
const timeout = Number(process.env.DRAFT_INSTALL_TIMEOUT_MS) || 300000;
|
|
18
|
+
const result = spawnSync('bash', [script], { stdio: 'inherit', timeout });
|
|
18
19
|
if (result.status !== 0) {
|
|
19
20
|
log.warn('Graph engine fetch skipped (offline or unsupported platform) — features degrade gracefully.');
|
|
20
21
|
}
|
|
@@ -24,7 +24,7 @@ Any skill that mutates `architecture.md` should execute this subroutine afterwar
|
|
|
24
24
|
| Input | Path | Description |
|
|
25
25
|
|-------|------|-------------|
|
|
26
26
|
| architecture.md | `draft/architecture.md` | Comprehensive human-readable engineering reference (source of truth) |
|
|
27
|
-
|
|
|
27
|
+
| Architecture view | `scripts/tools/graph-arch.sh --repo .` | Live graph metrics for tier computation (optional — skip when `draft/graph/schema.yaml` is absent) |
|
|
28
28
|
|
|
29
29
|
## Outputs
|
|
30
30
|
|
|
@@ -37,11 +37,12 @@ Any skill that mutates `architecture.md` should execute this subroutine afterwar
|
|
|
37
37
|
|
|
38
38
|
## Target Size
|
|
39
39
|
|
|
40
|
-
Compute tier from `
|
|
40
|
+
Compute tier from the live architecture view (the same metrics as `/draft:init` Step 1.4.5 — `schema.yaml` carries only counts, not these):
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
ARCH=$("$DRAFT_TOOLS/graph-arch.sh" --repo .) (DRAFT_TOOLS: resolver below)
|
|
43
|
+
M = $ARCH | jq '.packages | length' (modules)
|
|
44
|
+
F = $ARCH | jq '[.node_labels[] | select(.label=="Function" or .label=="Method") | .count] | add // 0' (functions + methods)
|
|
45
|
+
P = $ARCH | jq '.routes | length' (routes / RPCs)
|
|
45
46
|
|
|
46
47
|
| Tier | Label | Condition | Budget |
|
|
47
48
|
|------|--------|----------------------------------------|---------------|
|
|
@@ -51,7 +52,7 @@ Compute tier from `draft/graph/schema.yaml` after graph build:
|
|
|
51
52
|
| 4 | large | M≤100 AND F≤5000 AND P≤500 | 400–600 lines |
|
|
52
53
|
| 5 | XL | M>100 OR F>5000 OR P>500 | 600–900 lines |
|
|
53
54
|
|
|
54
|
-
If `schema.yaml` does not exist: default to tier 2 (180–280 lines).
|
|
55
|
+
If `schema.yaml` does not exist (no graph) or `graph-arch.sh` reports `source: unavailable`: default to tier 2 (180–280 lines).
|
|
55
56
|
|
|
56
57
|
- Below tier minimum: incomplete condensation — ensure all sections are represented
|
|
57
58
|
- Above tier maximum: insufficient compression — apply prioritization rules below
|
|
@@ -171,7 +172,7 @@ Before writing `draft/.ai-context.md`, verify:
|
|
|
171
172
|
- [ ] No references to `architecture.md` (file must be self-contained)
|
|
172
173
|
- [ ] All invariants from architecture.md are preserved
|
|
173
174
|
- [ ] Extension cookbooks are complete (an agent can follow them without other files)
|
|
174
|
-
- [ ] Output is within tier budget bounds (compute from
|
|
175
|
+
- [ ] Output is within tier budget bounds (compute from `graph-arch.sh` or default tier 2)
|
|
175
176
|
- [ ] GRAPH:HOTSPOTS present (or note "No hotspot data available" if graph absent)
|
|
176
177
|
- [ ] GRAPH:CYCLES present ("None ✓" or cycle list; or note if graph absent)
|
|
177
178
|
- [ ] GRAPH:MODULE-HOTSPOTS present for tier ≥ 3 (or note if no hotspot data)
|
|
@@ -71,7 +71,7 @@ If `draft/graph/schema.yaml` exists, the project has automated graph analysis da
|
|
|
71
71
|
|
|
72
72
|
| File | Purpose | Content |
|
|
73
73
|
|------|---------|---------|
|
|
74
|
-
| `draft/graph/schema.yaml` | Gate marker (engine
|
|
74
|
+
| `draft/graph/schema.yaml` | Gate marker (engine metadata + point-of-index counts); presence gates graph use | YAML, ~10 lines |
|
|
75
75
|
|
|
76
76
|
Note: `.ai-context.md` embeds a condensed graph summary (`GRAPH:MODULES`, `GRAPH:HOTSPOTS`, `GRAPH:CYCLES`) for first-pass structural ground truth. Deep structural data is queried live from the engine (see Live structural queries below).
|
|
77
77
|
|
|
@@ -103,7 +103,7 @@ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}
|
|
|
103
103
|
|---|---|---|
|
|
104
104
|
| `bash "$DRAFT_TOOLS/hotspot-rank.sh" [--top N]` | complexity-weighted hotspots | Emits `{hotspots:[],source:"unavailable"}` and exits 2 |
|
|
105
105
|
| `bash "$DRAFT_TOOLS/cycle-detect.sh"` | call cycles | Emits `{cycles:[],source:"unavailable"}` and exits 2 |
|
|
106
|
-
| `bash "$DRAFT_TOOLS/mermaid-from-graph.sh" [--diagram module-deps\|co-change\|proto-map]` | diagram text |
|
|
106
|
+
| `bash "$DRAFT_TOOLS/mermaid-from-graph.sh" [--diagram module-deps\|co-change\|proto-map]` | diagram text | Unavailable stub (`graph not built`) vs empty-graph stub (`no edges`); both exit 2 |
|
|
107
107
|
| `bash "$DRAFT_TOOLS/graph-callers.sh" --symbol N [--transitive[=N]] [--prod-only] [--qualified]` | callers | `{callers:[],status:"unavailable",source:"unavailable"}`, exit 2 |
|
|
108
108
|
| `bash "$DRAFT_TOOLS/graph-snippet.sh" --qualified N` | verified source + caller/callee counts | `{status:"unavailable",source:"unavailable"}`, exit 2 |
|
|
109
109
|
| `bash "$DRAFT_TOOLS/graph-search.sh" --query "STR" [--limit N]` | semantic/ranked search | `{results:[],source:"unavailable"}`, exit 2 |
|
|
@@ -115,7 +115,7 @@ DRAFT_TOOLS="${DRAFT_PLUGIN_ROOT:-$(cat ~/.cache/draft/plugin-root 2>/dev/null)}
|
|
|
115
115
|
| `bash "$DRAFT_TOOLS/graph-query.sh" (--cypher STR \| --tool NAME --json '{...}')` | generic read-only passthrough | `{source:"unavailable"}`, exit 2 |
|
|
116
116
|
| `bash "$DRAFT_TOOLS/graph-traces.sh" ingest --file F --experimental` | runtime traces (experimental write) | `{source:"unavailable"}`, exit 2 |
|
|
117
117
|
|
|
118
|
-
For
|
|
118
|
+
For an engine tool without a dedicated wrapper, use the read-only passthrough `graph-query.sh --repo . --tool <name> --json '{...}'` (project injected, write tools refused, `source:"unavailable"` on failure). Never call the engine binary directly — that skips engine resolution, the index refresh before each query, and the fail-loud contract.
|
|
119
119
|
|
|
120
120
|
### Capability wrappers & dialect limits (graph-tooling-v2)
|
|
121
121
|
|
|
@@ -123,8 +123,9 @@ All Cypher lives in `scripts/tools/_graph_queries.sh` (the single source of quer
|
|
|
123
123
|
truth). Wrappers are thin arg-parse → builder → fail-loud JSON. Three contracts
|
|
124
124
|
matter when consuming them:
|
|
125
125
|
|
|
126
|
-
**Fail-loud status.** Symbol-scoped wrappers (`graph-callers`, `graph-
|
|
127
|
-
`graph-tests --symbol`, `graph-hierarchy --symbol/--derived`,
|
|
126
|
+
**Fail-loud status.** Symbol-scoped wrappers (`graph-callers`, `graph-impact`,
|
|
127
|
+
`graph-snippet`, `graph-tests --symbol`, `graph-hierarchy --symbol/--derived`,
|
|
128
|
+
`graph-errors`)
|
|
128
129
|
emit a `status` field that distinguishes the three real outcomes — never read a
|
|
129
130
|
bare `[]` as a confirmed true negative:
|
|
130
131
|
|
|
@@ -133,9 +134,11 @@ bare `[]` as a confirmed true negative:
|
|
|
133
134
|
| `ok` | node found, edges returned |
|
|
134
135
|
| `no-edges` | node exists but has no matching edge (a *real* negative) |
|
|
135
136
|
| `no-match` | the named symbol was not found at all (check the name / try `--qualified`) |
|
|
136
|
-
| `unavailable` | engine could not be resolved (exit 2) |
|
|
137
|
+
| `unavailable` | engine could not be resolved, or engine returned shapeless/non-row JSON (exit 2) |
|
|
137
138
|
|
|
138
|
-
**
|
|
139
|
+
**Shapeless JSON is unavailable.** `gq_run` requires `has("rows") and (.rows|type=="array")`. A bare `{}` (or any object without a `.rows` array) is not a measured empty result — wrappers emit `source:"unavailable"` and a non-zero exit. Do not read `{}` as "no callers / no cycles / no edges". `graph-impact`, `graph-callers`, and `mermaid-from-graph` also require their tool-shaped object; a failed snapshot refresh does not rewrite `schema.yaml`.
|
|
140
|
+
|
|
141
|
+
**Verified engine param shapes** (engine v0.9.0 — the runtime source of truth is
|
|
139
142
|
`get_graph_schema`; do not hardcode a property set):
|
|
140
143
|
|
|
141
144
|
```bash
|
|
@@ -148,13 +151,18 @@ get_graph_schema '{"project":P}' # → {node_labels:[{label,count,properties}
|
|
|
148
151
|
|
|
149
152
|
**Cypher dialect — keep queries inside the SAFE set:**
|
|
150
153
|
|
|
151
|
-
- ✅ SAFE:
|
|
152
|
-
`
|
|
153
|
-
`[:
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
- ✅ SAFE: `=`, `<>`/`!=`, `<`, `>`, `<=`, `>=` against a literal; `STARTS WITH`,
|
|
155
|
+
`NOT x STARTS WITH`, `AND`, `OR`; explicit and variable-length patterns
|
|
156
|
+
(`[:R*1..3]`, fixed depth `[:R*2..2]`); relationship-type alternation `[:A|B]`;
|
|
157
|
+
`coalesce()`; `DISTINCT`; `count(x)`, `count(DISTINCT x)`; `WITH`-grouping
|
|
158
|
+
aggregation.
|
|
159
|
+
- ❌ UNSAFE: comparing one property against another (`a.x < b.x`), `NOT EXISTS(...)`,
|
|
160
|
+
`NOT (pattern)`, path variables (`p=(...)`, `length(p)`) — all rejected; and
|
|
161
|
+
multi-pattern joins (`MATCH (a)…, (b)…`), which parse but ignore `RETURN` and
|
|
162
|
+
`LIMIT`. `graph-query.sh --cypher` returns the engine's raw error, not a silent
|
|
157
163
|
empty — but the builders never emit these forms.
|
|
164
|
+
- ⚠️ `LIMIT` applies before `DISTINCT`: `RETURN DISTINCT … LIMIT n` can return
|
|
165
|
+
fewer than n rows while more exist. Judge truncation on raw rows.
|
|
158
166
|
|
|
159
167
|
**Caveats consumers must respect:**
|
|
160
168
|
|
|
@@ -189,22 +197,22 @@ The only committed file is the gate marker:
|
|
|
189
197
|
|
|
190
198
|
| File | Role |
|
|
191
199
|
|------|------|
|
|
192
|
-
| `draft/graph/schema.yaml` | Engine
|
|
200
|
+
| `draft/graph/schema.yaml` | Engine metadata and point-of-index counts (provenance, not authoritative). Carries **no graph data**. Its presence is the **gate** (see Pre-Check) — it signals the engine is wired for this repo. Written by `scripts/tools/graph-snapshot.sh`. |
|
|
193
201
|
|
|
194
|
-
All structural data is obtained live
|
|
202
|
+
All structural data is obtained live through the query-tool wrappers under `scripts/tools/`; `graph-query.sh --tool` covers every read-only engine tool that has no dedicated wrapper. The wrappers refresh the repo's index in the engine's own cache before each query, so no committed files are required.
|
|
195
203
|
|
|
196
204
|
### How skills query (engine is the interface; jq is optional)
|
|
197
205
|
|
|
198
|
-
- **The engine is the query
|
|
206
|
+
- **The engine is the query; the wrappers are the interface.** Every wrapper drives the engine's CLI and returns JSON. There is no other query surface.
|
|
199
207
|
- **Prefer the wrappers — they resolve the engine for you.** `graph-arch.sh` (architecture view: packages/routes/layers/hotspots), `graph-callers.sh`, `hotspot-rank.sh`, `graph-impact.sh`, `cycle-detect.sh`, `mermaid-from-graph.sh` return already-shaped JSON. The engine binary is usually **not on `$PATH`** (it lives under `~/.cache/draft/bin/`); the wrappers locate it via `_lib.sh:find_memory_bin`, so a skill using a wrapper needs no resolution step.
|
|
200
|
-
- **
|
|
208
|
+
- **Tools without a dedicated wrapper go through `graph-query.sh`:** `"$DRAFT_TOOLS/graph-query.sh" --repo . --tool search_code --json '{"pattern":"..."}'` (likewise `trace_path`, `get_graph_schema`, `index_status`). `search_graph` has its own wrapper, `graph-search.sh`.
|
|
201
209
|
- **`jq` is not a query tool — it only trims output.** Reach for it solely to slice a *large* response (chiefly the `get_architecture` blob) down to the field you need, for token economy. The agent can read raw JSON directly; jq is an optimization, not a requirement. Don't pipe wrapper output through jq unless you genuinely need a sub-field.
|
|
202
210
|
|
|
203
211
|
The engine uses a **unified, language-agnostic** node model — `Function`, `Method`, `Class`, `Module`, `File`, `Folder`, `Route`, `Section`, `Variable` (language is inferred from file extension) — and edges `CALLS`, `DEFINES`, `CONTAINS_FILE`, `IMPORTS`, `HTTP_CALLS`, `FILE_CHANGES_WITH`, `SEMANTICALLY_RELATED`, `SIMILAR_TO`. Each node carries `file_path` + `start_line`/`end_line` and rich `properties` (complexity, signature, parent_class), and the engine exposes full-text (`search_code`) and semantic search — none of which a committed snapshot reproduced.
|
|
204
212
|
|
|
205
213
|
## Query Tools
|
|
206
214
|
|
|
207
|
-
Live queries go through the shell tools under `scripts/tools/`, which drive the engine and shape results into stable JSON. Each tool resolves the engine (see Finding the Engine), indexes the repo on demand, and emits `source: "memory-graph"` on success or `source: "unavailable"` (non-zero exit) when the engine cannot be resolved. Set `DRAFT_MEMORY_DISABLE=1` to force the engine off; all tools then degrade
|
|
215
|
+
Live queries go through the shell tools under `scripts/tools/`, which drive the engine and shape results into stable JSON. Each tool resolves the engine (see Finding the Engine), indexes the repo on demand, and emits `source: "memory-graph"` on success or `source: "unavailable"` (non-zero exit) when the engine cannot be resolved **or returns shapeless JSON** (missing `.rows` array). Set `DRAFT_MEMORY_DISABLE=1` to force the engine off; all tools then degrade to `unavailable` rather than inventing empty results.
|
|
208
216
|
|
|
209
217
|
### Callers — who calls this function?
|
|
210
218
|
|
|
@@ -217,11 +225,11 @@ Output: `{symbol, callers[{name, file}], source}`. Use when enumerating call sit
|
|
|
217
225
|
### Impact — blast radius of a file or symbol
|
|
218
226
|
|
|
219
227
|
```bash
|
|
220
|
-
"$DRAFT_TOOLS/graph-impact.sh" --repo . --file <path> #
|
|
221
|
-
"$DRAFT_TOOLS/graph-impact.sh" --repo . --symbol <name> # transitive callers of a function
|
|
228
|
+
"$DRAFT_TOOLS/graph-impact.sh" --repo . --file <path> # dependents of a file: its symbols' callers + its importers
|
|
229
|
+
"$DRAFT_TOOLS/graph-impact.sh" --repo . --symbol <name> # dependents (transitive callers) of a function
|
|
222
230
|
```
|
|
223
231
|
|
|
224
|
-
Output: `{target, kind, impacted[{name, file, hop}], source}`. Use when sizing risk before modifying a file or symbol, especially high-fan-in hotspots.
|
|
232
|
+
Output: `{target, kind, impacted[{name, file, qualified, hop}], downstream_files, affected_modules, max_depth, by_category{code,test}, status, truncated, source}`. `impacted` lists each dependent once at its nearest hop (default depth 3), capped at 200 with `truncated:true`; the aggregates always cover the full set. `status` is `ok`, `no-edges` (target known, nothing depends on it), or `no-match` (target unknown to the graph — check the path). Use when sizing risk before modifying a file or symbol, especially high-fan-in hotspots.
|
|
225
233
|
|
|
226
234
|
### Hotspots — fan-in ranking
|
|
227
235
|
|
|
@@ -332,7 +340,7 @@ Unlocks any edge type or node property without a purpose-built wrapper. Write ve
|
|
|
332
340
|
"$DRAFT_TOOLS/graph-snapshot.sh" --repo .
|
|
333
341
|
```
|
|
334
342
|
|
|
335
|
-
Indexes the repo into the engine and writes the `draft/graph/schema.yaml` gate marker
|
|
343
|
+
Indexes the repo into the engine and writes the `draft/graph/schema.yaml` gate marker, and prints the `detect_changes` delta (`changed_files`/`impacted_symbols`) without committing it. It writes **no** graph data. Run during `/draft:init` and `/draft:graph`, or whenever the index should be refreshed.
|
|
336
344
|
|
|
337
345
|
## Finding the Engine (Resolution + Usage Report)
|
|
338
346
|
|
|
@@ -371,6 +379,6 @@ The engine indexes C/C++, Go, Python, TypeScript/JS, and more (tree-sitter, 159
|
|
|
371
379
|
| Scenario | Behavior |
|
|
372
380
|
|----------|----------|
|
|
373
381
|
| No engine resolvable (or `DRAFT_MEMORY_DISABLE=1`) | Skip graph indexing in init; all skills proceed without graph data; tools emit `source: unavailable` |
|
|
374
|
-
| Engine present but a query fails |
|
|
382
|
+
| Engine present but a query fails, or returns shapeless `{}` | Treat as unavailable — never as a true-negative empty result; skills proceed without graph data |
|
|
375
383
|
| `draft/graph/schema.yaml` exists | Engine is wired — use live query tools as needed during the run |
|
|
376
|
-
| Engine index out of date |
|
|
384
|
+
| Engine index out of date | Every wrapper re-indexes incrementally (content-based, git-aware) before it queries — ~0.1 s on an unchanged repo — so live answers track the working tree, including the run's own edits. `graph-snapshot.sh` (or init) also refreshes the `schema.yaml` marker. |
|
|
@@ -29,7 +29,7 @@ graph:
|
|
|
29
29
|
cpp: "{high}"
|
|
30
30
|
go: "{approximate | high}"
|
|
31
31
|
stats:
|
|
32
|
-
modules: "{N from
|
|
32
|
+
modules: "{N from engine: get_architecture .packages}"
|
|
33
33
|
edges: "{total_edges from engine: get_architecture .edges}"
|
|
34
34
|
hotspots: "{N}"
|
|
35
35
|
notes: "{explicit fidelity summary from engine: get_architecture .languages/.packages}"
|