@sdsrs/code-graph 0.154.0 → 0.156.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
|
@@ -427,7 +427,7 @@ skill does is also runnable by hand.
|
|
|
427
427
|
- **Rust has no `inherits` edges** — the language has no class inheritance, so `impl Trait for Type` is recorded as `implements` and an `inherits`-filtered query returns empty for Rust.
|
|
428
428
|
- **Kotlin/Swift interface conformance** is recorded as `inherits` (both use a single `: Type` grammar for base classes and protocols/interfaces), so `implements`-filtered queries return empty for these two languages.
|
|
429
429
|
- **Cross-file dead-code detection** may false-positive a type whose only cross-file reference sits beyond the 4096-byte stored-content cap per node (documented accepted limitation, v0.97.1).
|
|
430
|
-
- **
|
|
430
|
+
- **A file tree-sitter cannot fully parse is indexed over a damaged parse.** Symbols inside the damaged region can be missing or mis-scoped — e.g. a Swift class whose body holds `#if`/`#error` directives, or macro-heavy C++ headers. The index reports the damage rather than hiding it. A run prints `Syntax errors in <file> — symbols may be incomplete` per file plus an `N file(s) parsed with syntax errors` total, and the verdict is stored with the index, so it survives the run: `health-check` names the files (`Parse: N file(s) indexed over a damaged parse`, plus `files_with_parse_errors` / `parse_error_files` under `--json`), `doctor` shows a `Parse` row, and the MCP `get_index_status` carries the same two fields. An incremental run over unrelated files does not clear it — only re-parsing the offending file, or deleting it, does. Rust borrows of a binding named `raw` (`&raw`, `&raw[..]`, `&raw.field`), which the old `tree-sitter-rust` 0.23 grammar misread as the `&raw const` operator, parse cleanly since the tree-sitter 0.25 upgrade: this repo indexed fresh went from 9 damaged Rust files to 0.
|
|
431
431
|
|
|
432
432
|
## Team-shared graph snapshot
|
|
433
433
|
|
|
@@ -129,6 +129,11 @@ function firstShellClause(cmd) {
|
|
|
129
129
|
if (c === quote) quote = null;
|
|
130
130
|
continue;
|
|
131
131
|
}
|
|
132
|
+
// Outside quotes a backslash escapes the next character: `\"` opens no
|
|
133
|
+
// quote and `\;` / `\|` are literal. quotedSpans reads patterns by the same
|
|
134
|
+
// rule; a splitter that disagreed let `grep \"X\" src/ && echo "Y"` hand the
|
|
135
|
+
// echo's `Y` to the pattern reader (pre-ship review F1).
|
|
136
|
+
if (c === '\\') { i++; continue; }
|
|
132
137
|
if (c === '"' || c === "'") { quote = c; continue; }
|
|
133
138
|
// Control operators END the grep's argument list → truncate. NOT redirects
|
|
134
139
|
// (`>` `<`): `2>&1`, `>out`, and process substitution `-f <(cat pats) src/`
|
|
@@ -227,8 +232,47 @@ function extractPatterns(cmd) {
|
|
|
227
232
|
// Collect every quoted argument — first one is the pattern in standard grep
|
|
228
233
|
// usage; subsequent ones (e.g. `-e "second"`) are also patterns or filter
|
|
229
234
|
// expressions and worth screening too.
|
|
230
|
-
|
|
231
|
-
|
|
235
|
+
return quotedSpans(stripped).map(s => s.body).filter(Boolean);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* The quoted spans of a shell clause, read the way the shell reads them — the
|
|
240
|
+
* rules firstShellClause, splitTopLevelSegments and extractUnansweredTail also
|
|
241
|
+
* follow (lesson #9656 inside quotes; pre-ship review F1 outside), which a span regex (`"([^"]+)"|'([^']+)'`) did not: it closed a
|
|
242
|
+
* double-quoted argument at the first `\"`, so
|
|
243
|
+
* `grep "if:\s*'\|\"if\"\|statusMessage"` yielded `\|statusMessage`, and its
|
|
244
|
+
* translation `|statusMessage` matches every line (observed 2026-09-25).
|
|
245
|
+
* - `'…'` is literal to the next `'`.
|
|
246
|
+
* - `"…"`: a backslash escapes `"` `\` `$` and backtick (the backslash is
|
|
247
|
+
* dropped) and, before a newline, removes both characters (a line
|
|
248
|
+
* continuation); before anything else it is literal (`"a\|b"`).
|
|
249
|
+
* - Outside quotes a backslash escapes the next character, so `\"` opens
|
|
250
|
+
* nothing — the shell hands grep the quote character itself.
|
|
251
|
+
* An unterminated quote ends the scan: what follows is not a span we can read.
|
|
252
|
+
* @returns {{start: number, end: number, body: string}[]} `end` is exclusive,
|
|
253
|
+
* covering both quote characters.
|
|
254
|
+
*/
|
|
255
|
+
function quotedSpans(s) {
|
|
256
|
+
const spans = [];
|
|
257
|
+
if (typeof s !== 'string') return spans;
|
|
258
|
+
for (let i = 0; i < s.length; i++) {
|
|
259
|
+
const c = s[i];
|
|
260
|
+
if (c === '\\') { i++; continue; }
|
|
261
|
+
if (c !== '"' && c !== "'") continue;
|
|
262
|
+
let body = '';
|
|
263
|
+
let j = i + 1;
|
|
264
|
+
for (; j < s.length && s[j] !== c; j++) {
|
|
265
|
+
if (c === '"' && s[j] === '\\' && j + 1 < s.length && '"\\$`\n'.includes(s[j + 1])) {
|
|
266
|
+
j++;
|
|
267
|
+
if (s[j] === '\n') continue; // backslash-newline is a line continuation: both go
|
|
268
|
+
}
|
|
269
|
+
body += s[j];
|
|
270
|
+
}
|
|
271
|
+
if (j >= s.length) break;
|
|
272
|
+
spans.push({ start: i, end: j + 1, body });
|
|
273
|
+
i = j;
|
|
274
|
+
}
|
|
275
|
+
return spans;
|
|
232
276
|
}
|
|
233
277
|
|
|
234
278
|
// Declaration anchors inside a pattern (`def cascade_failure|class TaskState`)
|
|
@@ -349,7 +393,16 @@ function isAgFilenameSearch(clause) {
|
|
|
349
393
|
// argument can contain whitespace, so `ag "some_symbol -g x" src/` splits into
|
|
350
394
|
// three tokens and the middle one looks exactly like a flag. Blanking leaves
|
|
351
395
|
// an attached value's flag behind (`-g"x"` → `-g`), which is what we want.
|
|
352
|
-
|
|
396
|
+
// Spans come from quotedSpans, not a span regex: `"a\" -g x"` is ONE
|
|
397
|
+
// argument, and a regex that closed it at the `\"` left `-g` bare.
|
|
398
|
+
const unverbed = clause.replace(VERB_STRIP, '');
|
|
399
|
+
let scan = '';
|
|
400
|
+
let at = 0;
|
|
401
|
+
for (const sp of quotedSpans(unverbed)) {
|
|
402
|
+
scan += unverbed.slice(at, sp.start) + ' ';
|
|
403
|
+
at = sp.end;
|
|
404
|
+
}
|
|
405
|
+
scan += unverbed.slice(at);
|
|
353
406
|
for (const tok of scan.trim().split(/\s+/)) {
|
|
354
407
|
if (!tok || tok[0] !== '-') continue;
|
|
355
408
|
if (tok.startsWith('--')) {
|
|
@@ -602,6 +655,7 @@ function extractUnansweredTail(cmd) {
|
|
|
602
655
|
if (c === quote) quote = null;
|
|
603
656
|
continue;
|
|
604
657
|
}
|
|
658
|
+
if (c === '\\') { i++; continue; } // outside quotes: escapes the next char (see firstShellClause)
|
|
605
659
|
if (c === '"' || c === "'") { quote = c; continue; }
|
|
606
660
|
if (c === ';' || (c === '&' && cmd[i + 1] === '&')) {
|
|
607
661
|
const tail = cmd.slice(i + (c === ';' ? 1 : 2)).trim();
|
|
@@ -695,6 +749,15 @@ function splitTopLevelSegments(cmd) {
|
|
|
695
749
|
if (c === quote) quote = null;
|
|
696
750
|
continue;
|
|
697
751
|
}
|
|
752
|
+
// Outside quotes: escapes the next char, kept verbatim (see firstShellClause)
|
|
753
|
+
// — except a newline, where the pair is a line continuation and the shell
|
|
754
|
+
// removes both. Keeping them left `&& \⏎ grep …` a segment that starts
|
|
755
|
+
// with `\`, which GREP_HEAD rejects (pre-ship review round 2 F1).
|
|
756
|
+
if (c === '\\' && i + 1 < cmd.length) {
|
|
757
|
+
if (cmd[i + 1] !== '\n') cur += c + cmd[i + 1];
|
|
758
|
+
i++;
|
|
759
|
+
continue;
|
|
760
|
+
}
|
|
698
761
|
if (c === '"' || c === "'") { quote = c; cur += c; continue; }
|
|
699
762
|
// `&&` and `||` (a single `&`/`|` is NOT a split — `|` is an output-filter
|
|
700
763
|
// pipe, lone `&` is background and rare in tool calls).
|
|
@@ -35,7 +35,7 @@ jobs:
|
|
|
35
35
|
node-version: '20'
|
|
36
36
|
- name: Build snapshot
|
|
37
37
|
run: |
|
|
38
|
-
npx -y -p @sdsrs/code-graph@0.
|
|
38
|
+
npx -y -p @sdsrs/code-graph@0.156.0 code-graph-mcp snapshot create --out snapshot.db
|
|
39
39
|
zstd -9 snapshot.db -o snapshot.db.zst
|
|
40
40
|
mv snapshot.db.zst "code-graph-snapshot-${GITHUB_SHA:0:7}.db.zst"
|
|
41
41
|
- name: Upload to release
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdsrs/code-graph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.156.0",
|
|
4
4
|
"description": "MCP server that indexes codebases into an AST knowledge graph with semantic search, call graph traversal, and HTTP route tracing",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"node": ">=16"
|
|
36
36
|
},
|
|
37
37
|
"optionalDependencies": {
|
|
38
|
-
"@sdsrs/code-graph-linux-x64": "0.
|
|
39
|
-
"@sdsrs/code-graph-linux-arm64": "0.
|
|
40
|
-
"@sdsrs/code-graph-darwin-x64": "0.
|
|
41
|
-
"@sdsrs/code-graph-darwin-arm64": "0.
|
|
42
|
-
"@sdsrs/code-graph-win32-x64": "0.
|
|
38
|
+
"@sdsrs/code-graph-linux-x64": "0.156.0",
|
|
39
|
+
"@sdsrs/code-graph-linux-arm64": "0.156.0",
|
|
40
|
+
"@sdsrs/code-graph-darwin-x64": "0.156.0",
|
|
41
|
+
"@sdsrs/code-graph-darwin-arm64": "0.156.0",
|
|
42
|
+
"@sdsrs/code-graph-win32-x64": "0.156.0"
|
|
43
43
|
}
|
|
44
44
|
}
|