@sdsrs/code-graph 0.7.11 → 0.7.13
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.
|
@@ -1,56 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
{
|
|
5
|
-
"matcher": "tool == \"Edit\"",
|
|
6
|
-
"hooks": [
|
|
7
|
-
{
|
|
8
|
-
"type": "command",
|
|
9
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/pre-edit-guide.js\"",
|
|
10
|
-
"timeout": 4
|
|
11
|
-
}
|
|
12
|
-
],
|
|
13
|
-
"description": "Auto-inject impact analysis when editing function definitions with 2+ callers"
|
|
14
|
-
}
|
|
15
|
-
],
|
|
16
|
-
"PostToolUse": [
|
|
17
|
-
{
|
|
18
|
-
"matcher": "tool == \"Write\" || tool == \"Edit\"",
|
|
19
|
-
"hooks": [
|
|
20
|
-
{
|
|
21
|
-
"type": "command",
|
|
22
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/incremental-index.js\"",
|
|
23
|
-
"timeout": 10
|
|
24
|
-
}
|
|
25
|
-
],
|
|
26
|
-
"description": "Auto-update code graph index after file edits"
|
|
27
|
-
}
|
|
28
|
-
],
|
|
29
|
-
"UserPromptSubmit": [
|
|
30
|
-
{
|
|
31
|
-
"matcher": "",
|
|
32
|
-
"hooks": [
|
|
33
|
-
{
|
|
34
|
-
"type": "command",
|
|
35
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/user-prompt-context.js\"",
|
|
36
|
-
"timeout": 5
|
|
37
|
-
}
|
|
38
|
-
],
|
|
39
|
-
"description": "Inject code-graph structural context (impact, overview, callgraph) based on user intent"
|
|
40
|
-
}
|
|
41
|
-
],
|
|
42
|
-
"SessionStart": [
|
|
43
|
-
{
|
|
44
|
-
"matcher": "startup",
|
|
45
|
-
"hooks": [
|
|
46
|
-
{
|
|
47
|
-
"type": "command",
|
|
48
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/session-init.js\"",
|
|
49
|
-
"timeout": 5
|
|
50
|
-
}
|
|
51
|
-
],
|
|
52
|
-
"description": "StatusLine self-heal, lifecycle sync, project map injection at session start"
|
|
53
|
-
}
|
|
54
|
-
]
|
|
55
|
-
}
|
|
2
|
+
"_note": "Hooks registered to settings.json by lifecycle.js — hooks.json auto-loading is unreliable",
|
|
3
|
+
"hooks": {}
|
|
56
4
|
}
|
|
@@ -150,7 +150,8 @@ function cleanupDisabledStatusline() {
|
|
|
150
150
|
return { cleaned: false, settingsChanged: false };
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
|
|
153
|
+
let settingsChanged = detachStatuslineIntegration(settings);
|
|
154
|
+
if (removeHooksFromSettings(settings)) settingsChanged = true;
|
|
154
155
|
if (settingsChanged) {
|
|
155
156
|
writeJsonAtomic(SETTINGS_PATH, settings);
|
|
156
157
|
}
|
|
@@ -216,6 +217,91 @@ function migrateOldPluginIds(settings) {
|
|
|
216
217
|
return changed;
|
|
217
218
|
}
|
|
218
219
|
|
|
220
|
+
// --- Hook Registration ---
|
|
221
|
+
// Plugin system's hooks.json auto-loading is unreliable (observed across GSD,
|
|
222
|
+
// superpowers, code-graph-mcp). Write hooks directly to settings.json instead.
|
|
223
|
+
// Same strategy as claude-mem-lite. hooks.json is kept empty to prevent double-firing.
|
|
224
|
+
|
|
225
|
+
const OUR_HOOK_SCRIPTS = ['session-init.js', 'incremental-index.js', 'user-prompt-context.js', 'pre-edit-guide.js'];
|
|
226
|
+
|
|
227
|
+
function isOurHookEntry(entry) {
|
|
228
|
+
if (!entry || !entry.hooks) return false;
|
|
229
|
+
return entry.hooks.some(h =>
|
|
230
|
+
h.command && OUR_HOOK_SCRIPTS.some(s => h.command.includes(s)) &&
|
|
231
|
+
h.command.includes('code-graph')
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function hookCommand(scriptName) {
|
|
236
|
+
return `node ${JSON.stringify(path.join(PLUGIN_ROOT, 'scripts', scriptName))}`;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function getHookDefinitions() {
|
|
240
|
+
return {
|
|
241
|
+
SessionStart: [{
|
|
242
|
+
matcher: 'startup|clear|compact',
|
|
243
|
+
hooks: [{ type: 'command', command: hookCommand('session-init.js'), timeout: 5 }],
|
|
244
|
+
description: 'StatusLine self-heal, lifecycle sync, project map injection',
|
|
245
|
+
}],
|
|
246
|
+
PreToolUse: [{
|
|
247
|
+
matcher: 'tool == "Edit"',
|
|
248
|
+
hooks: [{ type: 'command', command: hookCommand('pre-edit-guide.js'), timeout: 4 }],
|
|
249
|
+
description: 'Auto-inject impact analysis when editing functions with 2+ callers',
|
|
250
|
+
}],
|
|
251
|
+
PostToolUse: [{
|
|
252
|
+
matcher: 'tool == "Write" || tool == "Edit"',
|
|
253
|
+
hooks: [{ type: 'command', command: hookCommand('incremental-index.js'), timeout: 10 }],
|
|
254
|
+
description: 'Auto-update code graph index after file edits',
|
|
255
|
+
}],
|
|
256
|
+
UserPromptSubmit: [{
|
|
257
|
+
matcher: '',
|
|
258
|
+
hooks: [{ type: 'command', command: hookCommand('user-prompt-context.js'), timeout: 5 }],
|
|
259
|
+
description: 'Inject code-graph structural context based on user intent',
|
|
260
|
+
}],
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function registerHooksToSettings(settings) {
|
|
265
|
+
if (!settings.hooks) settings.hooks = {};
|
|
266
|
+
const defs = getHookDefinitions();
|
|
267
|
+
let changed = false;
|
|
268
|
+
|
|
269
|
+
for (const [event, newEntries] of Object.entries(defs)) {
|
|
270
|
+
if (!settings.hooks[event]) settings.hooks[event] = [];
|
|
271
|
+
|
|
272
|
+
for (const newEntry of newEntries) {
|
|
273
|
+
const existingIdx = settings.hooks[event].findIndex(e => isOurHookEntry(e));
|
|
274
|
+
if (existingIdx >= 0) {
|
|
275
|
+
if (JSON.stringify(settings.hooks[event][existingIdx]) !== JSON.stringify(newEntry)) {
|
|
276
|
+
settings.hooks[event][existingIdx] = newEntry;
|
|
277
|
+
changed = true;
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
settings.hooks[event].push(newEntry);
|
|
281
|
+
changed = true;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return changed;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function removeHooksFromSettings(settings) {
|
|
290
|
+
if (!settings.hooks) return false;
|
|
291
|
+
let changed = false;
|
|
292
|
+
|
|
293
|
+
for (const event of Object.keys(settings.hooks)) {
|
|
294
|
+
if (!Array.isArray(settings.hooks[event])) continue;
|
|
295
|
+
const before = settings.hooks[event].length;
|
|
296
|
+
settings.hooks[event] = settings.hooks[event].filter(e => !isOurHookEntry(e));
|
|
297
|
+
if (settings.hooks[event].length !== before) changed = true;
|
|
298
|
+
if (settings.hooks[event].length === 0) delete settings.hooks[event];
|
|
299
|
+
}
|
|
300
|
+
if (Object.keys(settings.hooks).length === 0) delete settings.hooks;
|
|
301
|
+
|
|
302
|
+
return changed;
|
|
303
|
+
}
|
|
304
|
+
|
|
219
305
|
// --- Install (idempotent) ---
|
|
220
306
|
|
|
221
307
|
function install() {
|
|
@@ -247,16 +333,21 @@ function install() {
|
|
|
247
333
|
// Register code-graph provider
|
|
248
334
|
registerStatuslineProvider('code-graph', codeGraphStatuslineCommand(), false);
|
|
249
335
|
|
|
336
|
+
// 2. Hooks — register to settings.json (hooks.json auto-loading unreliable)
|
|
337
|
+
if (registerHooksToSettings(settings)) {
|
|
338
|
+
settingsChanged = true;
|
|
339
|
+
}
|
|
340
|
+
|
|
250
341
|
// NOTE: enabledPlugins is managed by Claude Code's plugin system, not by lifecycle.
|
|
251
342
|
// Do NOT add enabledPlugins entries here — it causes phantom plugin entries
|
|
252
343
|
// when the ID doesn't match the marketplace name.
|
|
253
344
|
|
|
254
|
-
//
|
|
345
|
+
// 3. Write settings atomically if changed
|
|
255
346
|
if (settingsChanged) {
|
|
256
347
|
writeJsonAtomic(SETTINGS_PATH, settings);
|
|
257
348
|
}
|
|
258
349
|
|
|
259
|
-
//
|
|
350
|
+
// 4. Write manifest with version
|
|
260
351
|
manifest.version = version;
|
|
261
352
|
manifest.installedAt = manifest.installedAt || new Date().toISOString();
|
|
262
353
|
manifest.updatedAt = new Date().toISOString();
|
|
@@ -277,7 +368,12 @@ function uninstall() {
|
|
|
277
368
|
settingsChanged = true;
|
|
278
369
|
}
|
|
279
370
|
|
|
280
|
-
// 2.
|
|
371
|
+
// 2. Hooks: remove from settings.json
|
|
372
|
+
if (removeHooksFromSettings(settings)) {
|
|
373
|
+
settingsChanged = true;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// 3. Remove all known IDs from enabledPlugins
|
|
281
377
|
if (settings.enabledPlugins) {
|
|
282
378
|
for (const id of [PLUGIN_ID, ...OLD_PLUGIN_IDS]) {
|
|
283
379
|
if (id in settings.enabledPlugins) {
|
|
@@ -287,13 +383,13 @@ function uninstall() {
|
|
|
287
383
|
}
|
|
288
384
|
}
|
|
289
385
|
|
|
290
|
-
//
|
|
386
|
+
// 4. Write settings if changed
|
|
291
387
|
if (settingsChanged) {
|
|
292
388
|
writeJsonAtomic(SETTINGS_PATH, settings);
|
|
293
389
|
}
|
|
294
390
|
}
|
|
295
391
|
|
|
296
|
-
//
|
|
392
|
+
// 5. Remove all known IDs from installed_plugins.json
|
|
297
393
|
const installedPlugins = readJson(INSTALLED_PLUGINS_PATH);
|
|
298
394
|
if (installedPlugins && installedPlugins.plugins) {
|
|
299
395
|
let ipChanged = false;
|
|
@@ -306,10 +402,10 @@ function uninstall() {
|
|
|
306
402
|
if (ipChanged) writeJsonAtomic(INSTALLED_PLUGINS_PATH, installedPlugins);
|
|
307
403
|
}
|
|
308
404
|
|
|
309
|
-
//
|
|
405
|
+
// 6. Remove cache directory
|
|
310
406
|
try { fs.rmSync(CACHE_DIR, { recursive: true, force: true }); } catch { /* ok */ }
|
|
311
407
|
|
|
312
|
-
//
|
|
408
|
+
// 7. Remove plugin files from cache (all known paths, including parent dirs)
|
|
313
409
|
const pluginCacheDirs = [
|
|
314
410
|
path.join(os.homedir(), '.claude', 'plugins', 'cache', MARKETPLACE_NAME),
|
|
315
411
|
path.join(os.homedir(), '.claude', 'plugins', 'cache', 'sdsrss-code-graph'),
|
|
@@ -348,23 +444,28 @@ function update() {
|
|
|
348
444
|
// 2. Update code-graph provider in registry
|
|
349
445
|
registerStatuslineProvider('code-graph', codeGraphStatuslineCommand(), false);
|
|
350
446
|
|
|
447
|
+
// 3. Hooks — update command paths
|
|
448
|
+
if (registerHooksToSettings(settings)) {
|
|
449
|
+
settingsChanged = true;
|
|
450
|
+
}
|
|
451
|
+
|
|
351
452
|
// NOTE: enabledPlugins is managed by Claude Code's plugin system, not by lifecycle.
|
|
352
453
|
|
|
353
|
-
//
|
|
454
|
+
// 4. Write settings if changed
|
|
354
455
|
if (settingsChanged) {
|
|
355
456
|
writeJsonAtomic(SETTINGS_PATH, settings);
|
|
356
457
|
}
|
|
357
458
|
|
|
358
|
-
//
|
|
459
|
+
// 5. Clear update-check cache (force re-check after update)
|
|
359
460
|
const updateCache = path.join(CACHE_DIR, 'update-check');
|
|
360
461
|
try { fs.unlinkSync(updateCache); } catch { /* ok */ }
|
|
361
462
|
|
|
362
|
-
//
|
|
463
|
+
// 6. Update manifest
|
|
363
464
|
manifest.version = version;
|
|
364
465
|
manifest.updatedAt = new Date().toISOString();
|
|
365
466
|
writeManifest(manifest);
|
|
366
467
|
|
|
367
|
-
//
|
|
468
|
+
// 7. Clean up old cached versions (keep latest 3)
|
|
368
469
|
cleanupOldCacheVersions(3);
|
|
369
470
|
|
|
370
471
|
return { oldVersion, version, settingsChanged };
|
|
@@ -411,6 +512,7 @@ module.exports = {
|
|
|
411
512
|
readManifest, readJson, writeJsonAtomic,
|
|
412
513
|
readRegistry, writeRegistry,
|
|
413
514
|
getPluginVersion, cleanupOldCacheVersions,
|
|
515
|
+
registerHooksToSettings, removeHooksFromSettings, getHookDefinitions,
|
|
414
516
|
PLUGIN_ID, OLD_PLUGIN_IDS, MARKETPLACE_NAME, CACHE_DIR, REGISTRY_FILE,
|
|
415
517
|
};
|
|
416
518
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdsrs/code-graph",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.13",
|
|
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": {
|
|
@@ -27,16 +27,17 @@
|
|
|
27
27
|
"claude-plugin"
|
|
28
28
|
],
|
|
29
29
|
"scripts": {
|
|
30
|
-
"build": "cargo build --release --no-default-features && node scripts/copy-binary.js"
|
|
30
|
+
"build": "cargo build --release --no-default-features && node scripts/copy-binary.js",
|
|
31
|
+
"prepare": "git rev-parse --git-dir > /dev/null 2>&1 && ln -sf ../../scripts/pre-commit.sh .git/hooks/pre-commit || true"
|
|
31
32
|
},
|
|
32
33
|
"engines": {
|
|
33
34
|
"node": ">=16"
|
|
34
35
|
},
|
|
35
36
|
"optionalDependencies": {
|
|
36
|
-
"@sdsrs/code-graph-linux-x64": "0.7.
|
|
37
|
-
"@sdsrs/code-graph-linux-arm64": "0.7.
|
|
38
|
-
"@sdsrs/code-graph-darwin-x64": "0.7.
|
|
39
|
-
"@sdsrs/code-graph-darwin-arm64": "0.7.
|
|
40
|
-
"@sdsrs/code-graph-win32-x64": "0.7.
|
|
37
|
+
"@sdsrs/code-graph-linux-x64": "0.7.13",
|
|
38
|
+
"@sdsrs/code-graph-linux-arm64": "0.7.13",
|
|
39
|
+
"@sdsrs/code-graph-darwin-x64": "0.7.13",
|
|
40
|
+
"@sdsrs/code-graph-darwin-arm64": "0.7.13",
|
|
41
|
+
"@sdsrs/code-graph-win32-x64": "0.7.13"
|
|
41
42
|
}
|
|
42
43
|
}
|