@sdsrs/code-graph 0.113.0 → 0.114.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.
|
@@ -55,6 +55,191 @@ function classifyEmbeddings(hc) {
|
|
|
55
55
|
return { name: 'Embeddings', status: 'ok', detail: `hybrid — embeddings complete (${done}/${total})` };
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Classify the `integrity` block that `health-check --json` has carried since
|
|
60
|
+
* v0.113.0 (audit DB-1). Pure, same as `classifyEmbeddings`.
|
|
61
|
+
*
|
|
62
|
+
* Severity is deliberately NOT uniform across the three probes:
|
|
63
|
+
* - `quick_check` complaining means pages do not read back — the index is
|
|
64
|
+
* corrupt, and only a rebuild fixes it. Error + fixId.
|
|
65
|
+
* - `fts_drift != 0` means the FTS5 index and `nodes` disagree, so search
|
|
66
|
+
* silently misses (or invents) symbols. Wrong answers, no crash. Warn + fixId.
|
|
67
|
+
* - `orphan_vectors != 0` is dead weight that skews coverage math; answers stay
|
|
68
|
+
* correct. It is DISCLOSED in the detail but does not raise an issue on its
|
|
69
|
+
* own: the only repair is a full rebuild, and a permanent warn with a
|
|
70
|
+
* disproportionate fix is how `doctor` ends up exiting 1 forever on installs
|
|
71
|
+
* that are fine (the MCP server already reaps these at startup; a CLI-only
|
|
72
|
+
* install is exactly who would be stuck with it).
|
|
73
|
+
* `null` on any probe means "could not be measured", never a fault.
|
|
74
|
+
* @returns {{name:string, status:'ok'|'warn'|'error'|'skip', detail:string, fixId?:string}}
|
|
75
|
+
*/
|
|
76
|
+
function classifyIntegrity(hc) {
|
|
77
|
+
const it = hc && hc.integrity;
|
|
78
|
+
if (!it || typeof it !== 'object') {
|
|
79
|
+
// Binary predates the probes. Say so rather than inventing a verdict — an
|
|
80
|
+
// absent measurement is not a passing one.
|
|
81
|
+
return { name: 'Integrity', status: 'skip', detail: 'not reported by this binary version' };
|
|
82
|
+
}
|
|
83
|
+
const orphanNote = it.orphan_vectors ? `; ${it.orphan_vectors} orphan vector(s)` : '';
|
|
84
|
+
const qc = it.quick_check;
|
|
85
|
+
if (typeof qc === 'string' && qc !== 'ok' && qc !== 'skipped_large') {
|
|
86
|
+
return {
|
|
87
|
+
name: 'Integrity', status: 'error', fixId: 'index-corrupt',
|
|
88
|
+
detail: `database is CORRUPT — quick_check: ${qc}${orphanNote}`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (typeof it.fts_drift === 'number' && it.fts_drift !== 0) {
|
|
92
|
+
return {
|
|
93
|
+
name: 'Integrity', status: 'warn', fixId: 'index-corrupt',
|
|
94
|
+
detail: `FTS index drifted from nodes by ${it.fts_drift} row(s) — search silently misses symbols${orphanNote}`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (qc === 'skipped_large') {
|
|
98
|
+
// The size gate skipped the page scan on purpose. Reporting `ok` here would
|
|
99
|
+
// claim a check that never ran.
|
|
100
|
+
return { name: 'Integrity', status: 'skip',
|
|
101
|
+
detail: `page check skipped (index over the size gate) — run: code-graph-mcp health-check --deep${orphanNote}` };
|
|
102
|
+
}
|
|
103
|
+
if (qc == null) {
|
|
104
|
+
return { name: 'Integrity', status: 'skip', detail: `page check unavailable${orphanNote}` };
|
|
105
|
+
}
|
|
106
|
+
return { name: 'Integrity', status: 'ok', detail: `quick_check ok, FTS in sync${orphanNote}` };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Turn a parsed `health-check --json` payload into doctor rows.
|
|
111
|
+
*
|
|
112
|
+
* Extracted so the success path and the recovered-from-stdout path (below)
|
|
113
|
+
* cannot classify the same payload differently. Pure.
|
|
114
|
+
*/
|
|
115
|
+
function classifyHealthReport(hc) {
|
|
116
|
+
// No-index short-circuit — binary deliberately returns a structured JSON with
|
|
117
|
+
// reason='no_index' instead of bailing, so we can route to the index-empty fix
|
|
118
|
+
// without grepping stderr.
|
|
119
|
+
if (hc.reason === 'no_index') {
|
|
120
|
+
return [
|
|
121
|
+
{ name: 'Schema', status: 'ok', detail: 'binary ok (no index yet)' },
|
|
122
|
+
{ name: 'Index', status: 'warn', detail: 'missing — not indexed yet', fixId: 'index-empty' },
|
|
123
|
+
{ name: 'Embeddings', status: 'skip', detail: 'no index' },
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
// The database could not be opened at all, so schema/nodes/embeddings are not
|
|
127
|
+
// unknown-but-probably-fine, they are unmeasurable. Reporting `Schema: ok
|
|
128
|
+
// vnull` off the zeroed payload would be a fabricated pass; the Integrity row
|
|
129
|
+
// below carries the real verdict and the `index-corrupt` fix.
|
|
130
|
+
if (hc.reason === 'corrupt') {
|
|
131
|
+
return [
|
|
132
|
+
{ name: 'Schema', status: 'skip', detail: 'index unreadable' },
|
|
133
|
+
{ name: 'Index', status: 'skip', detail: 'index unreadable' },
|
|
134
|
+
{ name: 'Embeddings', status: 'skip', detail: 'index unreadable' },
|
|
135
|
+
classifyIntegrity(hc),
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
const rows = [];
|
|
139
|
+
if (hc.issue && String(hc.issue).includes('schema')) {
|
|
140
|
+
rows.push({ name: 'Schema', status: 'warn', detail: hc.issue, fixId: 'schema-mismatch' });
|
|
141
|
+
} else {
|
|
142
|
+
rows.push({ name: 'Schema', status: 'ok', detail: `v${hc.schema_version}` });
|
|
143
|
+
}
|
|
144
|
+
if (hc.nodes === 0) {
|
|
145
|
+
rows.push({ name: 'Index', status: 'warn', detail: 'empty', fixId: 'index-empty' });
|
|
146
|
+
} else {
|
|
147
|
+
const age = hc.index_age ? ` (${hc.index_age})` : '';
|
|
148
|
+
rows.push({
|
|
149
|
+
name: 'Index', status: 'ok',
|
|
150
|
+
detail: `${hc.nodes} nodes, ${hc.edges} edges, ${hc.files} files${age}`,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
// Embeddings / vector availability — pure classifier; warns on FTS5-only
|
|
154
|
+
// degradation (model missing/not loaded) instead of false-greening it.
|
|
155
|
+
rows.push(classifyEmbeddings(hc));
|
|
156
|
+
rows.push(classifyIntegrity(hc));
|
|
157
|
+
return rows;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Recover a health-check payload from a buffer, or null if it isn't one.
|
|
162
|
+
*
|
|
163
|
+
* `health-check --json` prints the FULL report to stdout and THEN exits 1 when
|
|
164
|
+
* the index is unhealthy, so `execFileSync` throwing does not mean there is no
|
|
165
|
+
* report — it means there is a report saying something is wrong. Requiring a
|
|
166
|
+
* key only this command emits keeps unrelated stdout (a panic, a wrapper's
|
|
167
|
+
* noise) from being read as a clean bill of health.
|
|
168
|
+
*/
|
|
169
|
+
function parseHealthPayload(buf) {
|
|
170
|
+
if (!buf) return null;
|
|
171
|
+
try {
|
|
172
|
+
const obj = JSON.parse(buf.toString().trim());
|
|
173
|
+
if (!obj || typeof obj !== 'object' || Array.isArray(obj)) return null;
|
|
174
|
+
// `reason` covers payloads the binary emits BEFORE it can read a schema
|
|
175
|
+
// version (no_index, corrupt). Keying only on `schema_version` meant the
|
|
176
|
+
// corrupt payload — the one case where recovering the report matters most —
|
|
177
|
+
// was rejected and fell through to `binary-broken`. Caught by an end-to-end
|
|
178
|
+
// run against a real clobbered index; neither side's unit tests could see
|
|
179
|
+
// it, because each was asserted against its own fixture.
|
|
180
|
+
const looksLikeReport = 'schema_version' in obj || typeof obj.reason === 'string';
|
|
181
|
+
return looksLikeReport ? obj : null;
|
|
182
|
+
} catch {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Spawn `health-check --json`. Separate + injectable: see `rebuildIndexInPlace`. */
|
|
188
|
+
function runHealthCheckCli(binary) {
|
|
189
|
+
// Deliberately NOT `--deep`. That flag forces the integrity pragmas the
|
|
190
|
+
// default path skips above INTEGRITY_PRAGMA_MAX_BYTES, and quick_check reads
|
|
191
|
+
// every page at ~2.4 ms/MB — a multi-GB index would blow the 5 s budget below
|
|
192
|
+
// and report a phantom "health-check failed" instead of the integrity answer
|
|
193
|
+
// it went looking for. Raising the timeout to fit trades that for a doctor run
|
|
194
|
+
// that appears hung. `--deep` stays a user-invoked escape hatch until this
|
|
195
|
+
// call can size its own budget from the index.
|
|
196
|
+
return execFileSync(binary, ['health-check', '--json'], hidden({
|
|
197
|
+
cwd: process.cwd(),
|
|
198
|
+
timeout: 5000,
|
|
199
|
+
encoding: 'utf8',
|
|
200
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
201
|
+
})).trim();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Schema / Index / Embeddings / Integrity rows from the binary's health-check.
|
|
206
|
+
*
|
|
207
|
+
* The failure branches are the point of this function existing separately.
|
|
208
|
+
* `health-check --json` prints the FULL report to stdout and THEN exits 1 when
|
|
209
|
+
* the index is unhealthy, so `execFileSync` throwing does not mean the probe
|
|
210
|
+
* failed. The old code read the throw as "the binary is broken" and emitted
|
|
211
|
+
* `Schema: error … fixId:'binary-broken'` — a fixId `runRepairs` has no case
|
|
212
|
+
* for. Net effect: the integrity probes added in v0.113.0 never reached the
|
|
213
|
+
* consumer they were built for, and a genuinely corrupt index was reported as a
|
|
214
|
+
* binary problem with no repair offered.
|
|
215
|
+
*/
|
|
216
|
+
function healthRows(binary, { runHealthCheck = runHealthCheckCli } = {}) {
|
|
217
|
+
try {
|
|
218
|
+
return classifyHealthReport(JSON.parse(runHealthCheck(binary)));
|
|
219
|
+
} catch (e) {
|
|
220
|
+
const recovered = parseHealthPayload(e.stdout);
|
|
221
|
+
if (recovered) return classifyHealthReport(recovered);
|
|
222
|
+
|
|
223
|
+
const rawStderr = e.stderr ? e.stderr.toString() : '';
|
|
224
|
+
const msg = rawStderr ? rawStderr.trim().slice(0, 100) : e.message.slice(0, 100);
|
|
225
|
+
// "No index found" is a missing-index situation, not a broken binary — the
|
|
226
|
+
// index-empty fix path knows how to create one. Without this branch the
|
|
227
|
+
// fixId routes to nothing and the report shows "0/1 addressed".
|
|
228
|
+
if (rawStderr.includes('No index found')) {
|
|
229
|
+
return [
|
|
230
|
+
{ name: 'Schema', status: 'ok', detail: 'binary ok (no index yet)' },
|
|
231
|
+
{ name: 'Index', status: 'warn', detail: 'missing — not indexed yet', fixId: 'index-empty' },
|
|
232
|
+
{ name: 'Embeddings', status: 'skip', detail: 'no index' },
|
|
233
|
+
];
|
|
234
|
+
}
|
|
235
|
+
return [
|
|
236
|
+
{ name: 'Schema', status: 'error', detail: `health-check failed: ${msg}`, fixId: 'binary-broken' },
|
|
237
|
+
{ name: 'Index', status: 'skip', detail: 'health-check failed' },
|
|
238
|
+
{ name: 'Embeddings', status: 'skip', detail: 'health-check failed' },
|
|
239
|
+
];
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
58
243
|
/**
|
|
59
244
|
* Run all diagnostic checks. Returns an array of:
|
|
60
245
|
* { name: string, status: 'ok'|'warn'|'error'|'skip', detail: string, fixId?: string }
|
|
@@ -134,73 +319,9 @@ function runDiagnostics({ checkOnly = false } = {}) {
|
|
|
134
319
|
results.push({ name: 'Source fresh', status: 'skip', detail: 'not dev mode' });
|
|
135
320
|
}
|
|
136
321
|
|
|
137
|
-
// 4. health-check (schema, index, embeddings) via binary --json
|
|
322
|
+
// 4. health-check (schema, index, embeddings, integrity) via binary --json
|
|
138
323
|
if (execOk) {
|
|
139
|
-
|
|
140
|
-
const cwd = process.cwd();
|
|
141
|
-
// Deliberately NOT `--deep`. That flag forces the integrity pragmas the
|
|
142
|
-
// default path skips above INTEGRITY_PRAGMA_MAX_BYTES, and quick_check
|
|
143
|
-
// reads every page at ~2.4 ms/MB — a multi-GB index would blow the 5 s
|
|
144
|
-
// budget below and report a phantom "health-check failed" instead of the
|
|
145
|
-
// integrity answer it went looking for. Raising the timeout to fit trades
|
|
146
|
-
// that for a doctor run that appears hung. `--deep` stays a user-invoked
|
|
147
|
-
// escape hatch until this call can size its own budget from the index.
|
|
148
|
-
const hcOutput = execFileSync(binary, ['health-check', '--json'], hidden({
|
|
149
|
-
cwd,
|
|
150
|
-
timeout: 5000,
|
|
151
|
-
encoding: 'utf8',
|
|
152
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
153
|
-
})).trim();
|
|
154
|
-
const hc = JSON.parse(hcOutput);
|
|
155
|
-
|
|
156
|
-
// No-index short-circuit — binary deliberately returns a structured
|
|
157
|
-
// JSON with reason='no_index' instead of bailing, so we can route to
|
|
158
|
-
// the index-empty fix without grepping stderr. Falls through to the
|
|
159
|
-
// rest of runDiagnostics so Auto-update / Hooks still report.
|
|
160
|
-
if (hc.reason === 'no_index') {
|
|
161
|
-
results.push({ name: 'Schema', status: 'ok', detail: 'binary ok (no index yet)' });
|
|
162
|
-
results.push({ name: 'Index', status: 'warn', detail: 'missing — not indexed yet', fixId: 'index-empty' });
|
|
163
|
-
results.push({ name: 'Embeddings', status: 'skip', detail: 'no index' });
|
|
164
|
-
} else {
|
|
165
|
-
// Schema
|
|
166
|
-
if (hc.issue && hc.issue.includes('schema')) {
|
|
167
|
-
results.push({ name: 'Schema', status: 'warn', detail: hc.issue, fixId: 'schema-mismatch' });
|
|
168
|
-
} else {
|
|
169
|
-
results.push({ name: 'Schema', status: 'ok', detail: `v${hc.schema_version}` });
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Index
|
|
173
|
-
if (hc.nodes === 0) {
|
|
174
|
-
results.push({ name: 'Index', status: 'warn', detail: 'empty', fixId: 'index-empty' });
|
|
175
|
-
} else {
|
|
176
|
-
const age = hc.index_age ? ` (${hc.index_age})` : '';
|
|
177
|
-
results.push({
|
|
178
|
-
name: 'Index',
|
|
179
|
-
status: 'ok',
|
|
180
|
-
detail: `${hc.nodes} nodes, ${hc.edges} edges, ${hc.files} files${age}`,
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Embeddings / vector availability — pure classifier; warns on FTS5-only
|
|
185
|
-
// degradation (model missing/not loaded) instead of false-greening it.
|
|
186
|
-
results.push(classifyEmbeddings(hc));
|
|
187
|
-
}
|
|
188
|
-
} catch (e) {
|
|
189
|
-
const rawStderr = e.stderr ? e.stderr.toString() : '';
|
|
190
|
-
const msg = rawStderr ? rawStderr.trim().slice(0, 100) : e.message.slice(0, 100);
|
|
191
|
-
// "No index found" is a missing-index situation, not a broken binary —
|
|
192
|
-
// the index-empty fix path knows how to create one. Without this branch
|
|
193
|
-
// the fixId routes to nothing and the report shows "0/1 addressed".
|
|
194
|
-
if (rawStderr.includes('No index found')) {
|
|
195
|
-
results.push({ name: 'Schema', status: 'ok', detail: 'binary ok (no index yet)' });
|
|
196
|
-
results.push({ name: 'Index', status: 'warn', detail: 'missing — not indexed yet', fixId: 'index-empty' });
|
|
197
|
-
results.push({ name: 'Embeddings', status: 'skip', detail: 'no index' });
|
|
198
|
-
} else {
|
|
199
|
-
results.push({ name: 'Schema', status: 'error', detail: `health-check failed: ${msg}`, fixId: 'binary-broken' });
|
|
200
|
-
results.push({ name: 'Index', status: 'skip', detail: 'health-check failed' });
|
|
201
|
-
results.push({ name: 'Embeddings', status: 'skip', detail: 'health-check failed' });
|
|
202
|
-
}
|
|
203
|
-
}
|
|
324
|
+
results.push(...healthRows(binary));
|
|
204
325
|
} else {
|
|
205
326
|
results.push({ name: 'Schema', status: 'skip', detail: 'binary not executable' });
|
|
206
327
|
results.push({ name: 'Index', status: 'skip', detail: 'binary not executable' });
|
|
@@ -542,6 +663,54 @@ function updateIncompleteResolved({ readStateFile = readUpdateState } = {}) {
|
|
|
542
663
|
return !(state && state.updateAvailable && state.binaryUpdated === false);
|
|
543
664
|
}
|
|
544
665
|
|
|
666
|
+
/**
|
|
667
|
+
* Mirror of the `index-corrupt` diagnosis: re-run the probes against the
|
|
668
|
+
* database the rebuild just produced and re-classify with the SAME function the
|
|
669
|
+
* diagnosis used, so "resolved" cannot mean something different from "not
|
|
670
|
+
* raised". A rebuild that exits 0 over failing hardware still fails this.
|
|
671
|
+
*/
|
|
672
|
+
function integrityResolved({ probe = probeHealth, classify = classifyIntegrity } = {}) {
|
|
673
|
+
const hc = probe();
|
|
674
|
+
if (!hc) return false;
|
|
675
|
+
const row = classify(hc);
|
|
676
|
+
return row.status !== 'error' && row.status !== 'warn';
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Run `rebuild-index --confirm`. Returns false when there is no binary to run
|
|
681
|
+
* it with; throws whatever the child failed with (including the deliberate bail
|
|
682
|
+
* when another process holds the index lock, added in v0.113.0).
|
|
683
|
+
*
|
|
684
|
+
* Separate + injectable because `execFileSync` is destructured at load here, so
|
|
685
|
+
* a test that patches `child_process.execFileSync` after the fact stubs nothing
|
|
686
|
+
* and silently exercises the real spawn.
|
|
687
|
+
*/
|
|
688
|
+
function rebuildIndexInPlace({ find = findBinary } = {}) {
|
|
689
|
+
const binary = find();
|
|
690
|
+
if (!binary) return false;
|
|
691
|
+
execFileSync(binary, ['rebuild-index', '--confirm'], hidden({
|
|
692
|
+
cwd: process.cwd(),
|
|
693
|
+
stdio: 'inherit',
|
|
694
|
+
timeout: 600000, // full reindex, not a diff — same budget as a build
|
|
695
|
+
}));
|
|
696
|
+
return true;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Read a `health-check --json` payload, tolerating the exit-1-on-unhealthy
|
|
701
|
+
* contract (the report is on stdout either way). null when there is no payload.
|
|
702
|
+
*/
|
|
703
|
+
function probeHealth({ find = findBinary } = {}) {
|
|
704
|
+
const binary = find();
|
|
705
|
+
if (!binary) return null;
|
|
706
|
+
const opts = hidden({ cwd: process.cwd(), timeout: 5000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
707
|
+
try {
|
|
708
|
+
return parseHealthPayload(execFileSync(binary, ['health-check', '--json'], opts));
|
|
709
|
+
} catch (e) {
|
|
710
|
+
return parseHealthPayload(e.stdout);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
545
714
|
function readUpdateState() {
|
|
546
715
|
try { return readJson(path.join(CACHE_DIR, 'update-state.json')); } catch { return null; }
|
|
547
716
|
}
|
|
@@ -580,6 +749,8 @@ function runRepairs(results, {
|
|
|
580
749
|
runAutoUpdate = triggerAutoUpdateCheck,
|
|
581
750
|
binaryResolved = binaryVersionResolved,
|
|
582
751
|
updateResolved = updateIncompleteResolved,
|
|
752
|
+
integrityOk = integrityResolved,
|
|
753
|
+
rebuildIndex = rebuildIndexInPlace,
|
|
583
754
|
} = {}) {
|
|
584
755
|
const fixable = results.filter(r => r.fixId);
|
|
585
756
|
if (fixable.length === 0) return 0;
|
|
@@ -785,6 +956,32 @@ function runRepairs(results, {
|
|
|
785
956
|
break;
|
|
786
957
|
}
|
|
787
958
|
|
|
959
|
+
case 'index-corrupt': {
|
|
960
|
+
// `incremental-index` (the index-empty arm) cannot help here: it opens
|
|
961
|
+
// the same damaged file and diffs against it. The index is a rebuildable
|
|
962
|
+
// cache, and this is the command health-check itself prints.
|
|
963
|
+
console.log('\n Rebuilding corrupt index from scratch...');
|
|
964
|
+
console.log(' → code-graph-mcp rebuild-index --confirm');
|
|
965
|
+
try {
|
|
966
|
+
if (!rebuildIndex()) break; // no binary to run it with
|
|
967
|
+
} catch {
|
|
968
|
+
// Includes the deliberate bail when another process holds the index
|
|
969
|
+
// lock (v0.113.0), which is a refusal, not a failure to repair.
|
|
970
|
+
console.log(' ❌ Index rebuild failed — see the error above');
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
// Exit 0 says the command ran, not that the corruption cleared. Ask the
|
|
974
|
+
// database again, the same way the hooks arm re-scans after install().
|
|
975
|
+
if (integrityOk()) {
|
|
976
|
+
console.log(' ✅ Index rebuilt — integrity checks now pass');
|
|
977
|
+
fixed++;
|
|
978
|
+
} else {
|
|
979
|
+
console.log(' ❌ Rebuild completed but the integrity check still fails');
|
|
980
|
+
console.log(' The problem may be the filesystem or disk, not the index.');
|
|
981
|
+
}
|
|
982
|
+
break;
|
|
983
|
+
}
|
|
984
|
+
|
|
788
985
|
case 'schema-mismatch': {
|
|
789
986
|
console.log('\n Schema migration happens automatically when the binary runs.');
|
|
790
987
|
console.log(' If binary is older than DB, update the binary first.');
|
|
@@ -832,7 +1029,7 @@ function runDoctor(opts = {}) {
|
|
|
832
1029
|
return { results, issueCount: issues.length, unresolved };
|
|
833
1030
|
}
|
|
834
1031
|
|
|
835
|
-
module.exports = { runDiagnostics, formatReport, runRepairs, runDoctor, runDoctorCli, parseDoctorArgs, unresolvedCount, surveyHookCoverage, relicRepairGuard, classifyEmbeddings, detectEmbedModel, devBuildCommand, binaryVersionResolved, updateIncompleteResolved, autoUpdateNoOpReason };
|
|
1032
|
+
module.exports = { runDiagnostics, formatReport, runRepairs, runDoctor, runDoctorCli, parseDoctorArgs, unresolvedCount, surveyHookCoverage, relicRepairGuard, classifyEmbeddings, classifyIntegrity, classifyHealthReport, parseHealthPayload, integrityResolved, healthRows, detectEmbedModel, devBuildCommand, binaryVersionResolved, updateIncompleteResolved, autoUpdateNoOpReason };
|
|
836
1033
|
|
|
837
1034
|
// Shared by BOTH doctor entry points: `node doctor.js …` and `node lifecycle.js
|
|
838
1035
|
// doctor …`. It exists as one function because the first version of this guard
|
|
@@ -30,7 +30,7 @@ jobs:
|
|
|
30
30
|
node-version: '20'
|
|
31
31
|
- name: Build snapshot
|
|
32
32
|
run: |
|
|
33
|
-
npx -y -p @sdsrs/code-graph@0.
|
|
33
|
+
npx -y -p @sdsrs/code-graph@0.114.0 code-graph-mcp snapshot create --out snapshot.db
|
|
34
34
|
zstd -9 snapshot.db -o snapshot.db.zst
|
|
35
35
|
mv snapshot.db.zst "code-graph-snapshot-${GITHUB_SHA:0:7}.db.zst"
|
|
36
36
|
- 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.114.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.114.0",
|
|
39
|
+
"@sdsrs/code-graph-linux-arm64": "0.114.0",
|
|
40
|
+
"@sdsrs/code-graph-darwin-x64": "0.114.0",
|
|
41
|
+
"@sdsrs/code-graph-darwin-arm64": "0.114.0",
|
|
42
|
+
"@sdsrs/code-graph-win32-x64": "0.114.0"
|
|
43
43
|
}
|
|
44
44
|
}
|