@sdsrs/code-graph 0.74.4 → 0.74.6
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/.claude-plugin/plugin.json +1 -1
- package/claude-plugin/scripts/session-init.js +50 -15
- package/claude-plugin/scripts/session-init.test.js +50 -1
- package/claude-plugin/scripts/statusline.js +59 -16
- package/claude-plugin/scripts/statusline.test.js +166 -0
- package/package.json +6 -6
|
@@ -263,8 +263,39 @@ function syncLifecycleConfig() {
|
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
/**
|
|
266
|
-
*
|
|
267
|
-
*
|
|
266
|
+
* Cheap probe for a rebuild reason that mtime/git can't see: an INDEX_VERSION
|
|
267
|
+
* mismatch (the on-disk index was built by an older extractor generation). Since
|
|
268
|
+
* P0, a reader (statusline `health-check`, `grep`) no longer wipes such an index —
|
|
269
|
+
* it serves the stale structural data and reports "rebuild pending" — so in a
|
|
270
|
+
* project where the MCP server isn't running, nothing else nudges a rebuild.
|
|
271
|
+
* health-check carries the verdict in `index_version_stale`. Best-effort: any
|
|
272
|
+
* failure → false (never force work off a bad probe).
|
|
273
|
+
*/
|
|
274
|
+
function indexNeedsRevalidation(bin, cwd) {
|
|
275
|
+
try {
|
|
276
|
+
let out;
|
|
277
|
+
try {
|
|
278
|
+
out = execFileSync(bin, ['health-check', '--format', 'json'],
|
|
279
|
+
{ cwd, timeout: 3000, stdio: ['pipe', 'pipe', 'pipe'] }).toString();
|
|
280
|
+
} catch (e) {
|
|
281
|
+
// health-check exits non-zero on an unhealthy index but still writes JSON.
|
|
282
|
+
out = ((e && e.stdout) || '').toString();
|
|
283
|
+
}
|
|
284
|
+
return JSON.parse(out).index_version_stale === true;
|
|
285
|
+
} catch {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Decide whether the index needs a background refresh and, if so, spawn a
|
|
292
|
+
* detached `incremental-index` (which revalidates: an indexer open wipes +
|
|
293
|
+
* rebuilds a version-stale index, then re-indexes all files).
|
|
294
|
+
*
|
|
295
|
+
* Two independent triggers:
|
|
296
|
+
* 1. git HEAD newer than index.db mtime — content drifted since last index.
|
|
297
|
+
* 2. INDEX_VERSION mismatch (post-upgrade) — see indexNeedsRevalidation.
|
|
298
|
+
*
|
|
268
299
|
* Returns 'fresh' | 'refreshing' | 'skipped'.
|
|
269
300
|
*/
|
|
270
301
|
function ensureIndexFresh() {
|
|
@@ -276,25 +307,28 @@ function ensureIndexFresh() {
|
|
|
276
307
|
const dbPath = path.join(cwd, '.code-graph', 'index.db');
|
|
277
308
|
if (!fs.existsSync(dbPath)) return 'skipped';
|
|
278
309
|
|
|
310
|
+
let needsRefresh = false;
|
|
311
|
+
// Trigger 1: git HEAD newer than index mtime.
|
|
279
312
|
try {
|
|
280
313
|
const dbMtime = fs.statSync(dbPath).mtimeMs;
|
|
281
|
-
// Compare with git HEAD commit timestamp
|
|
282
314
|
const gitTs = parseInt(
|
|
283
315
|
execSync('git log -1 --format=%ct', { cwd, timeout: 2000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim()
|
|
284
316
|
) * 1000;
|
|
285
|
-
if (gitTs
|
|
317
|
+
if (gitTs > dbMtime) needsRefresh = true;
|
|
318
|
+
} catch { /* no git / not a repo — fall through to the version probe */ }
|
|
286
319
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
320
|
+
// Trigger 2: INDEX_VERSION mismatch (only probe when mtime looked fresh).
|
|
321
|
+
if (!needsRefresh && indexNeedsRevalidation(bin, cwd)) needsRefresh = true;
|
|
322
|
+
|
|
323
|
+
if (!needsRefresh) return 'fresh';
|
|
324
|
+
|
|
325
|
+
const child = spawn(bin, ['incremental-index', '--quiet'], {
|
|
326
|
+
cwd,
|
|
327
|
+
detached: true,
|
|
328
|
+
stdio: 'ignore',
|
|
329
|
+
});
|
|
330
|
+
if (child && typeof child.unref === 'function') child.unref();
|
|
331
|
+
return 'refreshing';
|
|
298
332
|
}
|
|
299
333
|
|
|
300
334
|
/**
|
|
@@ -720,6 +754,7 @@ module.exports = {
|
|
|
720
754
|
launchBackgroundAutoUpdate,
|
|
721
755
|
syncLifecycleConfig,
|
|
722
756
|
ensureIndexFresh,
|
|
757
|
+
indexNeedsRevalidation,
|
|
723
758
|
injectProjectMap,
|
|
724
759
|
injectRecentImpact,
|
|
725
760
|
verifyBinary,
|
|
@@ -4,7 +4,26 @@ const assert = require('node:assert/strict');
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const { launchBackgroundAutoUpdate, syncLifecycleConfig, ensureIndexFresh, indexNeedsRevalidation, verifyBinary, computeQuietHooks, shouldInjectMap, shouldInjectRecentImpact, recentImpactWorthShowing, filterSourceFiles, parseGitStatusPaths, formatRecentImpact } = require('./session-init');
|
|
9
|
+
|
|
10
|
+
// Write an executable stub named `code-graph-mcp` that emits `json` to stdout on
|
|
11
|
+
// `health-check` and exits with `exitCode`. Mirrors how the real binary behaves:
|
|
12
|
+
// non-zero exit on an unhealthy index, but the JSON report still goes to stdout.
|
|
13
|
+
function stubHealthBin(t, { json, exitCode = 0 }) {
|
|
14
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-sessinit-'));
|
|
15
|
+
t.after(() => fs.rmSync(dir, { recursive: true, force: true }));
|
|
16
|
+
const bin = path.join(dir, 'code-graph-mcp');
|
|
17
|
+
const payload = String(json).replace(/'/g, `'\\''`);
|
|
18
|
+
fs.writeFileSync(bin, [
|
|
19
|
+
'#!/usr/bin/env bash',
|
|
20
|
+
`printf '%s' '${payload}'`,
|
|
21
|
+
`exit ${exitCode}`,
|
|
22
|
+
'',
|
|
23
|
+
].join('\n'));
|
|
24
|
+
fs.chmodSync(bin, 0o755);
|
|
25
|
+
return { bin, cwd: dir };
|
|
26
|
+
}
|
|
8
27
|
|
|
9
28
|
test('syncLifecycleConfig is exported as a callable helper', () => {
|
|
10
29
|
assert.equal(typeof syncLifecycleConfig, 'function');
|
|
@@ -26,6 +45,36 @@ test('ensureIndexFresh returns skipped when no index exists', () => {
|
|
|
26
45
|
}
|
|
27
46
|
});
|
|
28
47
|
|
|
48
|
+
test('indexNeedsRevalidation true when health-check reports index_version_stale', (t) => {
|
|
49
|
+
const { bin, cwd } = stubHealthBin(t, {
|
|
50
|
+
json: JSON.stringify({ healthy: true, nodes: 5, index_version_stale: true }),
|
|
51
|
+
exitCode: 0,
|
|
52
|
+
});
|
|
53
|
+
assert.equal(indexNeedsRevalidation(bin, cwd), true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('indexNeedsRevalidation false when index is current', (t) => {
|
|
57
|
+
const { bin, cwd } = stubHealthBin(t, {
|
|
58
|
+
json: JSON.stringify({ healthy: true, nodes: 5, index_version_stale: false }),
|
|
59
|
+
exitCode: 0,
|
|
60
|
+
});
|
|
61
|
+
assert.equal(indexNeedsRevalidation(bin, cwd), false);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('indexNeedsRevalidation recovers JSON from a non-zero exit (unhealthy index)', (t) => {
|
|
65
|
+
// health-check exits 1 on an empty/unhealthy index but still emits the report.
|
|
66
|
+
const { bin, cwd } = stubHealthBin(t, {
|
|
67
|
+
json: JSON.stringify({ healthy: false, nodes: 0, index_version_stale: true }),
|
|
68
|
+
exitCode: 1,
|
|
69
|
+
});
|
|
70
|
+
assert.equal(indexNeedsRevalidation(bin, cwd), true);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('indexNeedsRevalidation false on garbage output (never forces work off a bad probe)', (t) => {
|
|
74
|
+
const { bin, cwd } = stubHealthBin(t, { json: 'not json at all', exitCode: 0 });
|
|
75
|
+
assert.equal(indexNeedsRevalidation(bin, cwd), false);
|
|
76
|
+
});
|
|
77
|
+
|
|
29
78
|
test('verifyBinary returns available:true when binary is found and executable', () => {
|
|
30
79
|
const result = verifyBinary();
|
|
31
80
|
// In dev repo, binary should be found (target/release/code-graph-mcp)
|
|
@@ -58,24 +58,67 @@ if (!bin) {
|
|
|
58
58
|
process.exit(0);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// Render the standard health line from a parsed health-check report. An
|
|
62
|
+
// unhealthy/empty index (healthy:false, 0 nodes) is a real, accurate state and
|
|
63
|
+
// is distinct from "offline" \u2014 the binary ran fine, the index just has no data.
|
|
64
|
+
function renderHealth(s) {
|
|
65
|
+
const icon = s.healthy ? '\u2713' : '\u2717';
|
|
66
|
+
let line = `code-graph: ${icon} ${s.nodes} nodes | ${s.files} files`;
|
|
67
|
+
// Surface vector-backfill progress so a structurally-complete but only
|
|
68
|
+
// partially-embedded index reads as "healthy and improving" (the embedding
|
|
69
|
+
// backfill is resumable and runs in the background), not as something stuck.
|
|
70
|
+
// Hidden when embeddings are complete, unavailable (no model), or there are no
|
|
71
|
+
// nodes yet \u2014 only the in-progress states add the suffix.
|
|
72
|
+
if (s.nodes > 0) {
|
|
73
|
+
if (s.embedding_status === 'partial' && typeof s.embedding_coverage_pct === 'number') {
|
|
74
|
+
line += ` | ${s.embedding_coverage_pct}% vec`;
|
|
75
|
+
} else if (s.embedding_status === 'pending') {
|
|
76
|
+
line += ' | vec pending';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// An index built by an older extractor generation is usable but a rebuild is
|
|
80
|
+
// owed (a background incremental-index revalidates it). Flag it so a stale
|
|
81
|
+
// index doesn't masquerade as fully current.
|
|
82
|
+
if (s.index_version_stale) line += ' | \u21bb rebuilding';
|
|
83
|
+
if (s.watching) line += ' | watching';
|
|
84
|
+
return line;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// A genuine report carries a boolean `healthy` field. Returns null for anything
|
|
88
|
+
// that isn't a parseable report (empty string, crash banner, partial output).
|
|
89
|
+
function parseReport(text) {
|
|
90
|
+
try {
|
|
91
|
+
const s = JSON.parse(text);
|
|
92
|
+
return (s && typeof s.healthy === 'boolean') ? s : null;
|
|
93
|
+
} catch { return null; }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// No usable report: the binary couldn't produce one (crashed / missing / schema
|
|
97
|
+
// too new). A schema-version error means the resolved binary is OLDER than the
|
|
98
|
+
// index it is reading \u2014 the classic post-update window where the new binary is
|
|
99
|
+
// still downloading. That, or any pending update, is transient: show "updating"
|
|
100
|
+
// so the user knows it self-heals, rather than the misleading "offline".
|
|
101
|
+
function statusUnavailable(errText) {
|
|
102
|
+
const binaryOutdated = /schema version/i.test(errText || '');
|
|
103
|
+
return (binaryOutdated || updatePending()) ? 'code-graph: \u21bb updating' : 'code-graph: offline';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let report = null;
|
|
107
|
+
let errText = '';
|
|
61
108
|
try {
|
|
62
|
-
|
|
109
|
+
report = parseReport(execFileSync(bin, ['health-check', '--format', 'json'], {
|
|
63
110
|
timeout: 3000,
|
|
64
111
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
65
|
-
}).toString()
|
|
66
|
-
const s = JSON.parse(out);
|
|
67
|
-
const icon = s.healthy ? '\u2713' : '\u2717';
|
|
68
|
-
process.stdout.write(
|
|
69
|
-
`code-graph: ${icon} ${s.nodes} nodes | ${s.files} files` +
|
|
70
|
-
(s.watching ? ' | watching' : '')
|
|
71
|
-
);
|
|
112
|
+
}).toString());
|
|
72
113
|
} catch (e) {
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
114
|
+
// health-check exits NON-ZERO on an unhealthy/empty index but still writes the
|
|
115
|
+
// full JSON report to stdout. The binary ran fine \u2014 recover the report from the
|
|
116
|
+
// error object so an empty index shows "\u2717 0 nodes" rather than a bogus "offline".
|
|
117
|
+
report = parseReport(((e && e.stdout) || '').toString());
|
|
118
|
+
// Scan BOTH streams for the schema marker: the binary writes it to stderr, but
|
|
119
|
+
// an empty stderr Buffer is truthy, so `stderr || stdout` would never fall
|
|
120
|
+
// through — concatenate instead of short-circuiting.
|
|
121
|
+
errText = [(e && e.stderr) || '', (e && e.stdout) || ''].map(String).join('\n');
|
|
81
122
|
}
|
|
123
|
+
|
|
124
|
+
process.stdout.write(report ? renderHealth(report) : statusUnavailable(errText));
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// statusline.js renders code-graph health into the Claude Code status line.
|
|
3
|
+
// The states are easy to confuse, so each is pinned here with a stub binary:
|
|
4
|
+
//
|
|
5
|
+
// ✓/✗ N nodes | M files — health-check produced a report (exit 0 OR exit 1)
|
|
6
|
+
// ↻ updating — no report + (schema-version error OR pending update)
|
|
7
|
+
// offline — no report + genuine failure, nothing pending
|
|
8
|
+
//
|
|
9
|
+
// The critical regression this guards: health-check exits NON-ZERO on an
|
|
10
|
+
// empty/unhealthy index but still emits the full JSON report. statusline must
|
|
11
|
+
// render that report ("✗ 0 nodes"), NOT collapse it into "offline".
|
|
12
|
+
const test = require('node:test');
|
|
13
|
+
const assert = require('node:assert/strict');
|
|
14
|
+
const { execFileSync } = require('child_process');
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const os = require('os');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
|
|
19
|
+
const STATUSLINE = path.join(__dirname, 'statusline.js');
|
|
20
|
+
|
|
21
|
+
function mkHome(t) {
|
|
22
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-statusline-'));
|
|
23
|
+
t.after(() => fs.rmSync(dir, { recursive: true, force: true }));
|
|
24
|
+
return dir;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Write an executable shell stub named `code-graph-mcp` (find-binary's
|
|
28
|
+
// isNativeBinary requires that exact basename) and register it in the binary
|
|
29
|
+
// cache so findBinary() returns it before any dev/platform discovery.
|
|
30
|
+
// --version → prints `version` (must be >= pkg version to be "fresh")
|
|
31
|
+
// health-check ... → prints `report` to stdout, exits with `exitCode`
|
|
32
|
+
function installStubBinary(home, { report, stderr = '', exitCode = 0, version = '9.9.9' }) {
|
|
33
|
+
const binDir = path.join(home, 'stub-bin');
|
|
34
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
35
|
+
const binPath = path.join(binDir, 'code-graph-mcp');
|
|
36
|
+
const sh = (s) => String(s).replace(/'/g, `'\\''`);
|
|
37
|
+
const payload = typeof report === 'string' ? report : JSON.stringify(report);
|
|
38
|
+
const lines = [
|
|
39
|
+
'#!/usr/bin/env bash',
|
|
40
|
+
'if [ "$1" = "--version" ]; then',
|
|
41
|
+
` echo "${version}"; exit 0`,
|
|
42
|
+
'fi',
|
|
43
|
+
];
|
|
44
|
+
if (payload) lines.push(`printf '%s' '${sh(payload)}'`);
|
|
45
|
+
if (stderr) lines.push(`printf '%s' '${sh(stderr)}' >&2`);
|
|
46
|
+
lines.push(`exit ${exitCode}`, '');
|
|
47
|
+
fs.writeFileSync(binPath, lines.join('\n'));
|
|
48
|
+
fs.chmodSync(binPath, 0o755);
|
|
49
|
+
|
|
50
|
+
const cacheDir = path.join(home, '.cache', 'code-graph');
|
|
51
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
52
|
+
fs.writeFileSync(path.join(cacheDir, 'binary-path'), binPath);
|
|
53
|
+
return binPath;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function setUpdateState(home, state) {
|
|
57
|
+
const cacheDir = path.join(home, '.cache', 'code-graph');
|
|
58
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
59
|
+
fs.writeFileSync(path.join(cacheDir, 'update-state.json'), JSON.stringify(state));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Run statusline.js in `projectDir` (must contain .code-graph/index.db) with a
|
|
63
|
+
// sandboxed HOME, and return its stdout. PATH retains bash for the stub.
|
|
64
|
+
function runStatusline(home, projectDir) {
|
|
65
|
+
return execFileSync('node', [STATUSLINE], {
|
|
66
|
+
cwd: projectDir,
|
|
67
|
+
env: { ...process.env, HOME: home },
|
|
68
|
+
encoding: 'utf8',
|
|
69
|
+
}).trim();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function mkProject(home) {
|
|
73
|
+
const dir = path.join(home, 'project');
|
|
74
|
+
const cg = path.join(dir, '.code-graph');
|
|
75
|
+
fs.mkdirSync(cg, { recursive: true });
|
|
76
|
+
fs.writeFileSync(path.join(cg, 'index.db'), 'stub'); // existence is all statusline checks
|
|
77
|
+
return dir;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
test('healthy index → ✓ with node/file counts', (t) => {
|
|
81
|
+
const home = mkHome(t);
|
|
82
|
+
const project = mkProject(home);
|
|
83
|
+
installStubBinary(home, {
|
|
84
|
+
report: { healthy: true, nodes: 3145, files: 205, watching: true },
|
|
85
|
+
exitCode: 0,
|
|
86
|
+
});
|
|
87
|
+
assert.equal(runStatusline(home, project), 'code-graph: ✓ 3145 nodes | 205 files | watching');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('empty index, health-check EXIT 1 with JSON → ✗ 0 nodes (not offline)', (t) => {
|
|
91
|
+
// The core regression: non-zero exit must not mask a valid report.
|
|
92
|
+
const home = mkHome(t);
|
|
93
|
+
const project = mkProject(home);
|
|
94
|
+
installStubBinary(home, {
|
|
95
|
+
report: { healthy: false, nodes: 0, files: 0, watching: false },
|
|
96
|
+
exitCode: 1,
|
|
97
|
+
});
|
|
98
|
+
assert.equal(runStatusline(home, project), 'code-graph: ✗ 0 nodes | 0 files');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('no report + update pending → updating', (t) => {
|
|
102
|
+
const home = mkHome(t);
|
|
103
|
+
const project = mkProject(home);
|
|
104
|
+
installStubBinary(home, { report: 'boom', exitCode: 1 });
|
|
105
|
+
setUpdateState(home, { updateAvailable: true });
|
|
106
|
+
assert.equal(runStatusline(home, project), 'code-graph: ↻ updating');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('schema-version error on stderr (no report) → updating', (t) => {
|
|
110
|
+
const home = mkHome(t);
|
|
111
|
+
const project = mkProject(home);
|
|
112
|
+
// The binary writes schema errors to stderr; no parseable report on stdout.
|
|
113
|
+
installStubBinary(home, {
|
|
114
|
+
report: '',
|
|
115
|
+
stderr: 'Error: Database schema version v9 is newer than supported v8',
|
|
116
|
+
exitCode: 1,
|
|
117
|
+
});
|
|
118
|
+
assert.equal(runStatusline(home, project), 'code-graph: ↻ updating');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('genuine crash (no report, nothing pending) → offline', (t) => {
|
|
122
|
+
const home = mkHome(t);
|
|
123
|
+
const project = mkProject(home);
|
|
124
|
+
installStubBinary(home, { report: 'segfault, core dumped', exitCode: 139 });
|
|
125
|
+
assert.equal(runStatusline(home, project), 'code-graph: offline');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('partial embeddings show vector coverage', (t) => {
|
|
129
|
+
const home = mkHome(t);
|
|
130
|
+
const project = mkProject(home);
|
|
131
|
+
installStubBinary(home, {
|
|
132
|
+
report: { healthy: true, nodes: 14119, files: 922, embedding_status: 'partial', embedding_coverage_pct: 60 },
|
|
133
|
+
exitCode: 0,
|
|
134
|
+
});
|
|
135
|
+
assert.equal(runStatusline(home, project), 'code-graph: ✓ 14119 nodes | 922 files | 60% vec');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test('pending embeddings show "vec pending"', (t) => {
|
|
139
|
+
const home = mkHome(t);
|
|
140
|
+
const project = mkProject(home);
|
|
141
|
+
installStubBinary(home, {
|
|
142
|
+
report: { healthy: true, nodes: 14119, files: 922, embedding_status: 'pending', embedding_coverage_pct: 0 },
|
|
143
|
+
exitCode: 0,
|
|
144
|
+
});
|
|
145
|
+
assert.equal(runStatusline(home, project), 'code-graph: ✓ 14119 nodes | 922 files | vec pending');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test('complete embeddings add no vector suffix', (t) => {
|
|
149
|
+
const home = mkHome(t);
|
|
150
|
+
const project = mkProject(home);
|
|
151
|
+
installStubBinary(home, {
|
|
152
|
+
report: { healthy: true, nodes: 14119, files: 922, embedding_status: 'complete', embedding_coverage_pct: 100 },
|
|
153
|
+
exitCode: 0,
|
|
154
|
+
});
|
|
155
|
+
assert.equal(runStatusline(home, project), 'code-graph: ✓ 14119 nodes | 922 files');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('version-stale index shows rebuilding marker', (t) => {
|
|
159
|
+
const home = mkHome(t);
|
|
160
|
+
const project = mkProject(home);
|
|
161
|
+
installStubBinary(home, {
|
|
162
|
+
report: { healthy: true, nodes: 14119, files: 922, embedding_status: 'complete', index_version_stale: true },
|
|
163
|
+
exitCode: 0,
|
|
164
|
+
});
|
|
165
|
+
assert.equal(runStatusline(home, project), 'code-graph: ✓ 14119 nodes | 922 files | ↻ rebuilding');
|
|
166
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdsrs/code-graph",
|
|
3
|
-
"version": "0.74.
|
|
3
|
+
"version": "0.74.6",
|
|
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.74.
|
|
39
|
-
"@sdsrs/code-graph-linux-arm64": "0.74.
|
|
40
|
-
"@sdsrs/code-graph-darwin-x64": "0.74.
|
|
41
|
-
"@sdsrs/code-graph-darwin-arm64": "0.74.
|
|
42
|
-
"@sdsrs/code-graph-win32-x64": "0.74.
|
|
38
|
+
"@sdsrs/code-graph-linux-x64": "0.74.6",
|
|
39
|
+
"@sdsrs/code-graph-linux-arm64": "0.74.6",
|
|
40
|
+
"@sdsrs/code-graph-darwin-x64": "0.74.6",
|
|
41
|
+
"@sdsrs/code-graph-darwin-arm64": "0.74.6",
|
|
42
|
+
"@sdsrs/code-graph-win32-x64": "0.74.6"
|
|
43
43
|
}
|
|
44
44
|
}
|