@grafema/cli 0.2.4-beta → 0.2.6-beta

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 (139) hide show
  1. package/README.md +85 -0
  2. package/dist/cli.js +7 -2
  3. package/dist/cli.js.map +1 -0
  4. package/dist/commands/analyze.d.ts +3 -1
  5. package/dist/commands/analyze.d.ts.map +1 -1
  6. package/dist/commands/analyze.js +8 -266
  7. package/dist/commands/analyze.js.map +1 -0
  8. package/dist/commands/analyzeAction.d.ts +28 -0
  9. package/dist/commands/analyzeAction.d.ts.map +1 -0
  10. package/dist/commands/analyzeAction.js +243 -0
  11. package/dist/commands/analyzeAction.js.map +1 -0
  12. package/dist/commands/check.d.ts +2 -6
  13. package/dist/commands/check.d.ts.map +1 -1
  14. package/dist/commands/check.js +34 -48
  15. package/dist/commands/check.js.map +1 -0
  16. package/dist/commands/context.d.ts +16 -0
  17. package/dist/commands/context.d.ts.map +1 -0
  18. package/dist/commands/context.js +238 -0
  19. package/dist/commands/context.js.map +1 -0
  20. package/dist/commands/coverage.js +1 -0
  21. package/dist/commands/coverage.js.map +1 -0
  22. package/dist/commands/doctor/checks.d.ts.map +1 -1
  23. package/dist/commands/doctor/checks.js +10 -6
  24. package/dist/commands/doctor/checks.js.map +1 -0
  25. package/dist/commands/doctor/output.js +1 -0
  26. package/dist/commands/doctor/output.js.map +1 -0
  27. package/dist/commands/doctor/types.js +1 -0
  28. package/dist/commands/doctor/types.js.map +1 -0
  29. package/dist/commands/doctor.js +1 -0
  30. package/dist/commands/doctor.js.map +1 -0
  31. package/dist/commands/explain.d.ts.map +1 -1
  32. package/dist/commands/explain.js +5 -3
  33. package/dist/commands/explain.js.map +1 -0
  34. package/dist/commands/explore.d.ts.map +1 -1
  35. package/dist/commands/explore.js +9 -4
  36. package/dist/commands/explore.js.map +1 -0
  37. package/dist/commands/file.d.ts +15 -0
  38. package/dist/commands/file.d.ts.map +1 -0
  39. package/dist/commands/file.js +144 -0
  40. package/dist/commands/file.js.map +1 -0
  41. package/dist/commands/get.d.ts.map +1 -1
  42. package/dist/commands/get.js +7 -0
  43. package/dist/commands/get.js.map +1 -0
  44. package/dist/commands/impact.d.ts.map +1 -1
  45. package/dist/commands/impact.js +3 -3
  46. package/dist/commands/impact.js.map +1 -0
  47. package/dist/commands/init.d.ts.map +1 -1
  48. package/dist/commands/init.js +20 -2
  49. package/dist/commands/init.js.map +1 -0
  50. package/dist/commands/ls.d.ts.map +1 -1
  51. package/dist/commands/ls.js +10 -2
  52. package/dist/commands/ls.js.map +1 -0
  53. package/dist/commands/overview.d.ts.map +1 -1
  54. package/dist/commands/overview.js +1 -0
  55. package/dist/commands/overview.js.map +1 -0
  56. package/dist/commands/query.d.ts +8 -0
  57. package/dist/commands/query.d.ts.map +1 -1
  58. package/dist/commands/query.js +217 -43
  59. package/dist/commands/query.js.map +1 -0
  60. package/dist/commands/schema.d.ts.map +1 -1
  61. package/dist/commands/schema.js +4 -2
  62. package/dist/commands/schema.js.map +1 -0
  63. package/dist/commands/server.d.ts +2 -1
  64. package/dist/commands/server.d.ts.map +1 -1
  65. package/dist/commands/server.js +76 -14
  66. package/dist/commands/server.js.map +1 -0
  67. package/dist/commands/setup-skill.d.ts +17 -0
  68. package/dist/commands/setup-skill.d.ts.map +1 -0
  69. package/dist/commands/setup-skill.js +131 -0
  70. package/dist/commands/setup-skill.js.map +1 -0
  71. package/dist/commands/stats.js +1 -0
  72. package/dist/commands/stats.js.map +1 -0
  73. package/dist/commands/trace.d.ts.map +1 -1
  74. package/dist/commands/trace.js +21 -10
  75. package/dist/commands/trace.js.map +1 -0
  76. package/dist/commands/types.js +1 -0
  77. package/dist/commands/types.js.map +1 -0
  78. package/dist/plugins/builtinPlugins.d.ts +10 -0
  79. package/dist/plugins/builtinPlugins.d.ts.map +1 -0
  80. package/dist/plugins/builtinPlugins.js +68 -0
  81. package/dist/plugins/builtinPlugins.js.map +1 -0
  82. package/dist/plugins/pluginLoader.d.ts +16 -0
  83. package/dist/plugins/pluginLoader.d.ts.map +1 -0
  84. package/dist/plugins/pluginLoader.js +101 -0
  85. package/dist/plugins/pluginLoader.js.map +1 -0
  86. package/dist/plugins/pluginResolver.js +38 -0
  87. package/dist/utils/codePreview.d.ts +1 -0
  88. package/dist/utils/codePreview.d.ts.map +1 -1
  89. package/dist/utils/codePreview.js +6 -3
  90. package/dist/utils/codePreview.js.map +1 -0
  91. package/dist/utils/errorFormatter.js +1 -0
  92. package/dist/utils/errorFormatter.js.map +1 -0
  93. package/dist/utils/formatNode.d.ts +1 -1
  94. package/dist/utils/formatNode.d.ts.map +1 -1
  95. package/dist/utils/formatNode.js +3 -2
  96. package/dist/utils/formatNode.js.map +1 -0
  97. package/dist/utils/pathUtils.d.ts +2 -0
  98. package/dist/utils/pathUtils.d.ts.map +1 -0
  99. package/dist/utils/pathUtils.js +9 -0
  100. package/dist/utils/pathUtils.js.map +1 -0
  101. package/dist/utils/progressRenderer.d.ts +119 -0
  102. package/dist/utils/progressRenderer.d.ts.map +1 -0
  103. package/dist/utils/progressRenderer.js +245 -0
  104. package/dist/utils/progressRenderer.js.map +1 -0
  105. package/dist/utils/spinner.d.ts +39 -0
  106. package/dist/utils/spinner.d.ts.map +1 -0
  107. package/dist/utils/spinner.js +84 -0
  108. package/dist/utils/spinner.js.map +1 -0
  109. package/package.json +8 -9
  110. package/skills/grafema-codebase-analysis/SKILL.md +295 -0
  111. package/skills/grafema-codebase-analysis/references/node-edge-types.md +123 -0
  112. package/skills/grafema-codebase-analysis/references/query-patterns.md +205 -0
  113. package/src/cli.ts +8 -2
  114. package/src/commands/analyze.ts +7 -342
  115. package/src/commands/analyzeAction.ts +284 -0
  116. package/src/commands/check.ts +38 -70
  117. package/src/commands/context.ts +309 -0
  118. package/src/commands/doctor/checks.ts +9 -6
  119. package/src/commands/explain.ts +4 -3
  120. package/src/commands/explore.tsx +15 -9
  121. package/src/commands/file.ts +179 -0
  122. package/src/commands/get.ts +8 -0
  123. package/src/commands/impact.ts +3 -4
  124. package/src/commands/init.ts +19 -3
  125. package/src/commands/ls.ts +11 -2
  126. package/src/commands/overview.ts +0 -4
  127. package/src/commands/query.ts +235 -44
  128. package/src/commands/schema.ts +3 -2
  129. package/src/commands/server.ts +85 -15
  130. package/src/commands/setup-skill.ts +162 -0
  131. package/src/commands/trace.ts +18 -9
  132. package/src/plugins/builtinPlugins.ts +108 -0
  133. package/src/plugins/pluginLoader.ts +123 -0
  134. package/src/plugins/pluginResolver.js +38 -0
  135. package/src/utils/codePreview.ts +7 -3
  136. package/src/utils/formatNode.ts +3 -3
  137. package/src/utils/pathUtils.ts +9 -0
  138. package/src/utils/progressRenderer.ts +288 -0
  139. package/src/utils/spinner.ts +94 -0
package/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # @grafema/cli
2
+
3
+ > Grafema command-line interface for building and querying the code graph.
4
+
5
+ **Warning: This package is in beta stage and the API may change between minor versions.**
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ npx @grafema/cli init
11
+ npx @grafema/cli analyze
12
+ npx @grafema/cli overview
13
+ ```
14
+
15
+ ## Commands
16
+
17
+ ### Project setup
18
+
19
+ ```bash
20
+ npx @grafema/cli init # Create .grafema/config.yaml
21
+ npx @grafema/cli analyze # Build the graph
22
+ npx @grafema/cli overview # Summary of nodes/edges found
23
+ npx @grafema/cli schema # List node and edge types
24
+ npx @grafema/cli types # List available node types
25
+ ```
26
+
27
+ ### Querying the graph
28
+
29
+ ```bash
30
+ npx @grafema/cli query "auth" # Name search (partial match)
31
+ npx @grafema/cli query "function login" # Type + name
32
+ npx @grafema/cli query "route /api" # Route search
33
+ npx @grafema/cli query "token in authenticate" # Scope filtering
34
+ npx @grafema/cli query --type http:request "/api" # Exact type
35
+ npx @grafema/cli query --raw 'type(X, "FUNCTION")'
36
+ ```
37
+
38
+ ### Data flow tracing
39
+
40
+ ```bash
41
+ npx @grafema/cli trace "userId" # Trace variable sources/sinks
42
+ npx @grafema/cli trace "userId from authenticate" # Scoped trace
43
+ npx @grafema/cli trace --to "addNode#0.type" # Sink-based trace
44
+ npx @grafema/cli trace --from-route "GET /status" # Route response trace
45
+ ```
46
+
47
+ ### Navigation helpers
48
+
49
+ ```bash
50
+ npx @grafema/cli ls --type FUNCTION # List nodes by type
51
+ npx @grafema/cli get <semantic-id> # Get a single node by ID
52
+ npx @grafema/cli explain <node-id> # Explain a node (summary)
53
+ ```
54
+
55
+ ### Checks & diagnostics
56
+
57
+ ```bash
58
+ npx @grafema/cli check # Run all guarantees
59
+ npx @grafema/cli check dataflow # Run a diagnostic category
60
+ npx @grafema/cli check --list-categories
61
+ npx @grafema/cli doctor # Validate local setup
62
+ ```
63
+
64
+ ### Server management
65
+
66
+ ```bash
67
+ npx @grafema/cli server start # Start RFDB server
68
+ npx @grafema/cli server stop # Stop RFDB server
69
+ npx @grafema/cli server status # Check server status
70
+ ```
71
+
72
+ ### Misc
73
+
74
+ ```bash
75
+ npx @grafema/cli coverage # Coverage stats
76
+ npx @grafema/cli impact # Impact analysis
77
+ npx @grafema/cli explore # Interactive explorer (TUI)
78
+ npx @grafema/cli analyze --log-file analysis.log # Log to file
79
+ ```
80
+
81
+ ## Notes
82
+
83
+ - All commands accept `--project <path>` to point at a specific repo.
84
+ - `npx @grafema/cli` works without global install and is preferred for docs/examples.
85
+ - Unknown Datalog predicates in `--raw` queries will show a warning with suggestions.
package/dist/cli.js CHANGED
@@ -15,7 +15,7 @@ import { lsCommand } from './commands/ls.js';
15
15
  import { getCommand } from './commands/get.js';
16
16
  import { traceCommand } from './commands/trace.js';
17
17
  import { impactCommand } from './commands/impact.js';
18
- import { exploreCommand } from './commands/explore.js';
18
+ import { contextCommand } from './commands/context.js';
19
19
  import { statsCommand } from './commands/stats.js';
20
20
  import { checkCommand } from './commands/check.js';
21
21
  import { serverCommand } from './commands/server.js';
@@ -23,6 +23,8 @@ import { coverageCommand } from './commands/coverage.js';
23
23
  import { doctorCommand } from './commands/doctor.js';
24
24
  import { schemaCommand } from './commands/schema.js';
25
25
  import { explainCommand } from './commands/explain.js';
26
+ import { fileCommand } from './commands/file.js';
27
+ import { setupSkillCommand } from './commands/setup-skill.js';
26
28
  // Read version from package.json
27
29
  const __dirname = dirname(fileURLToPath(import.meta.url));
28
30
  const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
@@ -36,12 +38,12 @@ program.addCommand(initCommand);
36
38
  program.addCommand(analyzeCommand);
37
39
  program.addCommand(overviewCommand);
38
40
  program.addCommand(queryCommand);
41
+ program.addCommand(contextCommand);
39
42
  program.addCommand(typesCommand);
40
43
  program.addCommand(lsCommand);
41
44
  program.addCommand(getCommand);
42
45
  program.addCommand(traceCommand);
43
46
  program.addCommand(impactCommand);
44
- program.addCommand(exploreCommand);
45
47
  program.addCommand(statsCommand); // Keep for backwards compat
46
48
  program.addCommand(coverageCommand);
47
49
  program.addCommand(checkCommand);
@@ -49,4 +51,7 @@ program.addCommand(serverCommand);
49
51
  program.addCommand(doctorCommand);
50
52
  program.addCommand(schemaCommand);
51
53
  program.addCommand(explainCommand);
54
+ program.addCommand(fileCommand);
55
+ program.addCommand(setupSkillCommand);
52
56
  program.parse();
57
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  /**
2
- * Analyze command - Run project analysis via Orchestrator
2
+ * Analyze command Run project analysis via Orchestrator.
3
+ *
4
+ * Command definition only. Execution logic is in analyzeAction.ts.
3
5
  */
4
6
  import { Command } from 'commander';
5
7
  export declare const analyzeCommand: Command;
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgLpC,eAAO,MAAM,cAAc,SAgMvB,CAAC"}
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,cAAc,SA2BH,CAAC"}
@@ -1,129 +1,10 @@
1
1
  /**
2
- * Analyze command - Run project analysis via Orchestrator
2
+ * Analyze command Run project analysis via Orchestrator.
3
+ *
4
+ * Command definition only. Execution logic is in analyzeAction.ts.
3
5
  */
4
6
  import { Command } from 'commander';
5
- import { resolve, join } from 'path';
6
- import { existsSync, mkdirSync, readdirSync } from 'fs';
7
- import { pathToFileURL } from 'url';
8
- import { Orchestrator, RFDBServerBackend, DiagnosticReporter, DiagnosticWriter, createLogger, loadConfig,
9
- // Discovery
10
- SimpleProjectDiscovery, MonorepoServiceDiscovery, WorkspaceDiscovery,
11
- // Indexing
12
- JSModuleIndexer, RustModuleIndexer,
13
- // Analysis
14
- JSASTAnalyzer, ExpressRouteAnalyzer, ExpressResponseAnalyzer, SocketIOAnalyzer, DatabaseAnalyzer, FetchAnalyzer, ServiceLayerAnalyzer, ReactAnalyzer, RustAnalyzer,
15
- // Enrichment
16
- MethodCallResolver, ArgumentParameterLinker, AliasTracker, ValueDomainAnalyzer, MountPointResolver, PrefixEvaluator, InstanceOfResolver, ImportExportLinker, FunctionCallResolver, HTTPConnectionEnricher, RustFFIEnricher,
17
- // Validation
18
- CallResolverValidator, EvalBanValidator, SQLInjectionValidator, ShadowingDetector, GraphConnectivityValidator, DataFlowValidator, TypeScriptDeadCodeValidator, BrokenImportValidator, } from '@grafema/core';
19
- const BUILTIN_PLUGINS = {
20
- // Discovery
21
- SimpleProjectDiscovery: () => new SimpleProjectDiscovery(),
22
- MonorepoServiceDiscovery: () => new MonorepoServiceDiscovery(),
23
- WorkspaceDiscovery: () => new WorkspaceDiscovery(),
24
- // Indexing
25
- JSModuleIndexer: () => new JSModuleIndexer(),
26
- RustModuleIndexer: () => new RustModuleIndexer(),
27
- // Analysis
28
- JSASTAnalyzer: () => new JSASTAnalyzer(),
29
- ExpressRouteAnalyzer: () => new ExpressRouteAnalyzer(),
30
- ExpressResponseAnalyzer: () => new ExpressResponseAnalyzer(),
31
- SocketIOAnalyzer: () => new SocketIOAnalyzer(),
32
- DatabaseAnalyzer: () => new DatabaseAnalyzer(),
33
- FetchAnalyzer: () => new FetchAnalyzer(),
34
- ServiceLayerAnalyzer: () => new ServiceLayerAnalyzer(),
35
- ReactAnalyzer: () => new ReactAnalyzer(),
36
- RustAnalyzer: () => new RustAnalyzer(),
37
- // Enrichment
38
- MethodCallResolver: () => new MethodCallResolver(),
39
- ArgumentParameterLinker: () => new ArgumentParameterLinker(),
40
- AliasTracker: () => new AliasTracker(),
41
- ValueDomainAnalyzer: () => new ValueDomainAnalyzer(),
42
- MountPointResolver: () => new MountPointResolver(),
43
- PrefixEvaluator: () => new PrefixEvaluator(),
44
- InstanceOfResolver: () => new InstanceOfResolver(),
45
- ImportExportLinker: () => new ImportExportLinker(),
46
- FunctionCallResolver: () => new FunctionCallResolver(),
47
- HTTPConnectionEnricher: () => new HTTPConnectionEnricher(),
48
- RustFFIEnricher: () => new RustFFIEnricher(),
49
- // Validation
50
- CallResolverValidator: () => new CallResolverValidator(),
51
- EvalBanValidator: () => new EvalBanValidator(),
52
- SQLInjectionValidator: () => new SQLInjectionValidator(),
53
- ShadowingDetector: () => new ShadowingDetector(),
54
- GraphConnectivityValidator: () => new GraphConnectivityValidator(),
55
- DataFlowValidator: () => new DataFlowValidator(),
56
- TypeScriptDeadCodeValidator: () => new TypeScriptDeadCodeValidator(),
57
- BrokenImportValidator: () => new BrokenImportValidator(),
58
- };
59
- /**
60
- * Load custom plugins from .grafema/plugins/ directory
61
- */
62
- async function loadCustomPlugins(projectPath, log) {
63
- const pluginsDir = join(projectPath, '.grafema', 'plugins');
64
- if (!existsSync(pluginsDir)) {
65
- return {};
66
- }
67
- const customPlugins = {};
68
- try {
69
- const files = readdirSync(pluginsDir).filter((f) => f.endsWith('.js') || f.endsWith('.mjs'));
70
- for (const file of files) {
71
- try {
72
- const pluginPath = join(pluginsDir, file);
73
- const pluginUrl = pathToFileURL(pluginPath).href;
74
- const module = await import(pluginUrl);
75
- const PluginClass = module.default || module[file.replace(/\.(m?js)$/, '')];
76
- if (PluginClass && typeof PluginClass === 'function') {
77
- const pluginName = PluginClass.name || file.replace(/\.(m?js)$/, '');
78
- customPlugins[pluginName] = () => new PluginClass();
79
- log(`Loaded custom plugin: ${pluginName}`);
80
- }
81
- }
82
- catch (err) {
83
- console.warn(`Failed to load plugin ${file}: ${err.message}`);
84
- }
85
- }
86
- }
87
- catch (err) {
88
- console.warn(`Error loading custom plugins: ${err.message}`);
89
- }
90
- return customPlugins;
91
- }
92
- function createPlugins(config, customPlugins = {}) {
93
- const plugins = [];
94
- const phases = ['discovery', 'indexing', 'analysis', 'enrichment', 'validation'];
95
- for (const phase of phases) {
96
- const names = config[phase] || [];
97
- for (const name of names) {
98
- // Check built-in first, then custom
99
- const factory = BUILTIN_PLUGINS[name] || customPlugins[name];
100
- if (factory) {
101
- plugins.push(factory());
102
- }
103
- else {
104
- console.warn(`Unknown plugin: ${name}`);
105
- }
106
- }
107
- }
108
- return plugins;
109
- }
110
- /**
111
- * Determine log level from CLI options.
112
- * Priority: --log-level > --quiet > --verbose > default ('info')
113
- */
114
- function getLogLevel(options) {
115
- if (options.logLevel) {
116
- const validLevels = ['silent', 'errors', 'warnings', 'info', 'debug'];
117
- if (validLevels.includes(options.logLevel)) {
118
- return options.logLevel;
119
- }
120
- }
121
- if (options.quiet)
122
- return 'silent';
123
- if (options.verbose)
124
- return 'debug';
125
- return 'info';
126
- }
7
+ import { analyzeAction } from './analyzeAction.js';
127
8
  export const analyzeCommand = new Command('analyze')
128
9
  .description('Run project analysis')
129
10
  .argument('[path]', 'Project path to analyze', '.')
@@ -134,6 +15,7 @@ export const analyzeCommand = new Command('analyze')
134
15
  .option('-v, --verbose', 'Show verbose logging')
135
16
  .option('--debug', 'Enable debug mode (writes diagnostics.log)')
136
17
  .option('--log-level <level>', 'Set log level (silent, errors, warnings, info, debug)')
18
+ .option('--log-file <path>', 'Write all log output to a file')
137
19
  .option('--strict', 'Enable strict mode (fail on unresolved references)')
138
20
  .option('--auto-start', 'Auto-start RFDB server if not running')
139
21
  .addHelpText('after', `
@@ -144,151 +26,11 @@ Examples:
144
26
  grafema analyze -s api Analyze only "api" service (monorepo)
145
27
  grafema analyze -v Verbose output with progress details
146
28
  grafema analyze --debug Write diagnostics.log for debugging
29
+ grafema analyze --log-file out.log Write all logs to a file
147
30
  grafema analyze --strict Fail on unresolved references (debugging)
148
31
  grafema analyze --auto-start Auto-start server (useful for CI)
149
32
 
150
33
  Note: Start the server first with: grafema server start
151
34
  `)
152
- .action(async (path, options) => {
153
- const projectPath = resolve(path);
154
- const grafemaDir = join(projectPath, '.grafema');
155
- const dbPath = join(grafemaDir, 'graph.rfdb');
156
- if (!existsSync(grafemaDir)) {
157
- mkdirSync(grafemaDir, { recursive: true });
158
- }
159
- const log = options.quiet ? () => { } : console.log;
160
- // Create logger based on CLI flags
161
- const logLevel = getLogLevel(options);
162
- const logger = createLogger(logLevel);
163
- log(`Analyzing project: ${projectPath}`);
164
- // Connect to RFDB server
165
- // Default: require explicit `grafema server start`
166
- // Use --auto-start for CI or backwards compatibility
167
- const backend = new RFDBServerBackend({
168
- dbPath,
169
- autoStart: options.autoStart ?? false
170
- });
171
- try {
172
- await backend.connect();
173
- }
174
- catch (err) {
175
- if (!options.autoStart && err instanceof Error && err.message.includes('not running')) {
176
- console.error('');
177
- console.error('RFDB server is not running.');
178
- console.error('');
179
- console.error('Start the server first:');
180
- console.error(' grafema server start');
181
- console.error('');
182
- console.error('Or use --auto-start flag:');
183
- console.error(' grafema analyze --auto-start');
184
- console.error('');
185
- process.exit(1);
186
- }
187
- throw err;
188
- }
189
- if (options.clear) {
190
- log('Clearing existing database...');
191
- await backend.clear();
192
- }
193
- const config = loadConfig(projectPath, logger);
194
- // Extract services from config (REG-174)
195
- if (config.services.length > 0) {
196
- log(`Loaded ${config.services.length} service(s) from config`);
197
- for (const svc of config.services) {
198
- const entry = svc.entryPoint ? ` (entry: ${svc.entryPoint})` : '';
199
- log(` - ${svc.name}: ${svc.path}${entry}`);
200
- }
201
- }
202
- // Load custom plugins from .grafema/plugins/
203
- const customPlugins = await loadCustomPlugins(projectPath, log);
204
- const plugins = createPlugins(config.plugins, customPlugins);
205
- log(`Loaded ${plugins.length} plugins`);
206
- // Resolve strict mode: CLI flag overrides config
207
- const strictMode = options.strict ?? config.strict ?? false;
208
- if (strictMode) {
209
- log('Strict mode enabled - analysis will fail on unresolved references');
210
- }
211
- const startTime = Date.now();
212
- const orchestrator = new Orchestrator({
213
- graph: backend,
214
- plugins,
215
- serviceFilter: options.service || null,
216
- entrypoint: options.entrypoint,
217
- forceAnalysis: options.clear || false,
218
- logger,
219
- services: config.services.length > 0 ? config.services : undefined, // Pass config services (REG-174)
220
- strictMode, // REG-330: Pass strict mode flag
221
- onProgress: (progress) => {
222
- if (options.verbose) {
223
- log(`[${progress.phase}] ${progress.message}`);
224
- }
225
- },
226
- });
227
- let exitCode = 0;
228
- try {
229
- await orchestrator.run(projectPath);
230
- await backend.flush();
231
- const elapsed = ((Date.now() - startTime) / 1000).toFixed(2);
232
- const stats = await backend.getStats();
233
- log('');
234
- log(`Analysis complete in ${elapsed}s`);
235
- log(` Nodes: ${stats.nodeCount}`);
236
- log(` Edges: ${stats.edgeCount}`);
237
- // Get diagnostics and report summary
238
- const diagnostics = orchestrator.getDiagnostics();
239
- const reporter = new DiagnosticReporter(diagnostics);
240
- // Print summary if there are any issues
241
- if (diagnostics.count() > 0) {
242
- log('');
243
- log(reporter.categorizedSummary());
244
- // In verbose mode, print full report
245
- if (options.verbose) {
246
- log('');
247
- log(reporter.report({ format: 'text', includeSummary: false }));
248
- }
249
- }
250
- // Always write diagnostics.log (required for `grafema check` command)
251
- const writer = new DiagnosticWriter();
252
- await writer.write(diagnostics, grafemaDir);
253
- if (options.debug) {
254
- log(`Diagnostics written to ${writer.getLogPath(grafemaDir)}`);
255
- }
256
- // Determine exit code based on severity
257
- if (diagnostics.hasFatal()) {
258
- exitCode = 1;
259
- }
260
- else if (diagnostics.hasErrors()) {
261
- exitCode = 2; // Completed with errors
262
- }
263
- else {
264
- exitCode = 0; // Success (maybe warnings)
265
- }
266
- }
267
- catch (e) {
268
- // Orchestrator threw (fatal error stopped analysis)
269
- const error = e instanceof Error ? e : new Error(String(e));
270
- const diagnostics = orchestrator.getDiagnostics();
271
- const reporter = new DiagnosticReporter(diagnostics);
272
- console.error('');
273
- console.error(`✗ Analysis failed: ${error.message}`);
274
- console.error('');
275
- console.error('→ Run with --debug for detailed diagnostics');
276
- if (diagnostics.count() > 0) {
277
- console.error('');
278
- console.error(reporter.report({ format: 'text', includeSummary: true }));
279
- }
280
- // Write diagnostics.log in debug mode even on failure
281
- if (options.debug) {
282
- const writer = new DiagnosticWriter();
283
- await writer.write(diagnostics, grafemaDir);
284
- console.error(`Diagnostics written to ${writer.getLogPath(grafemaDir)}`);
285
- }
286
- exitCode = 1;
287
- }
288
- await backend.close();
289
- // Exit with appropriate code
290
- // 0 = success, 1 = fatal, 2 = errors
291
- if (exitCode !== 0) {
292
- process.exit(exitCode);
293
- }
294
- });
35
+ .action(analyzeAction);
36
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,sBAAsB,CAAC;KACnC,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,EAAE,GAAG,CAAC;KAClD,MAAM,CAAC,sBAAsB,EAAE,iCAAiC,CAAC;KACjE,MAAM,CAAC,yBAAyB,EAAE,+CAA+C,CAAC;KAClF,MAAM,CAAC,aAAa,EAAE,yCAAyC,CAAC;KAChE,MAAM,CAAC,aAAa,EAAE,0BAA0B,CAAC;KACjD,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;KAC/C,MAAM,CAAC,SAAS,EAAE,4CAA4C,CAAC;KAC/D,MAAM,CAAC,qBAAqB,EAAE,uDAAuD,CAAC;KACtF,MAAM,CAAC,mBAAmB,EAAE,gCAAgC,CAAC;KAC7D,MAAM,CAAC,UAAU,EAAE,oDAAoD,CAAC;KACxE,MAAM,CAAC,cAAc,EAAE,uCAAuC,CAAC;KAC/D,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;;;;CAavB,CAAC;KACC,MAAM,CAAC,aAAa,CAAC,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Analyze command action — connects to RFDB, loads plugins, runs Orchestrator.
3
+ *
4
+ * Extracted from analyze.ts (REG-435) to keep command definition separate
5
+ * from execution logic.
6
+ */
7
+ export interface NodeEdgeCountBackend {
8
+ nodeCount: () => Promise<number>;
9
+ edgeCount: () => Promise<number>;
10
+ }
11
+ export declare function fetchNodeEdgeCounts(backend: NodeEdgeCountBackend): Promise<{
12
+ nodeCount: number;
13
+ edgeCount: number;
14
+ }>;
15
+ export declare function exitWithCode(code: number, exitFn?: (code: number) => void): void;
16
+ export declare function analyzeAction(path: string, options: {
17
+ service?: string;
18
+ entrypoint?: string;
19
+ clear?: boolean;
20
+ quiet?: boolean;
21
+ verbose?: boolean;
22
+ debug?: boolean;
23
+ logLevel?: string;
24
+ logFile?: string;
25
+ strict?: boolean;
26
+ autoStart?: boolean;
27
+ }): Promise<void>;
28
+ //# sourceMappingURL=analyzeAction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzeAction.d.ts","sourceRoot":"","sources":["../../src/commands/analyzeAction.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiBH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAClC;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAG1H;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAmB,GAAG,IAAI,CAE9F;AAqBD,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoOrQ"}