@grafema/cli 0.3.24 → 0.3.28

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.
Files changed (48) hide show
  1. package/README.md +59 -45
  2. package/dist/cli.js +10 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/analyzeAction.d.ts.map +1 -1
  5. package/dist/commands/analyzeAction.js +134 -3
  6. package/dist/commands/analyzeAction.js.map +1 -1
  7. package/dist/commands/doctor/checks.d.ts.map +1 -1
  8. package/dist/commands/doctor/checks.js +7 -3
  9. package/dist/commands/doctor/checks.js.map +1 -1
  10. package/dist/commands/export.d.ts +15 -0
  11. package/dist/commands/export.d.ts.map +1 -0
  12. package/dist/commands/export.js +88 -0
  13. package/dist/commands/export.js.map +1 -0
  14. package/dist/commands/exportAction.d.ts +35 -0
  15. package/dist/commands/exportAction.d.ts.map +1 -0
  16. package/dist/commands/exportAction.js +58 -0
  17. package/dist/commands/exportAction.js.map +1 -0
  18. package/dist/commands/features.d.ts +13 -0
  19. package/dist/commands/features.d.ts.map +1 -0
  20. package/dist/commands/features.js +69 -0
  21. package/dist/commands/features.js.map +1 -0
  22. package/dist/commands/featuresAction.d.ts +82 -0
  23. package/dist/commands/featuresAction.d.ts.map +1 -0
  24. package/dist/commands/featuresAction.js +139 -0
  25. package/dist/commands/featuresAction.js.map +1 -0
  26. package/dist/commands/start.d.ts +12 -0
  27. package/dist/commands/start.d.ts.map +1 -0
  28. package/dist/commands/start.js +294 -0
  29. package/dist/commands/start.js.map +1 -0
  30. package/dist/commands/trace.d.ts.map +1 -1
  31. package/dist/commands/trace.js +50 -30
  32. package/dist/commands/trace.js.map +1 -1
  33. package/dist/commands/upgrade.d.ts +3 -0
  34. package/dist/commands/upgrade.d.ts.map +1 -0
  35. package/dist/commands/upgrade.js +279 -0
  36. package/dist/commands/upgrade.js.map +1 -0
  37. package/package.json +8 -8
  38. package/src/cli.ts +11 -0
  39. package/src/commands/analyzeAction.ts +135 -2
  40. package/src/commands/doctor/checks.ts +4 -3
  41. package/src/commands/explore.tsx +29 -2
  42. package/src/commands/export.ts +102 -0
  43. package/src/commands/exportAction.ts +107 -0
  44. package/src/commands/features.ts +88 -0
  45. package/src/commands/featuresAction.ts +218 -0
  46. package/src/commands/start.ts +303 -0
  47. package/src/commands/trace.ts +49 -29
  48. package/src/commands/upgrade.ts +310 -0
@@ -0,0 +1,279 @@
1
+ import { Command } from 'commander';
2
+ import { existsSync, readdirSync, lstatSync, unlinkSync, rmSync, statSync, mkdirSync, } from 'fs';
3
+ import { join, resolve } from 'path';
4
+ import { getGrafemaBinDir, DOWNLOADABLE_BINARIES, isBinaryCurrentVersion, downloadBinary, GRAFEMA_VERSION, } from '@grafema/util';
5
+ const COLORS = {
6
+ green: '\x1b[32m',
7
+ red: '\x1b[31m',
8
+ yellow: '\x1b[33m',
9
+ cyan: '\x1b[36m',
10
+ dim: '\x1b[2m',
11
+ bold: '\x1b[1m',
12
+ reset: '\x1b[0m',
13
+ };
14
+ const LANG_BINARIES = {
15
+ js: ['grafema-analyzer', 'grafema-resolve'],
16
+ python: ['grafema-python-analyzer', 'python-resolve'],
17
+ haskell: ['haskell-analyzer', 'haskell-resolve'],
18
+ rust: ['grafema-rust-resolve'],
19
+ java: ['grafema-java-analyzer', 'java-resolve', 'java-parser'],
20
+ kotlin: ['grafema-kotlin-analyzer', 'kotlin-resolve', 'kotlin-parser'],
21
+ go: ['grafema-go-analyzer', 'go-resolve', 'go-parser'],
22
+ cpp: ['grafema-cpp-analyzer', 'cpp-resolve'],
23
+ swift: ['grafema-swift-analyzer', 'swift-resolve', 'swift-parser'],
24
+ objc: ['grafema-objc-analyzer', 'objc-parser'],
25
+ beam: ['beam-analyzer', 'beam-resolve'],
26
+ };
27
+ const INFRASTRUCTURE = ['grafema-orchestrator', 'rfdb-server'];
28
+ const DOWNLOADABLE_SET = new Set(DOWNLOADABLE_BINARIES);
29
+ function formatBytes(bytes) {
30
+ if (bytes === 0)
31
+ return '0 B';
32
+ const units = ['B', 'KB', 'MB', 'GB'];
33
+ const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
34
+ const val = bytes / Math.pow(1024, i);
35
+ return `${val.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
36
+ }
37
+ function auditBinDir(binDir) {
38
+ const toClean = [];
39
+ const knownBinaries = [];
40
+ if (!existsSync(binDir))
41
+ return { toClean, knownBinaries };
42
+ for (const entry of readdirSync(binDir)) {
43
+ const fullPath = join(binDir, entry);
44
+ let stat;
45
+ try {
46
+ stat = lstatSync(fullPath);
47
+ }
48
+ catch {
49
+ continue;
50
+ }
51
+ if (stat.isSymbolicLink() && !existsSync(fullPath)) {
52
+ toClean.push({ path: fullPath, name: entry, reason: 'broken symlink', size: 0 });
53
+ continue;
54
+ }
55
+ if (entry.startsWith('.build-hash.') || entry.endsWith('.downloading')) {
56
+ toClean.push({ path: fullPath, name: entry, reason: 'dev artifact', size: stat.size });
57
+ continue;
58
+ }
59
+ if (entry.endsWith('.version')) {
60
+ const binaryName = entry.slice(0, -'.version'.length);
61
+ if (!existsSync(join(binDir, binaryName))) {
62
+ toClean.push({ path: fullPath, name: entry, reason: 'orphaned version file', size: stat.size });
63
+ }
64
+ continue;
65
+ }
66
+ if (entry === '.gitkeep')
67
+ continue;
68
+ if (DOWNLOADABLE_SET.has(entry)) {
69
+ knownBinaries.push(entry);
70
+ }
71
+ else {
72
+ toClean.push({ path: fullPath, name: entry, reason: 'unknown binary', size: stat.size });
73
+ }
74
+ }
75
+ return { toClean, knownBinaries };
76
+ }
77
+ function getTargetBinaries(options, existingBinaries) {
78
+ if (options.all) {
79
+ return [...DOWNLOADABLE_BINARIES];
80
+ }
81
+ if (options.lang) {
82
+ const langs = options.lang.split(',').map(l => l.trim().toLowerCase());
83
+ const invalid = langs.filter(l => !LANG_BINARIES[l]);
84
+ if (invalid.length > 0) {
85
+ console.error(`${COLORS.red}Unknown languages: ${invalid.join(', ')}${COLORS.reset}`);
86
+ console.error(`Available: ${Object.keys(LANG_BINARIES).join(', ')}`);
87
+ process.exit(1);
88
+ }
89
+ const bins = new Set(INFRASTRUCTURE);
90
+ for (const lang of langs) {
91
+ for (const b of LANG_BINARIES[lang])
92
+ bins.add(b);
93
+ }
94
+ return [...bins];
95
+ }
96
+ const set = new Set(existingBinaries);
97
+ for (const b of INFRASTRUCTURE)
98
+ set.add(b);
99
+ return [...set];
100
+ }
101
+ function auditProjectDir(projectPath) {
102
+ const grafemaDir = join(projectPath, '.grafema');
103
+ if (!existsSync(grafemaDir))
104
+ return [];
105
+ const toClean = [];
106
+ const diagLog = join(grafemaDir, 'diagnostics.log');
107
+ if (existsSync(diagLog)) {
108
+ toClean.push({ path: diagLog, name: 'diagnostics.log', reason: 'old diagnostics', size: statSync(diagLog).size });
109
+ }
110
+ const oldDb = join(grafemaDir, 'grafema.rfdb');
111
+ const newDb = join(grafemaDir, 'graph.rfdb');
112
+ if (existsSync(oldDb) && existsSync(newDb)) {
113
+ let size = 0;
114
+ try {
115
+ for (const f of readdirSync(oldDb)) {
116
+ try {
117
+ size += statSync(join(oldDb, f)).size;
118
+ }
119
+ catch { /* skip */ }
120
+ }
121
+ }
122
+ catch { /* skip */ }
123
+ toClean.push({ path: oldDb, name: 'grafema.rfdb/', reason: 'stale database (renamed to graph.rfdb)', size });
124
+ }
125
+ const logsDir = join(grafemaDir, 'logs');
126
+ if (existsSync(logsDir)) {
127
+ const thirtyDaysAgo = Date.now() - 30 * 24 * 60 * 60 * 1000;
128
+ try {
129
+ for (const f of readdirSync(logsDir)) {
130
+ const fp = join(logsDir, f);
131
+ try {
132
+ const s = statSync(fp);
133
+ if (s.isFile() && s.mtimeMs < thirtyDaysAgo) {
134
+ toClean.push({ path: fp, name: `logs/${f}`, reason: 'log older than 30 days', size: s.size });
135
+ }
136
+ }
137
+ catch { /* skip */ }
138
+ }
139
+ }
140
+ catch { /* skip */ }
141
+ }
142
+ return toClean;
143
+ }
144
+ export const upgradeCommand = new Command('upgrade')
145
+ .description('Clean stale artifacts and upgrade binaries to current version')
146
+ .option('-a, --all', 'Download all available binaries (not just existing)')
147
+ .option('-l, --lang <langs>', 'Comma-separated languages to install (js,python,rust,...)')
148
+ .option('-n, --dry-run', 'Preview changes without executing')
149
+ .option('-p, --project [path]', 'Also clean project .grafema/ artifacts')
150
+ .addHelpText('after', `
151
+ Examples:
152
+ grafema upgrade Clean + upgrade existing binaries
153
+ grafema upgrade --all Clean + download ALL available binaries
154
+ grafema upgrade --lang js,python Clean + ensure JS and Python analyzers
155
+ grafema upgrade --dry-run Preview what would be cleaned/upgraded
156
+ grafema upgrade --project Also clean .grafema/ in current directory
157
+
158
+ Available languages: ${Object.keys(LANG_BINARIES).join(', ')}`)
159
+ .action(async (options) => {
160
+ const dryRun = !!options.dryRun;
161
+ const prefix = dryRun ? `${COLORS.dim}[dry-run]${COLORS.reset} ` : '';
162
+ const binDir = getGrafemaBinDir();
163
+ console.log(`${COLORS.bold}Grafema Upgrade${COLORS.reset} ${COLORS.dim}v${GRAFEMA_VERSION}${COLORS.reset}`);
164
+ console.log();
165
+ if (!existsSync(binDir)) {
166
+ mkdirSync(binDir, { recursive: true });
167
+ }
168
+ // Phase 1+2: Audit and clean ~/.grafema/bin/
169
+ const { toClean, knownBinaries } = auditBinDir(binDir);
170
+ if (toClean.length > 0) {
171
+ console.log(`${COLORS.bold}Cleaning ~/.grafema/bin/${COLORS.reset}`);
172
+ for (const item of toClean) {
173
+ console.log(` ${prefix}${COLORS.red}✗${COLORS.reset} ${item.name} ${COLORS.dim}(${item.reason}, ${formatBytes(item.size)})${COLORS.reset}`);
174
+ if (!dryRun) {
175
+ try {
176
+ const s = lstatSync(item.path);
177
+ if (s.isDirectory()) {
178
+ rmSync(item.path, { recursive: true, force: true });
179
+ }
180
+ else {
181
+ unlinkSync(item.path);
182
+ }
183
+ }
184
+ catch (err) {
185
+ console.log(` ${COLORS.yellow}warning: ${err instanceof Error ? err.message : err}${COLORS.reset}`);
186
+ }
187
+ }
188
+ }
189
+ console.log();
190
+ }
191
+ // Phase 3: Upgrade binaries
192
+ const targets = getTargetBinaries(options, knownBinaries);
193
+ console.log(`${COLORS.bold}Upgrading binaries${COLORS.reset} ${COLORS.dim}(target: binaries-v${GRAFEMA_VERSION})${COLORS.reset}`);
194
+ let upgradedCount = 0;
195
+ let currentCount = 0;
196
+ let failedCount = 0;
197
+ for (const name of targets) {
198
+ const binaryPath = join(binDir, name);
199
+ if (existsSync(binaryPath) && isBinaryCurrentVersion(binaryPath)) {
200
+ currentCount++;
201
+ console.log(` ${COLORS.green}✓${COLORS.reset} ${name} ${COLORS.dim}-- current${COLORS.reset}`);
202
+ continue;
203
+ }
204
+ if (dryRun) {
205
+ const status = existsSync(binaryPath) ? 'stale, would upgrade' : 'missing, would download';
206
+ console.log(` ${prefix}${COLORS.cyan}↓${COLORS.reset} ${name} ${COLORS.dim}(${status})${COLORS.reset}`);
207
+ upgradedCount++;
208
+ continue;
209
+ }
210
+ try {
211
+ process.stdout.write(` ${COLORS.cyan}↓${COLORS.reset} ${name} -- downloading...`);
212
+ const downloaded = await downloadBinary(name);
213
+ const size = statSync(downloaded).size;
214
+ process.stdout.write(`\r ${COLORS.green}✓${COLORS.reset} ${name} ${COLORS.dim}(${formatBytes(size)})${COLORS.reset} \n`);
215
+ upgradedCount++;
216
+ }
217
+ catch (err) {
218
+ const msg = err instanceof Error ? err.message : String(err);
219
+ process.stdout.write(`\r ${COLORS.red}✗${COLORS.reset} ${name} -- ${msg} \n`);
220
+ failedCount++;
221
+ }
222
+ }
223
+ console.log();
224
+ // Phase 4: Project cleanup (optional)
225
+ let projectCleanedCount = 0;
226
+ let projectCleanedBytes = 0;
227
+ if (options.project !== undefined) {
228
+ const projectPath = typeof options.project === 'string' ? resolve(options.project) : resolve('.');
229
+ const projectActions = auditProjectDir(projectPath);
230
+ if (projectActions.length > 0) {
231
+ console.log(`${COLORS.bold}Cleaning project artifacts${COLORS.reset} ${COLORS.dim}(${projectPath}/.grafema/)${COLORS.reset}`);
232
+ for (const item of projectActions) {
233
+ console.log(` ${prefix}${COLORS.red}✗${COLORS.reset} ${item.name} ${COLORS.dim}(${item.reason}, ${formatBytes(item.size)})${COLORS.reset}`);
234
+ if (!dryRun) {
235
+ try {
236
+ const s = lstatSync(item.path);
237
+ if (s.isDirectory()) {
238
+ rmSync(item.path, { recursive: true, force: true });
239
+ }
240
+ else {
241
+ unlinkSync(item.path);
242
+ }
243
+ projectCleanedCount++;
244
+ projectCleanedBytes += item.size;
245
+ }
246
+ catch (err) {
247
+ console.log(` ${COLORS.yellow}warning: ${err instanceof Error ? err.message : err}${COLORS.reset}`);
248
+ }
249
+ }
250
+ else {
251
+ projectCleanedCount++;
252
+ projectCleanedBytes += item.size;
253
+ }
254
+ }
255
+ console.log();
256
+ }
257
+ }
258
+ // Summary
259
+ const parts = [];
260
+ if (toClean.length > 0) {
261
+ const totalCleaned = toClean.reduce((s, a) => s + a.size, 0);
262
+ parts.push(`cleaned ${toClean.length} files (${formatBytes(totalCleaned)})`);
263
+ }
264
+ if (upgradedCount > 0)
265
+ parts.push(`upgraded ${upgradedCount} binaries`);
266
+ if (currentCount > 0)
267
+ parts.push(`${currentCount} already current`);
268
+ if (failedCount > 0)
269
+ parts.push(`${COLORS.red}${failedCount} failed${COLORS.reset}`);
270
+ if (projectCleanedCount > 0)
271
+ parts.push(`project: ${projectCleanedCount} files (${formatBytes(projectCleanedBytes)})`);
272
+ if (parts.length === 0) {
273
+ console.log(`${COLORS.green}✓${COLORS.reset} Everything is up to date.`);
274
+ }
275
+ else {
276
+ console.log(`${COLORS.bold}Summary:${COLORS.reset} ${parts.join(', ')}`);
277
+ }
278
+ });
279
+ //# sourceMappingURL=upgrade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grafema/cli",
3
- "version": "0.3.24",
3
+ "version": "0.3.28",
4
4
  "description": "CLI for Grafema code analysis toolkit",
5
5
  "type": "module",
6
6
  "main": "./dist/cli.js",
@@ -35,15 +35,15 @@
35
35
  "dependencies": {
36
36
  "commander": "^13.0.0",
37
37
  "yaml": "^2.8.2",
38
- "@grafema/util": "0.3.24",
39
- "@grafema/api": "0.3.24",
40
- "@grafema/types": "0.3.24"
38
+ "@grafema/util": "0.3.28",
39
+ "@grafema/api": "0.3.28",
40
+ "@grafema/types": "0.3.28"
41
41
  },
42
42
  "optionalDependencies": {
43
- "@grafema/grafema-darwin-arm64": "0.3.16",
44
- "@grafema/grafema-darwin-x64": "0.3.16",
45
- "@grafema/grafema-linux-arm64": "0.3.16",
46
- "@grafema/grafema-linux-x64": "0.3.16"
43
+ "@grafema/grafema-darwin-arm64": "0.3.28",
44
+ "@grafema/grafema-darwin-x64": "0.3.28",
45
+ "@grafema/grafema-linux-arm64": "0.3.28",
46
+ "@grafema/grafema-linux-x64": "0.3.28"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^25.0.8",
package/src/cli.ts CHANGED
@@ -35,6 +35,10 @@ import { fileCommand } from './commands/file.js';
35
35
  import { setupSkillCommand } from './commands/setup-skill.js';
36
36
  import { gitIngestCommand } from './commands/git-ingest.js';
37
37
  import { registryCommand } from './commands/registry.js';
38
+ import { featuresCommand } from './commands/features.js';
39
+ import { exportCommand } from './commands/export.js';
40
+ import { startCommand, stopCommand } from './commands/start.js';
41
+ import { upgradeCommand } from './commands/upgrade.js';
38
42
 
39
43
  // Read version from package.json
40
44
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -53,6 +57,10 @@ program.addCommand(wtfCommand);
53
57
  program.addCommand(whoCommand);
54
58
  program.addCommand(whyCommand);
55
59
 
60
+ // Lifecycle commands
61
+ program.addCommand(startCommand);
62
+ program.addCommand(stopCommand);
63
+
56
64
  // Commands in logical order
57
65
  program.addCommand(initCommand);
58
66
  program.addCommand(analyzeCommand);
@@ -72,11 +80,14 @@ program.addCommand(coverageCommand);
72
80
  program.addCommand(checkCommand);
73
81
  program.addCommand(serverCommand);
74
82
  program.addCommand(doctorCommand);
83
+ program.addCommand(upgradeCommand);
75
84
  program.addCommand(schemaCommand);
76
85
  program.addCommand(explainCommand);
77
86
  program.addCommand(fileCommand);
78
87
  program.addCommand(setupSkillCommand);
79
88
  program.addCommand(gitIngestCommand);
80
89
  program.addCommand(registryCommand);
90
+ program.addCommand(featuresCommand);
91
+ program.addCommand(exportCommand);
81
92
 
82
93
  program.parse();
@@ -20,9 +20,20 @@ import {
20
20
  ensureBinary,
21
21
  ManifestGenerator,
22
22
  ManifestResolver,
23
+ EffectsLookup,
23
24
  GRAFEMA_VERSION,
24
25
  getSchemaVersion,
25
26
  } from '@grafema/util';
27
+ import { enrichBehaviors } from '@grafema/util/enrichers/behaviorEnricher';
28
+ import { enrichContracts } from '@grafema/util/enrichers/contractEnricher';
29
+ import { enrichLibraryCallbacks } from '@grafema/util/enrichers/libraryCallbackEnricher';
30
+ import { enrichPackageApis } from '@grafema/util/enrichers/packageApiEnricher';
31
+ import { enrichMcpToolDefinitions } from '@grafema/util/enrichers/mcpToolDefinitionEnricher';
32
+ import { enrichSpecedContracts } from '@grafema/util/enrichers/specedContractEnricher';
33
+ import { commanderExtractor } from '@grafema/util/enrichers/extractors/commanderExtractor';
34
+ import { mcpInputSchemaExtractor } from '@grafema/util/enrichers/extractors/mcpInputSchemaExtractor';
35
+ import { vscodeContributesExtractor } from '@grafema/util/enrichers/extractors/vscodeContributesExtractor';
36
+ import { httpRouteExtractor } from '@grafema/util/enrichers/extractors/httpRouteExtractor';
26
37
  import type { LogLevel } from '@grafema/util';
27
38
  import { scanExtensions, generateSmartConfig, writeConfig, updateGitignore, formatDetected } from '../utils/quickstart.js';
28
39
 
@@ -95,8 +106,8 @@ const EXT_TO_BINARIES: Record<string, string[]> = {
95
106
  pyi: ['grafema-python-analyzer', 'python-resolve'],
96
107
  // Haskell
97
108
  hs: ['haskell-analyzer', 'haskell-resolve'],
98
- // Rust
99
- rs: ['grafema-rust-analyzer', 'grafema-rust-resolve'],
109
+ // Rust (analyzer is native in-process inside orchestrator)
110
+ rs: ['grafema-rust-resolve'],
100
111
  // Java
101
112
  java: ['grafema-java-analyzer', 'java-resolve', 'java-parser'],
102
113
  // Kotlin
@@ -322,6 +333,114 @@ export async function analyzeAction(path: string, options: { service?: string; e
322
333
  info(` Nodes: ${stats.nodeCount}`);
323
334
  info(` Edges: ${stats.edgeCount}`);
324
335
 
336
+ // Run library-callback enricher before manifest generation.
337
+ // Creates domain nodes (cli:command, mcp:tool, ...) and HANDLES edges
338
+ // for callbacks passed to library entry points (Commander, MCP SDK, ...).
339
+ // Reuses the effects-db loaded for ManifestGenerator.
340
+ const effectsDbPath = resolveEffectsDbPath(projectPath);
341
+ const effectsLookup = effectsDbPath
342
+ ? EffectsLookup.load(effectsDbPath)
343
+ : EffectsLookup.empty();
344
+ try {
345
+ // RFDBServerBackend's RFDBClient field is private at compile time but
346
+ // accessible at runtime; the enricher only needs the wire-level client.
347
+ const client = (backend as unknown as { client: Parameters<typeof enrichLibraryCallbacks>[0] }).client;
348
+ if (client) {
349
+ const result = await enrichLibraryCallbacks(client, effectsLookup);
350
+ info(` Library callbacks: ${result.domainNodesCreated} domain nodes, ${result.handlesEdgesCreated} HANDLES edges (unresolved: ${result.unresolvedCalls})`);
351
+ }
352
+ } catch (err) {
353
+ debug(`Library callback enricher skipped: ${err instanceof Error ? err.message : String(err)}`);
354
+ }
355
+
356
+ // MCP tool definition enricher — scans `packages/mcp/src/definitions/*-tools.ts`
357
+ // (or any matching tree under projectPath) and creates `mcp:tool` nodes for
358
+ // each defined tool. Complements libraryCallbackEnricher: that one captures
359
+ // the high-level setRequestHandler calls; this one captures the ~30+ tools
360
+ // dispatched by the switch statement inside the CallTool handler.
361
+ try {
362
+ const client = (backend as unknown as { client: Parameters<typeof enrichMcpToolDefinitions>[0] }).client;
363
+ if (client) {
364
+ const definitionsDir = join(projectPath, 'packages/mcp/src/definitions');
365
+ const result = await enrichMcpToolDefinitions(client, { definitionsDir });
366
+ if (result.toolNodesCreated > 0) {
367
+ info(` MCP tool defs: ${result.toolNodesCreated} mcp:tool nodes, ${result.handlesEdgesCreated} HANDLES edges (unresolved: ${result.unresolvedHandlers.length})`);
368
+ }
369
+ }
370
+ } catch (err) {
371
+ debug(`MCP tool definition enricher skipped: ${err instanceof Error ? err.message : String(err)}`);
372
+ }
373
+
374
+ // Contract enricher — for every FEATURE-class node (cli:command, mcp:tool,
375
+ // vscode:command) created by the L0 entry-point enrichers above, walk the
376
+ // HANDLES edge to the handler FUNCTION and extract a CONTRACT node carrying
377
+ // structured inputs/outputs/errors metadata. Must run AFTER the FEATURE
378
+ // creators (enrichLibraryCallbacks, enrichMcpToolDefinitions) so HANDLES
379
+ // edges already exist, and BEFORE generateManifest so contracts can flow
380
+ // into the manifest if needed.
381
+ try {
382
+ const client = (backend as unknown as { client: Parameters<typeof enrichContracts>[0] }).client;
383
+ if (client) {
384
+ const result = await enrichContracts(client);
385
+ info(` Contracts: ${result.contractsCreated} contracts (${result.inputsTotal} inputs, ${result.outputsTotal} outputs, ${result.errorsTotal} errors); ${result.featuresWithoutEntry} features lacked HANDLES edge`);
386
+ }
387
+ } catch (err) {
388
+ debug(`Contract enricher skipped: ${err instanceof Error ? err.message : String(err)}`);
389
+ }
390
+
391
+ // Speced-contract enricher — for every FEATURE node, run the registered
392
+ // per-category extractors (commander spec strings, MCP inputSchema, …)
393
+ // to produce SPECED_CONTRACT nodes carrying the user-facing interface.
394
+ // Distinct from the existing CONTRACT (handler signature scrape) which
395
+ // is implementation-side. See `_ai/research/feature-taxonomy.md` §1.3.
396
+ try {
397
+ const client = (backend as unknown as { client: Parameters<typeof enrichSpecedContracts>[0] }).client;
398
+ if (client) {
399
+ const result = await enrichSpecedContracts(client, [
400
+ commanderExtractor,
401
+ mcpInputSchemaExtractor,
402
+ vscodeContributesExtractor,
403
+ httpRouteExtractor,
404
+ ]);
405
+ info(` Speced contracts: ${result.contractsCreated} (${result.inputsTotal} inputs); byCategory=${JSON.stringify(result.byCategory)}; missingExtractor=${result.featuresWithoutExtractor}, missingSpec=${result.featuresWithoutSpec}`);
406
+ }
407
+ } catch (err) {
408
+ debug(`Speced contract enricher skipped: ${err instanceof Error ? err.message : String(err)}`);
409
+ }
410
+
411
+ // Behavior enricher — for every FEATURE-class node, walk the HANDLES
412
+ // edge to the entry function and compute a transitive CALLS closure.
413
+ // Stores BEHAVIOR with hash + effects + summary (no COMPRISES edges —
414
+ // see skill `materialize-only-what-queries-need`). Pass 2 emits
415
+ // SHARES_BEHAVIOR_WITH between behaviors with identical hash.
416
+ try {
417
+ const client = (backend as unknown as { client: Parameters<typeof enrichBehaviors>[0] }).client;
418
+ if (client) {
419
+ const result = await enrichBehaviors(client, effectsLookup);
420
+ info(` Behaviors: ${result.behaviorsCreated} BEHAVIOR nodes, ${result.sharesBehaviorEdges} SHARES_BEHAVIOR_WITH edges (totalCoreNodes=${result.totalCoreNodes}, missingEntry=${result.featuresWithoutEntry})`);
421
+ }
422
+ } catch (err) {
423
+ debug(`Behavior enricher skipped: ${err instanceof Error ? err.message : String(err)}`);
424
+ }
425
+
426
+ // Package API enricher — for every monorepo package barrel
427
+ // (`packages/<pkg>/src/index.ts`), emit a `package:export` FEATURE node
428
+ // per EXPORT_BINDING and a HANDLES edge to the underlying definition.
429
+ // Surfaces inter-package public-API surfaces so the contract enricher
430
+ // (run already) can wire contracts onto these on the next pass; the
431
+ // benefit is realised by downstream consumers (manifest, GUI, agents).
432
+ try {
433
+ const client = (backend as unknown as { client: Parameters<typeof enrichPackageApis>[0] }).client;
434
+ if (client) {
435
+ const result = await enrichPackageApis(client);
436
+ if (result.apiNodesCreated > 0) {
437
+ info(` Package APIs: ${result.apiNodesCreated} package:export nodes, ${result.handlesEdgesCreated} HANDLES edges across ${result.packagesScanned} barrels (unresolved: ${result.exportsWithoutHandler})`);
438
+ }
439
+ }
440
+ } catch (err) {
441
+ debug(`Package API enricher skipped: ${err instanceof Error ? err.message : String(err)}`);
442
+ }
443
+
325
444
  // Generate manifest after successful analysis
326
445
  try {
327
446
  const manifestPath = await generateManifest(backend, projectPath, grafemaDir, debug);
@@ -381,6 +500,20 @@ export async function analyzeAction(path: string, options: { service?: string; e
381
500
  }
382
501
  }
383
502
 
503
+ /**
504
+ * Resolve effects-db directory: prefer the one shipped next to the CLI package,
505
+ * fall back to a project-local effects-db. Returns undefined if neither exists.
506
+ * Shared by both the library-callback enricher and ManifestGenerator.
507
+ */
508
+ function resolveEffectsDbPath(projectPath: string): string | undefined {
509
+ const cliDir = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
510
+ const candidates = [
511
+ join(cliDir, 'effects-db'),
512
+ join(projectPath, 'effects-db'),
513
+ ];
514
+ return candidates.find(p => existsSync(p));
515
+ }
516
+
384
517
  /**
385
518
  * Generate manifest.yaml after successful analysis.
386
519
  * Reads package.json to determine package name and entry point,
@@ -8,7 +8,7 @@
8
8
  * - Level 4: Informational - checkVersions
9
9
  */
10
10
 
11
- import { existsSync, readFileSync, statSync } from 'fs';
11
+ import { existsSync, readFileSync, statSync, unlinkSync } from 'fs';
12
12
  import { join, dirname, delimiter } from 'path';
13
13
  import { fileURLToPath } from 'url';
14
14
  import { createRequire } from 'module';
@@ -261,11 +261,12 @@ export async function checkServerStatus(
261
261
  details: { version, socketPath },
262
262
  };
263
263
  } catch {
264
+ try { unlinkSync(socketPath); } catch { /* already gone */ }
264
265
  return {
265
266
  name: 'server',
266
267
  status: 'warn',
267
- message: 'Server socket exists but not responding (stale)',
268
- recommendation: 'Run: grafema analyze (will restart server)',
268
+ message: 'Stale socket removed. Run grafema analyze to restart server.',
269
+ recommendation: 'Run: grafema analyze (starts fresh server)',
269
270
  };
270
271
  }
271
272
  }
@@ -74,6 +74,7 @@ interface ExploreState {
74
74
  // Code preview
75
75
  showCodePreview: boolean;
76
76
  codePreviewLines: string[];
77
+ showHelp: boolean;
77
78
  }
78
79
 
79
80
  interface ExplorerProps {
@@ -108,6 +109,7 @@ function Explorer({ backend, startNode, projectPath }: ExplorerProps) {
108
109
  viewMode: 'function',
109
110
  showCodePreview: false,
110
111
  codePreviewLines: [],
112
+ showHelp: false,
111
113
  });
112
114
 
113
115
  // Load data when currentNode changes
@@ -214,7 +216,7 @@ function Explorer({ backend, startNode, projectPath }: ExplorerProps) {
214
216
  }
215
217
 
216
218
  if (input === '?') {
217
- // TODO: show help
219
+ setState(s => ({ ...s, showHelp: !s.showHelp }))
218
220
  return;
219
221
  }
220
222
 
@@ -745,10 +747,35 @@ function Explorer({ backend, startNode, projectPath }: ExplorerProps) {
745
747
  </Box>
746
748
  )}
747
749
 
750
+ {/* Help overlay */}
751
+ {state.showHelp && (
752
+ <Box
753
+ flexDirection="column"
754
+ borderStyle="single"
755
+ borderColor="cyan"
756
+ paddingX={1}
757
+ marginBottom={1}
758
+ >
759
+ <Text bold color="cyan"> Клавиши управления </Text>
760
+ <Text> q — выход</Text>
761
+ <Text> / — поиск</Text>
762
+ <Text> ? — помощь (это окно)</Text>
763
+ <Text> m — переключить режим (модули/функции)</Text>
764
+ <Text> Space — предпросмотр кода</Text>
765
+ <Text> ←/h — callers / fields / sources</Text>
766
+ <Text> →/l — callees / methods / targets</Text>
767
+ <Text> ↑/k — предыдущий элемент</Text>
768
+ <Text> ↓/j — следующий элемент</Text>
769
+ <Text> Enter — перейти к узлу</Text>
770
+ <Text> Bksp — назад</Text>
771
+ <Text> Tab — toggle callers/callees</Text>
772
+ </Box>
773
+ )}
774
+
748
775
  {/* Help footer */}
749
776
  <Box marginTop={1} borderStyle="single" borderColor="gray" paddingX={1}>
750
777
  <Text color="gray">
751
- ↑↓: Select | ←→: Panel | Enter: Open | Backspace: Back | /: Search | m: Modules | Space: Code | o: Editor | q: Quit
778
+ ↑↓: Select | ←→: Panel | Enter: Open | Backspace: Back | /: Search | m: Modules | Space: Code | o: Editor | ?: Help | q: Quit
752
779
  </Text>
753
780
  </Box>
754
781
  </Box>