@nanonets/graft 0.1.0 → 0.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/README.md CHANGED
@@ -14,7 +14,7 @@
14
14
  <a href="https://nodejs.org"><img src="https://img.shields.io/node/v/%40nanonets%2Fgraft?style=for-the-badge&logo=nodedotjs&logoColor=white" /></a>
15
15
  <img src="https://img.shields.io/badge/TypeScript-strict-3178C6?style=for-the-badge&logo=typescript&logoColor=white" />
16
16
  <img src="https://img.shields.io/badge/License-MIT-20C997?style=for-the-badge" />
17
- <img src="https://img.shields.io/badge/runs-100%25%20local-546FFF?style=for-the-badge&logo=ollama&logoColor=white" />
17
+ <img src="https://img.shields.io/badge/telemetry-none-546FFF?style=for-the-badge" />
18
18
  </p>
19
19
 
20
20
  <!-- placeholder: numbers pending a committed benchmark run, see Benchmark below -->
@@ -26,7 +26,7 @@
26
26
 
27
27
  ```mermaid
28
28
  flowchart LR
29
- A["Your code"] -->|"graft init"| B[".context/<br/>a graph of linked<br/>markdown nodes"]
29
+ A["Your code"] -->|"graft build --deep"| B["graft/<br/>a graph of linked<br/>markdown nodes"]
30
30
  B -->|"git commit"| C[("your repo")]
31
31
  C -->|"git clone"| D["teammate + their agent"]
32
32
  D -->|"reads the graph first"| E["starts already knowing<br/>how the repo fits together"]
@@ -37,10 +37,13 @@ flowchart LR
37
37
  ## Quick start
38
38
 
39
39
  ```bash
40
- npx @nanonets/graft init
41
- # builds .context/ from your code, one node per system, API, or concept
40
+ export OPENROUTER_API_KEY=sk-or-...
41
+ # the summaries are LLM-written — get a key at https://openrouter.ai/keys
42
42
 
43
- git add .context && git commit -m "add context graph"
43
+ npx @nanonets/graft build --deep
44
+ # builds graft/ from your code, one node per system, API, or concept
45
+
46
+ git add graft && git commit -m "add context graph"
44
47
  # commit it so everyone who clones the repo (and their agents) gets the graph
45
48
  ```
46
49
 
@@ -48,10 +51,10 @@ Or install it once and get the `graft` command everywhere:
48
51
 
49
52
  ```bash
50
53
  npm install -g @nanonets/graft
51
- graft init
54
+ graft build --deep
52
55
  ```
53
56
 
54
- That is it. Point your agent at `.context/` and it reads the graph before it starts working.
57
+ That is it. Point your agent at `graft/` and it reads the graph before it starts working.
55
58
 
56
59
  ---
57
60
 
@@ -73,9 +76,9 @@ Graft builds that understanding **once** and writes it into your repo as a folde
73
76
 
74
77
  - **Real explanations, not a list of symbols.** Each node says, in plain English, what a part of the system does and how it connects to the rest, the way a senior engineer would explain it. That is the part an agent actually needs so it can skip the exploration. It is not a dump of function names.
75
78
  - **A real graph you can read.** No embeddings, no similarity search, no index to keep warm. The graph is a set of linked files your agent opens, greps, and follows, exactly the way it reads any other file in the repo.
76
- - **Grafted into git.** The graph is just files in `.context/`. Commit it, and anyone who clones the repo has it. No database, no server, no setup. Git does the syncing, and a stale graph shows up as a diff in review instead of rotting in some external store.
79
+ - **Grafted into git.** The graph is just files in `graft/`. Commit it, and anyone who clones the repo has it. No database, no server, no setup. Git does the syncing, and a stale graph shows up as a diff in review instead of rotting in some external store.
77
80
  - **The diff lives with the code.** When a change moves things around, you see it in the graph diff in the same pull request, right next to the code that caused it.
78
- - **Local by default.** The graph builds with a local model, so your code stays on your machine. Cloud models are opt-in for richer summaries.
81
+ - **Your key, your model.** Summaries are written by a model you pick on [OpenRouter](https://openrouter.ai), under your own key. The structural code graph (`graft build`, `graft check`) is deterministic tree-sitter and never calls a model at all.
79
82
 
80
83
  ---
81
84
 
@@ -88,6 +91,8 @@ Graft builds the graph in two passes, both powered by a language model:
88
91
 
89
92
  Both passes are cached by content hash. Re-running only touches the files that changed, so the second build is fast and cheap.
90
93
 
94
+ Alongside the markdown graph, `graft build` builds `graft/.graph/wiring.json` — a per-symbol code graph — plus a per-file wiring card mirroring your source tree. Tier 1 is pure tree-sitter (every function, class, and call edge; deterministic, no model, no network), which is why plain `graft build` needs no key. The `--deep` pass adds a one-line summary and a crux excerpt per symbol, cached by body hash.
95
+
91
96
  ---
92
97
 
93
98
  ## What's in a node
@@ -108,7 +113,7 @@ That is three depths in one file: the summary says *what* the code does, the cru
108
113
 
109
114
  The crux is stored as the code itself, not as a line range, on purpose. Line numbers drift whenever unrelated code above them shifts, but the lines that matter do not. Keeping the text, not the numbers, means the crux stays correct even as the file around it moves.
110
115
 
111
- _Summary, sources, links, and notes ship today. The inline crux excerpt is rolling out as the node schema lands._
116
+ _Summary, sources, links, and notes ship today in markdown nodes. The crux ships per-symbol in the code graph (`graft build --deep`); inlining it into markdown nodes is next._
112
117
 
113
118
  ---
114
119
 
@@ -117,42 +122,45 @@ _Summary, sources, links, and notes ship today. The inline crux excerpt is rolli
117
122
  A graph that has drifted from the code is worse than no graph. `graft check` compares each node's tracked source hashes against the current files and fails if the graph is stale. Drop it in CI so a pull request cannot merge with an out-of-date map.
118
123
 
119
124
  ```bash
120
- graft check # exits non-zero if .context/ has drifted
125
+ graft check # exits non-zero if graft/ has drifted
121
126
  graft check --json # machine-readable drift report
122
127
  ```
123
128
 
129
+ When the wiring graph exists, `graft check` validates it too — structural drift (symbols added, removed, or changed since the last `graft build`) and stale summaries both fail the check. A repo without a wiring graph is not penalized; the markdown graph stands alone.
130
+
124
131
  <!-- placeholder: planned, not yet in the CLI -->
125
- > **Planned: auto-sync on commit.** `graft hook install` will add a post-commit hook that regenerates changed nodes automatically, so the graph stays current without anyone remembering to run `init`. Until then, regenerate with `graft init` and commit it alongside your code.
132
+ > **Planned: auto-regen on PR.** A single CI bot will regenerate changed nodes on a pull request and push the update, so the graph stays current without anyone remembering to run `build`. Until then, regenerate with `graft build --deep` and commit it alongside your code.
126
133
 
127
134
  ---
128
135
 
129
- ## Runs locally
136
+ ## What runs where
130
137
 
131
- Everything runs on your machine. No accounts, no cloud calls, no keys required.
138
+ - **On your machine, no key, no network:** the structural code graph. `graft build` (wiring graph + per-file cards), `graft check`, and `graft ask` are deterministic tree-sitter — they never call a model.
139
+ - **Through your OpenRouter key:** the LLM-written parts — `graft build --deep` adds the concept nodes (file summaries + node synthesis) and the per-symbol summaries and cruxes. Set `OPENROUTER_API_KEY` and optionally pick the model with `GRAFT_OPENROUTER_MODEL` (default: `openai/gpt-4o-mini`).
140
+ - **No telemetry** and no analytics — the only network calls are the LLM requests you configured.
132
141
 
133
- - **Default.** A local model via [Ollama](https://ollama.com) builds the graph. Nothing leaves your machine.
134
- - **Optional.** Set `OPENROUTER_API_KEY` to use a cloud model for richer summaries. Pass `--local` to force local even when a key is set.
135
- - **No telemetry** and no analytics.
136
-
137
- See [`.env.example`](.env.example) for the full list of settings (model names, base URLs).
142
+ See [`.env.example`](.env.example) for the full list of settings (model, base URL, graph directory).
138
143
 
139
144
  ---
140
145
 
141
146
  ## CLI
142
147
 
143
148
  ```bash
144
- graft init [dir] # build .context/ from the code at [dir] (default: .)
145
- graft init --extensions .ts .py # only include these code extensions
146
- graft init --local # force local Ollama even if OPENROUTER_API_KEY is set
149
+ graft build [dir] # build graft/ from the code at [dir]: wiring graph + per-file cards (no LLM, no key)
150
+ graft build --deep # add the LLM layer: concept nodes + per-symbol summary/crux (cached)
151
+ graft build --extensions .ts .py # only include these code extensions
152
+
153
+ graft ask "<task>" [dir] # query the graph — ranked nodes + exact file:line (no LLM, no key)
154
+ graft ask "<task>" --json # machine-readable result
147
155
 
148
- graft check [dir] # fail (exit 1) if .context/ has drifted from the code
156
+ graft check [dir] # fail (exit 1) if graft/ has drifted from the code
149
157
  graft check --json # print the drift report as JSON
150
158
 
151
159
  graft viz [dir] # see the graph: serves an interactive viewer on localhost
152
160
  graft viz --port 5000 --no-open # pick a port; don't auto-open the browser
153
161
 
154
162
  # global
155
- graft --dir <path> # use a context dir other than <repo>/.context
163
+ graft --dir <path> # use a context dir other than <repo>/graft
156
164
  ```
157
165
 
158
166
  ## Visualize it (`graft viz`)
@@ -160,9 +168,9 @@ graft --dir <path> # use a context dir other than <repo>/.cont
160
168
  `graft viz` opens a local, interactive view of both graphs — no install, no dev
161
169
  server; the viewer ships prebuilt inside the package.
162
170
 
163
- - **Context** tab — the architecture graph from `.context/*.md`. Nodes colored by
171
+ - **Context** tab — the architecture graph from `graft/*.md`. Nodes colored by
164
172
  type, sized by connectedness.
165
- - **Code** tab — the per-symbol graph from `graph.json` (run `graft graph` first).
173
+ - **Code** tab — the per-symbol graph from `graft/.graph/wiring.json` (run `graft build` first).
166
174
  - **Outline** tab — the file → class → method hierarchy as a collapsible tree.
167
175
 
168
176
  Edges speak the code's language. Every link is one of a closed set of verbs, each
@@ -180,7 +188,7 @@ answering a question someone building or reviewing code actually asks:
180
188
  Select a node and its edges take on direction: **amber = what it depends on,
181
189
  teal = what depends on it**, with the verb written on each highlighted edge.
182
190
  Chips above the canvas filter by verb; tree-sitter-extracted edges draw solid
183
- while LLM-inferred ones draw dashed. The viewer live-reloads when `.context/`
191
+ while LLM-inferred ones draw dashed. The viewer live-reloads when `graft/`
184
192
  changes on disk. Older graphs with vague verbs (`influences`, `supports`) are
185
193
  normalized on load — no regeneration needed.
186
194
 
@@ -190,7 +198,7 @@ normalized on load — no regeneration needed.
190
198
 
191
199
  <!-- placeholder: fill from a committed bench/results/ run before launch -->
192
200
 
193
- The claim Graft has to earn is simple: an agent that reads the graph first is cheaper and faster without getting more answers wrong. The harness runs every task twice through the same agent with the same file tools. One run is **cold** (it explores from zero) and one is **graph** (it gets the `.context/` bundle up front). A separate model judges correctness, with a required-keyword floor so a fast-but-wrong answer cannot win.
201
+ The claim Graft has to earn is simple: an agent that reads the graph first is cheaper and faster without getting more answers wrong. The harness runs every task twice through the same agent with the same file tools. One run is **cold** (it explores from zero) and one is **graph** (it gets the `graft/` bundle up front). A separate model judges correctness, with a required-keyword floor so a fast-but-wrong answer cannot win.
194
202
 
195
203
  | Metric | Cold | Graph | Change |
196
204
  |---|---|---|---|
@@ -218,7 +226,7 @@ npm install
218
226
  npm run build
219
227
  npm test
220
228
 
221
- npm run cli -- init . # run the CLI from source
229
+ npm run cli -- build --deep . # run the CLI from source
222
230
  ```
223
231
 
224
232
  ---
@@ -0,0 +1,28 @@
1
+ import type { Relation } from "../graph/types.js";
2
+ export interface AskHit {
3
+ kind: "concept" | "symbol" | "caller" | "callee";
4
+ title: string;
5
+ /** A `file` or `file:Lx-Ly` pointer the agent can open directly. */
6
+ pointer: string;
7
+ snippet: string;
8
+ relation?: Relation;
9
+ related?: string[];
10
+ score: number;
11
+ }
12
+ export interface AskResult {
13
+ query: string;
14
+ mode: "structural" | "lexical" | "empty";
15
+ /** For structural mode: the symbol whose neighbours we walked. */
16
+ subject?: string;
17
+ hits: AskHit[];
18
+ note?: string;
19
+ }
20
+ export interface AskOptions {
21
+ contextDir?: string;
22
+ limit?: number;
23
+ }
24
+ /** Answer a query from the graft/ graph at `dir`. Deterministic, $0. */
25
+ export declare function ask(dir: string, query: string, opts?: AskOptions): AskResult;
26
+ /** Render an {@link AskResult} as a compact markdown context pack. */
27
+ export declare function formatAsk(r: AskResult): string;
28
+ //# sourceMappingURL=ask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/ask/ask.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAA2B,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE3E,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;IACzC,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAmMD,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wEAAwE;AACxE,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,SAAS,CAUhF;AAED,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAqB9C"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * `graft ask "<task>"` — the ACTIVE channel.
3
+ *
4
+ * One tool that routes a plain-words query to the right graph and returns a lean,
5
+ * ranked context pack (prose + exact `file:line` + related), never raw JSON and
6
+ * never whole files:
7
+ *
8
+ * - Structural intent ("what calls X", "callers of X", "what does X import")
9
+ * → walk the wiring graph's edges and return the neighbour symbols with spans.
10
+ * - Everything else → lexical rank over concept nodes (prose) and wiring symbols
11
+ * (name + signature + summary), returning the best few with pointers.
12
+ *
13
+ * v1 is deterministic and $0 (term-overlap scoring, no LLM, no embeddings). The
14
+ * output is markdown so it drops straight into an agent's context.
15
+ */
16
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
17
+ import { join, resolve } from "node:path";
18
+ import matter from "gray-matter";
19
+ import { contextDirFor } from "../context/node-file.js";
20
+ import { readGraph, wiringPath } from "../graph/write.js";
21
+ const STOP = new Set([
22
+ "the", "a", "an", "of", "to", "in", "is", "are", "how", "does", "do", "what",
23
+ "where", "which", "that", "this", "it", "for", "on", "and", "or", "with",
24
+ "i", "we", "get", "set", "use", "used", "using", "when", "why", "can",
25
+ ]);
26
+ /** Split prose + identifiers into lowercased subword tokens (camelCase, snake, kebab). */
27
+ function tokenize(text) {
28
+ return text
29
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2") // camelCase → camel Case
30
+ .toLowerCase()
31
+ .split(/[^a-z0-9]+/)
32
+ .filter((t) => t.length > 1 && !STOP.has(t));
33
+ }
34
+ /** Term-frequency count map. */
35
+ function counts(tokens) {
36
+ const m = new Map();
37
+ for (const t of tokens)
38
+ m.set(t, (m.get(t) ?? 0) + 1);
39
+ return m;
40
+ }
41
+ /** First real prose line of a node body (skips headings, markers, blanks). */
42
+ function firstProse(body) {
43
+ for (const raw of body.split("\n")) {
44
+ const line = raw.trim();
45
+ if (!line || line.startsWith("#") || line.startsWith("<!--") || line.startsWith("-"))
46
+ continue;
47
+ return line;
48
+ }
49
+ return "";
50
+ }
51
+ function loadCorpus(outDir) {
52
+ const concepts = [];
53
+ if (existsSync(outDir)) {
54
+ for (const entry of readdirSync(outDir)) {
55
+ if (!entry.endsWith(".md") || entry === "INDEX.md")
56
+ continue;
57
+ const parsed = matter(readFileSync(join(outDir, entry), "utf8"));
58
+ const fm = parsed.data;
59
+ const sources = Array.isArray(fm.sources)
60
+ ? fm.sources.map((s) => s.path)
61
+ : [];
62
+ const related = Array.isArray(fm.links)
63
+ ? fm.links.map((l) => l.to)
64
+ : [];
65
+ const snippet = firstProse(parsed.content);
66
+ concepts.push({
67
+ slug: String(fm.slug ?? entry.replace(/\.md$/, "")),
68
+ name: String(fm.name ?? ""),
69
+ sources,
70
+ related,
71
+ snippet,
72
+ text: `${fm.name ?? ""} ${snippet} ${sources.join(" ")}`,
73
+ });
74
+ }
75
+ }
76
+ return { concepts, graph: readGraph(wiringPath(outDir)) };
77
+ }
78
+ /** Score a document's token counts against the query counts (name field pre-weighted by caller). */
79
+ function score(query, doc) {
80
+ let s = 0;
81
+ for (const [t, qn] of query) {
82
+ const dn = doc.get(t);
83
+ if (dn)
84
+ s += qn * dn;
85
+ }
86
+ return s;
87
+ }
88
+ // ── Structural intent ──────────────────────────────────────────────────────
89
+ const INCOMING = /\b(caller|callers|calls?\s+into|who\s+calls|what\s+calls|called\s+by|used\s+by|uses)\b/;
90
+ const OUTGOING = /\b(callee|callees|what\s+does\s+\w+\s+call|calls\s+what|imports?|depends\s+on)\b/;
91
+ const INCOMING_RELS = ["calls", "references", "implements", "extends"];
92
+ const OUTGOING_RELS = ["calls", "references", "imports", "implements", "extends"];
93
+ /** Pick the query word that names a real symbol (longest exact name match wins). */
94
+ function findSubject(query, graph) {
95
+ const byName = new Map();
96
+ for (const n of graph.nodes) {
97
+ if (n.kind === "file")
98
+ continue;
99
+ const key = n.name.toLowerCase();
100
+ byName.set(key, [...(byName.get(key) ?? []), n]);
101
+ }
102
+ const words = query.split(/[^A-Za-z0-9_.]+/).filter(Boolean);
103
+ let best = [];
104
+ let bestLen = 0;
105
+ for (const w of words) {
106
+ const hit = byName.get(w.toLowerCase());
107
+ if (hit && w.length > bestLen) {
108
+ best = hit;
109
+ bestLen = w.length;
110
+ }
111
+ }
112
+ return best;
113
+ }
114
+ function structural(query, graph, limit) {
115
+ const wantsIn = INCOMING.test(query);
116
+ const wantsOut = OUTGOING.test(query);
117
+ if (!wantsIn && !wantsOut)
118
+ return null;
119
+ const subjects = findSubject(query, graph);
120
+ if (subjects.length === 0)
121
+ return null;
122
+ const ids = new Set(subjects.map((n) => n.id));
123
+ const byId = new Map(graph.nodes.map((n) => [n.id, n]));
124
+ const outgoing = wantsOut && !wantsIn; // "what does X call / import" — else default to callers
125
+ const rels = new Set(outgoing ? OUTGOING_RELS : INCOMING_RELS);
126
+ const hits = [];
127
+ const seen = new Set();
128
+ for (const e of graph.edges) {
129
+ if (!rels.has(e.relation))
130
+ continue;
131
+ const anchor = outgoing ? e.source : e.target;
132
+ const other = outgoing ? e.target : e.source;
133
+ if (!ids.has(anchor) || seen.has(other + e.relation))
134
+ continue;
135
+ seen.add(other + e.relation);
136
+ const node = byId.get(other);
137
+ hits.push({
138
+ kind: outgoing ? "callee" : "caller",
139
+ title: node ? node.name : other, // unresolved import target → raw module string
140
+ pointer: node ? `${node.path}:${node.span}` : other,
141
+ snippet: node?.summary?.split("\n")[0].trim() ?? node?.signature ?? "",
142
+ relation: e.relation,
143
+ score: 1,
144
+ });
145
+ }
146
+ hits.sort((a, b) => a.pointer.localeCompare(b.pointer));
147
+ return {
148
+ query,
149
+ mode: "structural",
150
+ subject: subjects[0].name,
151
+ hits: hits.slice(0, limit),
152
+ note: outgoing
153
+ ? `outgoing edges from ${subjects[0].name}`
154
+ : `callers / references of ${subjects[0].name}`,
155
+ };
156
+ }
157
+ // ── Lexical rank ─────────────────────────────────────────────────────────────
158
+ function lexical(query, corpus, limit) {
159
+ const q = counts(tokenize(query));
160
+ const scored = [];
161
+ for (const c of corpus.concepts) {
162
+ const nameScore = score(q, counts(tokenize(c.name))) * 3;
163
+ const bodyScore = score(q, counts(tokenize(c.text)));
164
+ const total = nameScore + bodyScore;
165
+ if (total > 0) {
166
+ scored.push({
167
+ kind: "concept",
168
+ title: c.name || c.slug,
169
+ pointer: c.sources.join(", ") || c.slug,
170
+ snippet: c.snippet,
171
+ related: c.related,
172
+ score: total,
173
+ });
174
+ }
175
+ }
176
+ for (const n of corpus.graph?.nodes ?? []) {
177
+ if (n.kind === "file")
178
+ continue;
179
+ const nameScore = score(q, counts(tokenize(n.name))) * 3;
180
+ const pathScore = score(q, counts(tokenize(n.path))) * 2;
181
+ const bodyScore = score(q, counts(tokenize(`${n.signature ?? ""} ${n.summary ?? ""}`)));
182
+ const total = nameScore + pathScore + bodyScore;
183
+ if (total > 0) {
184
+ scored.push({
185
+ kind: "symbol",
186
+ title: `${n.name} · ${n.kind}`,
187
+ pointer: `${n.path}:${n.span}`,
188
+ snippet: n.summary?.split("\n")[0].trim() ?? n.signature ?? "",
189
+ score: total,
190
+ });
191
+ }
192
+ }
193
+ scored.sort((a, b) => b.score - a.score || a.title.localeCompare(b.title));
194
+ return {
195
+ query,
196
+ mode: scored.length ? "lexical" : "empty",
197
+ hits: scored.slice(0, limit),
198
+ note: scored.length ? undefined : "no matching nodes — try different words, or `graft build` if graft/ is empty",
199
+ };
200
+ }
201
+ /** Answer a query from the graft/ graph at `dir`. Deterministic, $0. */
202
+ export function ask(dir, query, opts = {}) {
203
+ const outDir = contextDirFor(resolve(dir), opts.contextDir);
204
+ const limit = opts.limit ?? 8;
205
+ const corpus = loadCorpus(outDir);
206
+ if (corpus.graph) {
207
+ const s = structural(query, corpus.graph, limit);
208
+ if (s)
209
+ return s;
210
+ }
211
+ return lexical(query, corpus, limit);
212
+ }
213
+ /** Render an {@link AskResult} as a compact markdown context pack. */
214
+ export function formatAsk(r) {
215
+ const head = `graft ask — "${r.query}" (${r.mode}${r.note ? `: ${r.note}` : ""})`;
216
+ if (r.hits.length === 0) {
217
+ return `${head}\n\n${r.note ?? "no matches."}`;
218
+ }
219
+ const lines = [head, ""];
220
+ if (r.mode === "structural") {
221
+ for (const h of r.hits) {
222
+ const tail = h.snippet ? ` — ${h.snippet}` : "";
223
+ lines.push(`- ${h.title} ${h.pointer} (${h.relation})${tail}`);
224
+ }
225
+ }
226
+ else {
227
+ r.hits.forEach((h, i) => {
228
+ lines.push(`${i + 1}. ${h.title} [${h.kind}]`);
229
+ lines.push(` ${h.pointer}`);
230
+ if (h.snippet)
231
+ lines.push(` ${h.snippet}`);
232
+ if (h.related?.length)
233
+ lines.push(` related: ${h.related.join(", ")}`);
234
+ lines.push("");
235
+ });
236
+ }
237
+ return lines.join("\n").trimEnd() + "\n";
238
+ }
239
+ //# sourceMappingURL=ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../src/ask/ask.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -19,58 +19,74 @@ const program = new Command();
19
19
  program
20
20
  .name("graft")
21
21
  .description("Build a repo's context graph as linked markdown, and keep it in sync with the code.")
22
- .option("--dir <path>", "context graph directory (default: <repo>/.context)");
22
+ .option("--dir <path>", "context graph directory (default: <repo>/graft)");
23
23
  function engineFrom() {
24
24
  const opts = program.opts();
25
25
  return new Graft({ contextDir: opts.dir });
26
26
  }
27
27
  program
28
- .command("init")
29
- .description("Build .context/ from your code — one markdown node per system, API, or concept")
28
+ .command("build")
29
+ .description("Build graft/ from your code — wiring graph + per-file cards ($0, no key). " +
30
+ "Add --deep for the LLM concept map + per-symbol summaries/crux.")
30
31
  .argument("[dir]", "repository root", ".")
32
+ .option("--deep", "run the LLM pass: concept nodes (graft/*.md) + per-symbol summary/crux")
31
33
  .option("-e, --extensions <exts...>", 'code extensions to include (e.g. ".ts" ".py")')
32
34
  .action(async (dir, opts) => {
33
35
  const engine = engineFrom();
34
- const r = await engine.init(dir, {
35
- extensions: opts.extensions,
36
- onProgress: ({ phase, index, total, file }) => process.stderr.write(`\r${phase === "summarize" ? "reading" : "writing"} ${index + 1}/${total}: ${file.slice(0, 50).padEnd(50)}`),
36
+ const fmt = (o) => Object.entries(o)
37
+ .sort((a, b) => b[1] - a[1])
38
+ .map(([k, n]) => `${n} ${k}`)
39
+ .join(", ");
40
+ // --deep: concept nodes first (they're LLM prose; the wiring cards link up to
41
+ // them), then the wiring graph rewrites the cards + INDEX with those up-links.
42
+ if (opts.deep) {
43
+ const c = await engine.init(dir, {
44
+ extensions: opts.extensions,
45
+ onProgress: ({ phase, index, total, file }) => process.stderr.write(`\r${phase === "summarize" ? "reading" : "writing"} concepts ${index + 1}/${total}: ${file.slice(0, 40).padEnd(40)}`),
46
+ });
47
+ process.stderr.write("\n");
48
+ console.log(`✓ concepts: ${c.nodes} nodes, ${c.links} links from ${c.files} files (${c.summarized} read, ${c.cached} cached)`);
49
+ for (const e of c.errors)
50
+ console.error(`✗ ${e}`);
51
+ }
52
+ // Wiring graph (Tier-2 cards + Tier-3 wiring.json) — always. LLM meaning only with --deep.
53
+ const g = await engine.graph(dir, {
54
+ llm: opts.deep,
55
+ onProgress: ({ phase, index, total, file }) => process.stderr.write(`\r${phase === "enrich" ? "summarizing" : "parsing"} ${index + 1}/${total}: ${file.slice(0, 50).padEnd(50)}`),
37
56
  });
38
57
  process.stderr.write("\n");
39
- console.log(`✓ ${r.nodes} nodes, ${r.links} links from ${r.files} files ` +
40
- `(${r.summarized} read, ${r.cached} cached)`);
41
- console.log(` → ${r.contextDir}`);
42
- for (const e of r.errors)
58
+ console.log(`✓ wiring: ${g.nodes} nodes (${fmt(g.byKind)}), ${g.edges} edges, ${g.cards} cards [${g.languages.join(", ")}]`);
59
+ if (opts.deep) {
60
+ const m = g.meaning;
61
+ console.log(` meaning: ${m.computed} computed, ${m.cached} cached, ${m.stale} stale, ${m.pending} pending`);
62
+ }
63
+ console.log(` → ${g.contextDir}`);
64
+ for (const e of g.errors)
43
65
  console.error(`✗ ${e}`);
44
- const rel = relative(process.cwd(), r.contextDir) || ".context";
45
- console.log(` commit it: git add ${rel} && git commit -m "update context graph"`);
66
+ const rel = relative(process.cwd(), g.contextDir) || "graft";
67
+ console.log(` commit it: git add ${rel} && git commit -m "update graft"`);
46
68
  });
47
69
  program
48
- .command("graph")
49
- .description("Build .context/graph.json — a per-symbol code graph (tree-sitter structure + optional LLM meaning)")
70
+ .command("ask")
71
+ .description("Query the graft/ graph — returns ranked nodes + exact file:line, routed to prose or wiring ($0, no key)")
72
+ .argument("<query>", "what you want to understand, in plain words")
50
73
  .argument("[dir]", "repository root", ".")
51
- .option("--llm", "run the Tier-2 LLM pass (summary + crux); unchanged bodies are served from cache")
52
- .action(async (dir, opts) => {
74
+ .option("-n, --limit <n>", "max results", "8")
75
+ .option("--json", "output the result as JSON")
76
+ .action(async (query, dir, opts) => {
53
77
  const engine = engineFrom();
54
- const r = await engine.graph(dir, {
55
- llm: opts.llm,
56
- onProgress: ({ phase, index, total, file }) => process.stderr.write(`\r${phase === "enrich" ? "summarizing" : "parsing"} ${index + 1}/${total}: ${file.slice(0, 50).padEnd(50)}`),
57
- });
58
- process.stderr.write("\n");
59
- const fmt = (o) => Object.entries(o)
60
- .sort((a, b) => b[1] - a[1])
61
- .map(([k, n]) => `${n} ${k}`)
62
- .join(", ");
63
- console.log(`✓ ${r.nodes} nodes (${fmt(r.byKind)}) from ${r.files} files [${r.languages.join(", ")}]`);
64
- console.log(` ${r.edges} edges (${fmt(r.byRelation)})`);
65
- const m = r.meaning;
66
- console.log(` meaning: ${m.computed} computed, ${m.cached} cached, ${m.stale} stale, ${m.pending} pending`);
67
- console.log(` → ${r.graphPath}`);
68
- for (const e of r.errors)
69
- console.error(`✗ ${e}`);
78
+ const r = engine.ask(dir, query, { limit: Number(opts.limit) });
79
+ if (opts.json) {
80
+ console.log(JSON.stringify(r, null, 2));
81
+ }
82
+ else {
83
+ const { formatAsk } = await import("./ask/ask.js");
84
+ process.stdout.write(formatAsk(r));
85
+ }
70
86
  });
71
87
  program
72
88
  .command("check")
73
- .description("Fail if .context/ is stale relative to the code (for CI)")
89
+ .description("Fail if graft/ is stale relative to the code (for CI)")
74
90
  .argument("[dir]", "repository root", ".")
75
91
  .option("-e, --extensions <exts...>", "code extensions to include")
76
92
  .option("--json", "output the drift as JSON")
@@ -107,7 +123,7 @@ program
107
123
  const globalOpts = program.opts();
108
124
  const contextDir = contextDirFor(root, globalOpts.dir);
109
125
  if (!existsSync(contextDir)) {
110
- console.error(`✗ no context graph at ${contextDir} — run \`graft init\` first`);
126
+ console.error(`✗ no context graph at ${contextDir} — run \`graft build --deep\` first`);
111
127
  process.exit(1);
112
128
  }
113
129
  // dist/cli.js → dist/viewer/ (prebuilt at package build time)
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}