code-auditor-mcp 2.6.2 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -196
- package/dist/analyzers/analyzerUtils.d.ts +13 -11
- package/dist/analyzers/analyzerUtils.d.ts.map +1 -1
- package/dist/analyzers/analyzerUtils.js +22 -56
- package/dist/analyzers/analyzerUtils.js.map +1 -1
- package/dist/analyzers/cross-language/APIContractAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/cross-language/CrossLanguageSOLIDAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/cross-language/CrossLanguageSOLIDAnalyzer.js.map +1 -1
- package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts.map +1 -1
- package/dist/analyzers/cross-language/DependencyGraphBuilder.js.map +1 -1
- package/dist/analyzers/cross-language/SchemaValidator.d.ts.map +1 -1
- package/dist/analyzers/cross-language/SchemaValidator.js.map +1 -1
- package/dist/analyzers/dataAccessAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/dataAccessAnalyzer.js +50 -24
- package/dist/analyzers/dataAccessAnalyzer.js.map +1 -1
- package/dist/analyzers/documentationAnalyzer.d.ts +4 -1
- package/dist/analyzers/documentationAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/documentationAnalyzer.js +210 -111
- package/dist/analyzers/documentationAnalyzer.js.map +1 -1
- package/dist/analyzers/dryAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/dryAnalyzer.js +190 -58
- package/dist/analyzers/dryAnalyzer.js.map +1 -1
- package/dist/analyzers/invariantsAnalyzer.d.ts +20 -0
- package/dist/analyzers/invariantsAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/invariantsAnalyzer.js +148 -0
- package/dist/analyzers/invariantsAnalyzer.js.map +1 -0
- package/dist/analyzers/reactAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/reactAnalyzer.js +2 -2
- package/dist/analyzers/reactAnalyzer.js.map +1 -1
- package/dist/analyzers/schemaAnalyzer.d.ts +2 -0
- package/dist/analyzers/schemaAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/schemaAnalyzer.js +306 -147
- package/dist/analyzers/schemaAnalyzer.js.map +1 -1
- package/dist/analyzers/solidAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/solidAnalyzer.js +145 -119
- package/dist/analyzers/solidAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts +3 -1
- package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalDRYAnalyzer.js +41 -1
- package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js +8 -8
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalDocumentationAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js +6 -6
- package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.js +1 -1
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.js.map +1 -1
- package/dist/api/index.js +1 -0
- package/dist/api/index.js.map +1 -1
- package/dist/auditRunner.d.ts.map +1 -1
- package/dist/auditRunner.js +367 -24
- package/dist/auditRunner.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +740 -18
- package/dist/cli.js.map +1 -1
- package/dist/codeIndexDB-enhanced.d.ts +35 -13
- package/dist/codeIndexDB-enhanced.d.ts.map +1 -1
- package/dist/codeIndexDB-enhanced.js +311 -214
- package/dist/codeIndexDB-enhanced.js.map +1 -1
- package/dist/{codeIndexDb.d.ts → codeIndexDB.d.ts} +51 -224
- package/dist/codeIndexDB.d.ts.map +1 -0
- package/dist/codeIndexDB.js +2042 -0
- package/dist/codeIndexDB.js.map +1 -0
- package/dist/codeIndexService.d.ts.map +1 -1
- package/dist/codeIndexService.js.map +1 -1
- package/dist/componentScanner.d.ts +14 -8
- package/dist/componentScanner.d.ts.map +1 -1
- package/dist/componentScanner.js +136 -113
- package/dist/componentScanner.js.map +1 -1
- package/dist/config/configLoader.d.ts.map +1 -1
- package/dist/config/configLoader.js +10 -7
- package/dist/config/configLoader.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/fingerprint.d.ts +15 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/fingerprint.js +32 -0
- package/dist/fingerprint.js.map +1 -0
- package/dist/functionScanner.d.ts +5 -0
- package/dist/functionScanner.d.ts.map +1 -1
- package/dist/functionScanner.js +417 -341
- package/dist/functionScanner.js.map +1 -1
- package/dist/generators/AWSQConfigGenerator.d.ts.map +1 -1
- package/dist/generators/AiderConfigGenerator.d.ts.map +1 -1
- package/dist/generators/BaseConfigGenerator.d.ts.map +1 -1
- package/dist/generators/BaseConfigGenerator.js.map +1 -1
- package/dist/generators/ClaudeConfigGenerator.d.ts.map +1 -1
- package/dist/generators/ClineConfigGenerator.d.ts.map +1 -1
- package/dist/generators/CodeiumConfigGenerator.d.ts.map +1 -1
- package/dist/generators/ConfigGeneratorFactory.d.ts.map +1 -1
- package/dist/generators/ConfigGeneratorFactory.js.map +1 -1
- package/dist/generators/ContinueConfigGenerator.d.ts.map +1 -1
- package/dist/generators/CopilotConfigGenerator.d.ts.map +1 -1
- package/dist/generators/CursorConfigGenerator.d.ts.map +1 -1
- package/dist/generators/JetBrainsConfigGenerator.d.ts.map +1 -1
- package/dist/generators/VSCodeConfigGenerator.d.ts.map +1 -1
- package/dist/grammars/tree-sitter-go.wasm +0 -0
- package/dist/grammars/tree-sitter-javascript.wasm +0 -0
- package/dist/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/invariants/index.d.ts +9 -0
- package/dist/invariants/index.d.ts.map +1 -0
- package/dist/invariants/index.js +4 -0
- package/dist/invariants/index.js.map +1 -0
- package/dist/invariants/invariant-rules.schema.json +137 -0
- package/dist/invariants/ruleEngine.d.ts +32 -0
- package/dist/invariants/ruleEngine.d.ts.map +1 -0
- package/dist/invariants/ruleEngine.js +536 -0
- package/dist/invariants/ruleEngine.js.map +1 -0
- package/dist/invariants/ruleValidator.d.ts +17 -0
- package/dist/invariants/ruleValidator.d.ts.map +1 -0
- package/dist/invariants/ruleValidator.js +264 -0
- package/dist/invariants/ruleValidator.js.map +1 -0
- package/dist/invariants/types.d.ts +78 -0
- package/dist/invariants/types.d.ts.map +1 -0
- package/dist/invariants/types.js +5 -0
- package/dist/invariants/types.js.map +1 -0
- package/dist/languages/LanguageOrchestrator.d.ts.map +1 -1
- package/dist/languages/LanguageOrchestrator.js.map +1 -1
- package/dist/languages/LanguageRegistry.d.ts.map +1 -1
- package/dist/languages/RuntimeManager.d.ts.map +1 -1
- package/dist/languages/RuntimeManager.js +1 -1
- package/dist/languages/RuntimeManager.js.map +1 -1
- package/dist/languages/UniversalAnalyzer.d.ts.map +1 -1
- package/dist/languages/UniversalAnalyzer.js.map +1 -1
- package/dist/languages/adapterBridge.d.ts +102 -0
- package/dist/languages/adapterBridge.d.ts.map +1 -0
- package/dist/languages/adapterBridge.js +382 -0
- package/dist/languages/adapterBridge.js.map +1 -0
- package/dist/languages/go/GoAdapter.d.ts +37 -26
- package/dist/languages/go/GoAdapter.d.ts.map +1 -1
- package/dist/languages/go/GoAdapter.js +560 -281
- package/dist/languages/go/GoAdapter.js.map +1 -1
- package/dist/languages/index.d.ts +5 -2
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js +11 -9
- package/dist/languages/index.js.map +1 -1
- package/dist/languages/tree-sitter/converter.d.ts +43 -0
- package/dist/languages/tree-sitter/converter.d.ts.map +1 -0
- package/dist/languages/tree-sitter/converter.js +150 -0
- package/dist/languages/tree-sitter/converter.js.map +1 -0
- package/dist/languages/tree-sitter/parser.d.ts +36 -0
- package/dist/languages/tree-sitter/parser.d.ts.map +1 -0
- package/dist/languages/tree-sitter/parser.js +114 -0
- package/dist/languages/tree-sitter/parser.js.map +1 -0
- package/dist/languages/types.d.ts +11 -0
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts +92 -0
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -0
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +951 -0
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -0
- package/dist/mcp-tools/projectTasks.d.ts +58 -22
- package/dist/mcp-tools/projectTasks.d.ts.map +1 -1
- package/dist/mcp-tools/projectTasks.js +172 -10
- package/dist/mcp-tools/projectTasks.js.map +1 -1
- package/dist/mcp-tools/whitelistTools.d.ts +21 -21
- package/dist/mcp-tools/whitelistTools.d.ts.map +1 -1
- package/dist/mcp-tools/workflowGuide.d.ts.map +1 -1
- package/dist/mcp-tools/workflowGuide.js +130 -126
- package/dist/mcp-tools/workflowGuide.js.map +1 -1
- package/dist/mcp-tools-shared.d.ts.map +1 -1
- package/dist/mcp-tools-shared.js.map +1 -1
- package/dist/mcp-ui-simple.js +1 -1
- package/dist/mcp-ui-simple.js.map +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +1376 -1181
- package/dist/mcp.js.map +1 -1
- package/dist/mcpAuditJobs.d.ts +4 -0
- package/dist/mcpAuditJobs.d.ts.map +1 -1
- package/dist/mcpAuditJobs.js +49 -2
- package/dist/mcpAuditJobs.js.map +1 -1
- package/dist/mcpToolErrors.d.ts.map +1 -1
- package/dist/mcpToolErrors.js.map +1 -1
- package/dist/native/ast-grep-napi.darwin-arm64.node +0 -0
- package/dist/native/ast-grep-napi.darwin-x64.node +0 -0
- package/dist/native/ast-grep-napi.linux-arm64-gnu.node +0 -0
- package/dist/native/ast-grep-napi.linux-arm64-musl.node +0 -0
- package/dist/native/ast-grep-napi.linux-x64-gnu.node +0 -0
- package/dist/native/ast-grep-napi.linux-x64-musl.node +0 -0
- package/dist/native/ast-grep-napi.win32-x64-msvc.node +0 -0
- package/dist/native-bootstrap.d.ts +15 -0
- package/dist/native-bootstrap.d.ts.map +1 -0
- package/dist/native-bootstrap.js +75 -0
- package/dist/native-bootstrap.js.map +1 -0
- package/dist/reporting/csvReportGenerator.d.ts.map +1 -1
- package/dist/reporting/htmlReportGenerator.d.ts.map +1 -1
- package/dist/reporting/jsonReportGenerator.d.ts.map +1 -1
- package/dist/reporting/reportGenerator.d.ts.map +1 -1
- package/dist/reporting/reportGenerator.js +4 -0
- package/dist/reporting/reportGenerator.js.map +1 -1
- package/dist/reporting/sarifReportGenerator.d.ts +39 -0
- package/dist/reporting/sarifReportGenerator.d.ts.map +1 -0
- package/dist/reporting/sarifReportGenerator.js +229 -0
- package/dist/reporting/sarifReportGenerator.js.map +1 -0
- package/dist/search/QueryParser.d.ts +41 -0
- package/dist/search/QueryParser.d.ts.map +1 -1
- package/dist/search/QueryParser.js +200 -19
- package/dist/search/QueryParser.js.map +1 -1
- package/dist/services/CodeMapGenerator.d.ts.map +1 -1
- package/dist/services/CodeMapGenerator.js +4 -4
- package/dist/services/CodeMapGenerator.js.map +1 -1
- package/dist/services/ProjectTaskRepository.d.ts +15 -2
- package/dist/services/ProjectTaskRepository.d.ts.map +1 -1
- package/dist/services/ProjectTaskRepository.js +16 -1
- package/dist/services/ProjectTaskRepository.js.map +1 -1
- package/dist/services/SchemaParser.d.ts.map +1 -1
- package/dist/services/SchemaParser.js +5 -8
- package/dist/services/SchemaParser.js.map +1 -1
- package/dist/services/auditJobService.d.ts +1 -1
- package/dist/services/projectTaskHelpers.js.map +1 -1
- package/dist/services/whitelistService.d.ts.map +1 -1
- package/dist/services/whitelistService.js +1 -1
- package/dist/services/whitelistService.js.map +1 -1
- package/dist/tool-registry.d.ts +79 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +139 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/types/projectTask.d.ts +4 -0
- package/dist/types/projectTask.d.ts.map +1 -1
- package/dist/types.d.ts +26 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/ui/InteractivePrompts.d.ts.map +1 -1
- package/dist/ui/InteractivePrompts.js.map +1 -1
- package/dist/utils/astParser.d.ts +31 -38
- package/dist/utils/astParser.d.ts.map +1 -1
- package/dist/utils/astParser.js +138 -196
- package/dist/utils/astParser.js.map +1 -1
- package/dist/utils/astUtils.d.ts +87 -58
- package/dist/utils/astUtils.d.ts.map +1 -1
- package/dist/utils/astUtils.js +852 -581
- package/dist/utils/astUtils.js.map +1 -1
- package/dist/utils/componentPatterns.js.map +1 -1
- package/dist/utils/componentResponsibility.d.ts +13 -9
- package/dist/utils/componentResponsibility.d.ts.map +1 -1
- package/dist/utils/componentResponsibility.js +236 -206
- package/dist/utils/componentResponsibility.js.map +1 -1
- package/dist/utils/dependencyExtractor.d.ts +11 -6
- package/dist/utils/dependencyExtractor.d.ts.map +1 -1
- package/dist/utils/dependencyExtractor.js +200 -119
- package/dist/utils/dependencyExtractor.js.map +1 -1
- package/dist/utils/fileDiscovery.d.ts +1 -1
- package/dist/utils/fileDiscovery.d.ts.map +1 -1
- package/dist/utils/fileDiscovery.js +15 -6
- package/dist/utils/fileDiscovery.js.map +1 -1
- package/dist/utils/jsDocParser.d.ts +27 -30
- package/dist/utils/jsDocParser.d.ts.map +1 -1
- package/dist/utils/jsDocParser.js +271 -207
- package/dist/utils/jsDocParser.js.map +1 -1
- package/dist/utils/reactDetection.d.ts +27 -12
- package/dist/utils/reactDetection.d.ts.map +1 -1
- package/dist/utils/reactDetection.js +331 -219
- package/dist/utils/reactDetection.js.map +1 -1
- package/dist/workers/auditWorker.js +17 -3
- package/dist/workers/auditWorker.js.map +1 -1
- package/package.json +54 -51
- package/dist/adapters/GoAdapter.d.ts +0 -53
- package/dist/adapters/GoAdapter.d.ts.map +0 -1
- package/dist/adapters/GoAdapter.js +0 -611
- package/dist/adapters/GoAdapter.js.map +0 -1
- package/dist/adapters/GoConfig.d.ts +0 -35
- package/dist/adapters/GoConfig.d.ts.map +0 -1
- package/dist/adapters/GoConfig.js +0 -155
- package/dist/adapters/GoConfig.js.map +0 -1
- package/dist/adapters/LanguageAdapter.d.ts +0 -135
- package/dist/adapters/LanguageAdapter.d.ts.map +0 -1
- package/dist/adapters/LanguageAdapter.js +0 -47
- package/dist/adapters/LanguageAdapter.js.map +0 -1
- package/dist/adapters/TypeScriptAdapter.d.ts +0 -43
- package/dist/adapters/TypeScriptAdapter.d.ts.map +0 -1
- package/dist/adapters/TypeScriptAdapter.js +0 -386
- package/dist/adapters/TypeScriptAdapter.js.map +0 -1
- package/dist/adapters/UniversalAnalyzer.d.ts +0 -42
- package/dist/adapters/UniversalAnalyzer.d.ts.map +0 -1
- package/dist/adapters/UniversalAnalyzer.js +0 -103
- package/dist/adapters/UniversalAnalyzer.js.map +0 -1
- package/dist/adapters/UniversalSOLIDAnalyzer.d.ts +0 -48
- package/dist/adapters/UniversalSOLIDAnalyzer.d.ts.map +0 -1
- package/dist/adapters/UniversalSOLIDAnalyzer.js +0 -178
- package/dist/adapters/UniversalSOLIDAnalyzer.js.map +0 -1
- package/dist/adapters/solidAnalyzerCompat.d.ts +0 -21
- package/dist/adapters/solidAnalyzerCompat.d.ts.map +0 -1
- package/dist/adapters/solidAnalyzerCompat.js +0 -78
- package/dist/adapters/solidAnalyzerCompat.js.map +0 -1
- package/dist/analyzers/dataAccessAnalyzerCompat.d.ts +0 -20
- package/dist/analyzers/dataAccessAnalyzerCompat.d.ts.map +0 -1
- package/dist/analyzers/dataAccessAnalyzerCompat.js +0 -59
- package/dist/analyzers/dataAccessAnalyzerCompat.js.map +0 -1
- package/dist/analyzers/documentationAnalyzerCompat.d.ts +0 -20
- package/dist/analyzers/documentationAnalyzerCompat.d.ts.map +0 -1
- package/dist/analyzers/documentationAnalyzerCompat.js +0 -52
- package/dist/analyzers/documentationAnalyzerCompat.js.map +0 -1
- package/dist/analyzers/dryAnalyzerCompat.d.ts +0 -20
- package/dist/analyzers/dryAnalyzerCompat.d.ts.map +0 -1
- package/dist/analyzers/dryAnalyzerCompat.js +0 -44
- package/dist/analyzers/dryAnalyzerCompat.js.map +0 -1
- package/dist/analyzers/schemaAnalyzerCompat.d.ts +0 -20
- package/dist/analyzers/schemaAnalyzerCompat.d.ts.map +0 -1
- package/dist/analyzers/schemaAnalyzerCompat.js +0 -69
- package/dist/analyzers/schemaAnalyzerCompat.js.map +0 -1
- package/dist/analyzers/solidAnalyzerCompat.d.ts +0 -20
- package/dist/analyzers/solidAnalyzerCompat.d.ts.map +0 -1
- package/dist/analyzers/solidAnalyzerCompat.js +0 -78
- package/dist/analyzers/solidAnalyzerCompat.js.map +0 -1
- package/dist/codeIndexDb.d.ts.map +0 -1
- package/dist/codeIndexDb.js +0 -2102
- package/dist/codeIndexDb.js.map +0 -1
- package/dist/languages/typescript/TypeScriptAdapter.d.ts +0 -108
- package/dist/languages/typescript/TypeScriptAdapter.d.ts.map +0 -1
- package/dist/languages/typescript/TypeScriptAdapter.js +0 -567
- package/dist/languages/typescript/TypeScriptAdapter.js.map +0 -1
- package/dist/languages/typescript/test-extraction.d.ts +0 -2
- package/dist/languages/typescript/test-extraction.d.ts.map +0 -1
- package/dist/languages/typescript/test-extraction.js +0 -36
- package/dist/languages/typescript/test-extraction.js.map +0 -1
- package/dist/mcp-hybrid.d.ts +0 -10
- package/dist/mcp-hybrid.d.ts.map +0 -1
- package/dist/mcp-hybrid.js +0 -41
- package/dist/mcp-hybrid.js.map +0 -1
- package/dist/mcp-index.d.ts +0 -13
- package/dist/mcp-index.d.ts.map +0 -1
- package/dist/mcp-index.js +0 -136
- package/dist/mcp-index.js.map +0 -1
- package/dist/mcp-standalone.d.ts +0 -3
- package/dist/mcp-standalone.d.ts.map +0 -1
- package/dist/mcp-standalone.js +0 -1324
- package/dist/mcp-standalone.js.map +0 -1
- package/dist/mcp-ui-server.d.ts +0 -27
- package/dist/mcp-ui-server.d.ts.map +0 -1
- package/dist/mcp-ui-server.js +0 -484
- package/dist/mcp-ui-server.js.map +0 -1
- package/dist/test-multi-strategy-search.d.ts +0 -3
- package/dist/test-multi-strategy-search.d.ts.map +0 -1
- package/dist/test-multi-strategy-search.js +0 -170
- package/dist/test-multi-strategy-search.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -2,17 +2,23 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Code Auditor CLI - Enhanced with AI Tool Integration
|
|
4
4
|
*/
|
|
5
|
+
// MUST be first import: sets NAPI_RS_NATIVE_LIBRARY_PATH before @ast-grep/napi loads
|
|
6
|
+
import './native-bootstrap.js';
|
|
5
7
|
import { Command } from 'commander';
|
|
6
8
|
import chalk from 'chalk';
|
|
7
9
|
import { createAuditRunner } from './auditRunner.js';
|
|
8
10
|
import { readFileSync } from 'fs';
|
|
9
11
|
import { promises as fs } from 'fs';
|
|
12
|
+
import { createInterface } from 'readline';
|
|
10
13
|
import { fileURLToPath } from 'url';
|
|
11
|
-
import { dirname, join, resolve } from 'path';
|
|
14
|
+
import { dirname, isAbsolute, join, relative, resolve } from 'path';
|
|
12
15
|
import { ConfigGeneratorFactory } from './generators/ConfigGeneratorFactory.js';
|
|
13
16
|
import { InteractivePrompts } from './ui/InteractivePrompts.js';
|
|
14
17
|
import { DEFAULT_SERVER_URL, DEFAULT_PORT } from './constants.js';
|
|
15
18
|
import { CodeMapGenerator } from './services/CodeMapGenerator.js';
|
|
19
|
+
import { initParsers } from './languages/index.js';
|
|
20
|
+
import { queryParser } from './search/QueryParser.js';
|
|
21
|
+
import { CodeIndexDB } from './codeIndexDB.js';
|
|
16
22
|
// Get package.json for version info
|
|
17
23
|
const __filename = fileURLToPath(import.meta.url);
|
|
18
24
|
const __dirname = dirname(__filename);
|
|
@@ -30,10 +36,12 @@ program
|
|
|
30
36
|
.option('-p, --path <path>', 'Path to audit', process.cwd())
|
|
31
37
|
.option('-c, --config <config>', 'Configuration name')
|
|
32
38
|
.option('-o, --output <dir>', 'Output directory for reports')
|
|
39
|
+
.option('-f, --format <format>', 'Report format: html, json, csv, or sarif')
|
|
33
40
|
.action(async (options) => {
|
|
34
41
|
console.log(chalk.blue('🔍 Code Quality Audit Tool'));
|
|
35
42
|
console.log(chalk.gray('══════════════════════════════════════════════════'));
|
|
36
43
|
try {
|
|
44
|
+
await initParsers();
|
|
37
45
|
const runner = createAuditRunner({
|
|
38
46
|
projectRoot: options.path,
|
|
39
47
|
configName: options.config,
|
|
@@ -44,6 +52,148 @@ program
|
|
|
44
52
|
console.log(`Critical: ${result.summary.criticalIssues}`);
|
|
45
53
|
console.log(`Warnings: ${result.summary.warnings}`);
|
|
46
54
|
console.log(`Suggestions: ${result.summary.suggestions}`);
|
|
55
|
+
// Generate formatted report if --format is specified
|
|
56
|
+
if (options.format) {
|
|
57
|
+
const validFormats = ['html', 'json', 'csv', 'sarif'];
|
|
58
|
+
if (!validFormats.includes(options.format)) {
|
|
59
|
+
console.error(chalk.red(`Unknown format: "${options.format}". Must be one of: ${validFormats.join(', ')}`));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
const { generateReport } = await import('./reporting/reportGenerator.js');
|
|
63
|
+
const report = generateReport(result, options.format);
|
|
64
|
+
const outputDir = options.output || process.cwd();
|
|
65
|
+
const ext = options.format === 'sarif' ? 'sarif' : options.format;
|
|
66
|
+
const reportPath = join(outputDir, `audit-report.${ext}`);
|
|
67
|
+
await fs.writeFile(reportPath, report, 'utf-8');
|
|
68
|
+
console.log(chalk.green(`\nReport written to ${reportPath}`));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.error(chalk.red('Error:'), error);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
// Diff-scoped audit command (Spec 04 R4)
|
|
77
|
+
program
|
|
78
|
+
.command('changed [paths...]')
|
|
79
|
+
.description('Audit changed files only — reads stdin when --stdin is set')
|
|
80
|
+
.option('--json', 'Output violations as machine-readable JSON to stdout')
|
|
81
|
+
.option('-f, --format <format>', 'Report format: json, or sarif (overrides --json)')
|
|
82
|
+
.option('--quiet', 'Suppress output when zero violations')
|
|
83
|
+
.option('--fail-on <severity>', 'Exit code 2 when violations at or above this severity exist', 'critical')
|
|
84
|
+
.option('--stdin', 'Read file paths from stdin (one per line)')
|
|
85
|
+
.option('-p, --path <projectPath>', 'Project root path', process.cwd())
|
|
86
|
+
.action(async (paths, options) => {
|
|
87
|
+
try {
|
|
88
|
+
await initParsers();
|
|
89
|
+
const fileSet = new Set();
|
|
90
|
+
// Collect paths from stdin if requested
|
|
91
|
+
if (options.stdin) {
|
|
92
|
+
const rl = createInterface({
|
|
93
|
+
input: process.stdin,
|
|
94
|
+
output: undefined,
|
|
95
|
+
terminal: false
|
|
96
|
+
});
|
|
97
|
+
for await (const line of rl) {
|
|
98
|
+
const trimmed = line.trim();
|
|
99
|
+
if (trimmed)
|
|
100
|
+
fileSet.add(trimmed);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Add paths from command line
|
|
104
|
+
for (const p of paths) {
|
|
105
|
+
fileSet.add(p);
|
|
106
|
+
}
|
|
107
|
+
// Resolve scope
|
|
108
|
+
let scope = 'changed';
|
|
109
|
+
if (fileSet.size > 0) {
|
|
110
|
+
// Convert to absolute paths
|
|
111
|
+
const resolved = [...fileSet].map((f) => isAbsolute(f) ? f : resolve(process.cwd(), f));
|
|
112
|
+
scope = resolved;
|
|
113
|
+
}
|
|
114
|
+
// Validate --fail-on severity
|
|
115
|
+
const validSeverities = ['critical', 'warning', 'suggestion'];
|
|
116
|
+
const failOnSeverity = options.failOn;
|
|
117
|
+
if (!validSeverities.includes(failOnSeverity)) {
|
|
118
|
+
console.error(chalk.red(`Invalid --fail-on severity: "${failOnSeverity}". Must be one of: ${validSeverities.join(', ')}`));
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
// Create runner
|
|
122
|
+
const runner = createAuditRunner({
|
|
123
|
+
projectRoot: options.path,
|
|
124
|
+
scope,
|
|
125
|
+
analyzerConcurrency: 4
|
|
126
|
+
});
|
|
127
|
+
const result = await runner.run();
|
|
128
|
+
// Collect all violations
|
|
129
|
+
const violations = Object.values(result.analyzerResults).flatMap((r) => r.violations || []);
|
|
130
|
+
// JSON output
|
|
131
|
+
if (options.format === 'sarif') {
|
|
132
|
+
const { generateSARIFReport } = await import('./reporting/sarifReportGenerator.js');
|
|
133
|
+
const sarifOutput = generateSARIFReport(result);
|
|
134
|
+
process.stdout.write(sarifOutput + '\n');
|
|
135
|
+
}
|
|
136
|
+
else if (options.json) {
|
|
137
|
+
const projectDir = resolve(options.path || process.cwd());
|
|
138
|
+
const jsonOutput = violations.map((v) => {
|
|
139
|
+
// Compute relative path if file resolves inside the project
|
|
140
|
+
let filePath = v.file || '';
|
|
141
|
+
if (filePath.startsWith('/') || filePath.startsWith('\\\\')) {
|
|
142
|
+
const rel = relative(projectDir, filePath);
|
|
143
|
+
// Only use relative path if it doesn't escape the project
|
|
144
|
+
if (!rel.startsWith('..') && !isAbsolute(rel)) {
|
|
145
|
+
filePath = rel;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Find column: prefer explicit column, then start.column, then default to 1
|
|
149
|
+
const col = v.column ?? v.start?.column ?? 1;
|
|
150
|
+
return {
|
|
151
|
+
analyzer: v.analyzer || '',
|
|
152
|
+
rule: v.rule || v.type || '',
|
|
153
|
+
severity: v.severity,
|
|
154
|
+
message: v.message,
|
|
155
|
+
file: filePath,
|
|
156
|
+
line: v.line ?? v.start?.line,
|
|
157
|
+
column: col,
|
|
158
|
+
endLine: v.end?.line,
|
|
159
|
+
endColumn: v.end?.column,
|
|
160
|
+
enclosingSymbol: v.symbol || v.enclosingFunction || '',
|
|
161
|
+
suggestion: v.suggestion || '',
|
|
162
|
+
details: v.details || ''
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
process.stdout.write(JSON.stringify(jsonOutput, null, 2) + '\n');
|
|
166
|
+
}
|
|
167
|
+
else if (!options.quiet || violations.length > 0) {
|
|
168
|
+
// Console output
|
|
169
|
+
console.log(chalk.blue('🔍 Diff-Scoped Code Audit'));
|
|
170
|
+
console.log(chalk.gray('══════════════════════════════════════════════════'));
|
|
171
|
+
console.log(chalk.gray(`Files analyzed: ${result.metadata.filesAnalyzed}`));
|
|
172
|
+
console.log(`\nFound ${violations.length} violations`);
|
|
173
|
+
console.log(`Critical: ${result.summary.criticalIssues}`);
|
|
174
|
+
console.log(`Warnings: ${result.summary.warnings}`);
|
|
175
|
+
console.log(`Suggestions: ${result.summary.suggestions}`);
|
|
176
|
+
if (violations.length > 0) {
|
|
177
|
+
console.log(chalk.gray('\n── Violations ────────────────────────────────────'));
|
|
178
|
+
for (const v of violations) {
|
|
179
|
+
const icon = v.severity === 'critical' ? '🔴' :
|
|
180
|
+
v.severity === 'warning' ? '🟡' : '🔵';
|
|
181
|
+
console.log(`${icon} ${chalk.bold(v.file)}${v.line ? `:${v.line}` : ''} [${v.severity}] ${v.message}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Exit code based on --fail-on
|
|
186
|
+
if (failOnSeverity) {
|
|
187
|
+
const severityOrder = ['critical', 'warning', 'suggestion'];
|
|
188
|
+
const failIndex = severityOrder.indexOf(failOnSeverity);
|
|
189
|
+
const hasAtOrAbove = violations.some((v) => {
|
|
190
|
+
const vIndex = severityOrder.indexOf(v.severity);
|
|
191
|
+
return vIndex >= 0 && vIndex <= failIndex;
|
|
192
|
+
});
|
|
193
|
+
if (hasAtOrAbove) {
|
|
194
|
+
process.exit(2);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
47
197
|
}
|
|
48
198
|
catch (error) {
|
|
49
199
|
console.error(chalk.red('Error:'), error);
|
|
@@ -85,27 +235,226 @@ program
|
|
|
85
235
|
console.log('Options:', options);
|
|
86
236
|
// TODO: Implement server start
|
|
87
237
|
});
|
|
88
|
-
// Index command
|
|
89
|
-
program
|
|
90
|
-
.command('index
|
|
91
|
-
.description('
|
|
92
|
-
.
|
|
93
|
-
.
|
|
94
|
-
console.log(chalk.
|
|
95
|
-
console.log('
|
|
96
|
-
|
|
238
|
+
// Index command
|
|
239
|
+
const indexCmd = program
|
|
240
|
+
.command('index')
|
|
241
|
+
.description('Manage the code index')
|
|
242
|
+
.action(() => {
|
|
243
|
+
console.log(chalk.yellow('Use an index subcommand:'));
|
|
244
|
+
console.log(chalk.gray(' code-audit index sync --path . Sync the index from source files'));
|
|
245
|
+
console.log(chalk.gray(' code-audit index cleanup Remove stale entries for deleted files'));
|
|
246
|
+
console.log(chalk.gray(' code-audit index reset Clear all analysis data'));
|
|
97
247
|
});
|
|
98
|
-
|
|
248
|
+
indexCmd
|
|
249
|
+
.command('sync')
|
|
250
|
+
.description('Synchronize index from source files')
|
|
251
|
+
.option('--path <path>', 'Path to a specific file or directory', process.cwd())
|
|
252
|
+
.option('--json', 'Output as JSON')
|
|
253
|
+
.action(async (options) => {
|
|
254
|
+
try {
|
|
255
|
+
await initParsers();
|
|
256
|
+
const db = CodeIndexDB.getInstance();
|
|
257
|
+
await db.initialize();
|
|
258
|
+
const targetPath = resolve(options.path || process.cwd());
|
|
259
|
+
const isSingleFile = (await fs.stat(targetPath).catch(() => null))?.isFile();
|
|
260
|
+
let result;
|
|
261
|
+
if (isSingleFile) {
|
|
262
|
+
result = await db.synchronizeFile(targetPath);
|
|
263
|
+
result = { mode: 'sync', success: true, path: targetPath, ...(result || { message: 'File not found' }) };
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
const syncResult = await db.deepSync();
|
|
267
|
+
result = {
|
|
268
|
+
mode: 'sync',
|
|
269
|
+
success: true,
|
|
270
|
+
syncedFiles: syncResult.syncedFiles,
|
|
271
|
+
addedFunctions: syncResult.addedFunctions,
|
|
272
|
+
updatedFunctions: syncResult.updatedFunctions,
|
|
273
|
+
removedFunctions: syncResult.removedFunctions,
|
|
274
|
+
errors: syncResult.errors,
|
|
275
|
+
message: `Synced ${syncResult.syncedFiles} files: ${syncResult.addedFunctions} added, ${syncResult.updatedFunctions} updated, ${syncResult.removedFunctions} removed`,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
if (options.json) {
|
|
279
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
console.log(chalk.green(result.success ? '✓ Index sync complete' : '✗ Index sync failed'));
|
|
283
|
+
if (result.message)
|
|
284
|
+
console.log(chalk.gray(result.message));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
console.error(chalk.red('Error:'), error);
|
|
289
|
+
process.exit(1);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
indexCmd
|
|
293
|
+
.command('cleanup')
|
|
294
|
+
.description('Remove index entries for deleted files')
|
|
295
|
+
.option('--json', 'Output as JSON')
|
|
296
|
+
.action(async (options) => {
|
|
297
|
+
try {
|
|
298
|
+
const db = CodeIndexDB.getInstance();
|
|
299
|
+
await db.initialize();
|
|
300
|
+
const result = await db.bulkCleanup();
|
|
301
|
+
if (options.json) {
|
|
302
|
+
process.stdout.write(JSON.stringify({ mode: 'cleanup', success: true, ...result }) + '\n');
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
console.log(chalk.green('✓ Cleanup complete'));
|
|
306
|
+
console.log(chalk.gray(`Removed ${result.removedCount} entries from ${result.removedFiles.length} deleted files`));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
console.error(chalk.red('Error:'), error);
|
|
311
|
+
process.exit(1);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
indexCmd
|
|
315
|
+
.command('reset')
|
|
316
|
+
.description('Clear all analysis data (preserves tasks, config, whitelist)')
|
|
317
|
+
.option('--json', 'Output as JSON')
|
|
318
|
+
.action(async (options) => {
|
|
319
|
+
try {
|
|
320
|
+
const db = CodeIndexDB.getInstance();
|
|
321
|
+
await db.initialize();
|
|
322
|
+
await db.clearIndex();
|
|
323
|
+
if (options.json) {
|
|
324
|
+
process.stdout.write(JSON.stringify({ mode: 'reset', success: true, message: 'All analysis data cleared' }) + '\n');
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
console.log(chalk.green('✓ Index reset complete'));
|
|
328
|
+
console.log(chalk.gray('All analysis-derived data cleared (tasks, config, and whitelist preserved)'));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
console.error(chalk.red('Error:'), error);
|
|
333
|
+
process.exit(1);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
// Config command
|
|
337
|
+
const configCmd = program
|
|
338
|
+
.command('config')
|
|
339
|
+
.description('Manage analyzer configuration and invariant rules')
|
|
340
|
+
.action(() => {
|
|
341
|
+
console.log(chalk.yellow('Use a config subcommand:'));
|
|
342
|
+
console.log(chalk.gray(' code-audit config rules-list List invariant rules from .codeauditor.json'));
|
|
343
|
+
console.log(chalk.gray(' code-audit config rules-check Validate .codeauditor.json rules'));
|
|
344
|
+
});
|
|
345
|
+
configCmd
|
|
346
|
+
.command('rules-list')
|
|
347
|
+
.description('List all configured invariant rules from .codeauditor.json')
|
|
348
|
+
.option('--config-path <path>', 'Path to .codeauditor.json')
|
|
349
|
+
.option('--json', 'Output as JSON')
|
|
350
|
+
.action(async (options) => {
|
|
351
|
+
try {
|
|
352
|
+
const pathModule = await import('path');
|
|
353
|
+
const { readFileSync } = await import('fs');
|
|
354
|
+
const configPath = options.configPath ||
|
|
355
|
+
pathModule.join(process.cwd(), '.codeauditor.json');
|
|
356
|
+
try {
|
|
357
|
+
const raw = readFileSync(configPath, 'utf-8');
|
|
358
|
+
const config = JSON.parse(raw);
|
|
359
|
+
const rules = config?.rules ?? [];
|
|
360
|
+
if (options.json) {
|
|
361
|
+
process.stdout.write(JSON.stringify({
|
|
362
|
+
rules: rules.map((r) => ({ id: r.id, kind: r.kind, severity: r.severity, message: r.message || null })),
|
|
363
|
+
count: rules.length,
|
|
364
|
+
configPath,
|
|
365
|
+
}, null, 2) + '\n');
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
if (rules.length === 0) {
|
|
369
|
+
console.log(chalk.yellow(`No rules found in ${configPath}`));
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
console.log(chalk.blue(`\n${rules.length} rule(s) in ${configPath}`));
|
|
373
|
+
console.log(chalk.gray('──────────────────────────────────────────'));
|
|
374
|
+
for (const r of rules) {
|
|
375
|
+
const sevIcon = r.severity === 'critical' ? '🔴' : r.severity === 'warning' ? '🟡' : '🔵';
|
|
376
|
+
console.log(`${sevIcon} ${chalk.bold(r.id)} [${r.kind}] ${chalk.dim(r.severity)}`);
|
|
377
|
+
if (r.message)
|
|
378
|
+
console.log(` ${r.message}`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
catch (err) {
|
|
384
|
+
console.error(chalk.red(`Failed to read rules: ${err.message}`));
|
|
385
|
+
process.exit(1);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
catch (error) {
|
|
389
|
+
console.error(chalk.red('Error:'), error);
|
|
390
|
+
process.exit(1);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
configCmd
|
|
394
|
+
.command('rules-check')
|
|
395
|
+
.description('Validate the current .codeauditor.json rules')
|
|
396
|
+
.option('--config-path <path>', 'Path to .codeauditor.json')
|
|
397
|
+
.option('--json', 'Output as JSON')
|
|
398
|
+
.action(async (options) => {
|
|
399
|
+
try {
|
|
400
|
+
const pathModule = await import('path');
|
|
401
|
+
const { readFileSync } = await import('fs');
|
|
402
|
+
const { validateRulesConfig } = await import('./invariants/ruleValidator.js');
|
|
403
|
+
const configPath = options.configPath ||
|
|
404
|
+
pathModule.join(process.cwd(), '.codeauditor.json');
|
|
405
|
+
try {
|
|
406
|
+
const raw = readFileSync(configPath, 'utf-8');
|
|
407
|
+
const config = JSON.parse(raw);
|
|
408
|
+
const rulesArray = config?.rules;
|
|
409
|
+
const errors = validateRulesConfig({ rules: rulesArray ?? [] });
|
|
410
|
+
if (options.json) {
|
|
411
|
+
process.stdout.write(JSON.stringify({
|
|
412
|
+
valid: errors.length === 0,
|
|
413
|
+
errors: errors.map(e => ({ ruleId: e.ruleId || null, message: e.message })),
|
|
414
|
+
configPath,
|
|
415
|
+
}, null, 2) + '\n');
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
if (errors.length === 0) {
|
|
419
|
+
console.log(chalk.green(`✓ All rules valid (${configPath})`));
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
console.log(chalk.red(`✗ ${errors.length} validation error(s) in ${configPath}`));
|
|
423
|
+
console.log(chalk.gray('──────────────────────────────────────────'));
|
|
424
|
+
for (const e of errors) {
|
|
425
|
+
const id = e.ruleId ? chalk.bold(e.ruleId) + ': ' : '';
|
|
426
|
+
console.log(` ${id}${chalk.red(e.message)}`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
catch (err) {
|
|
432
|
+
console.error(chalk.red(`Failed to read/parse config: ${err.message}`));
|
|
433
|
+
process.exit(1);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
catch (error) {
|
|
437
|
+
console.error(chalk.red('Error:'), error);
|
|
438
|
+
process.exit(1);
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
// Search command
|
|
99
442
|
program
|
|
100
443
|
.command('search <query>')
|
|
101
|
-
.description('Search the code index')
|
|
102
|
-
.option('-f, --fuzzy', 'Use fuzzy search', true)
|
|
103
|
-
.option('-t, --type <type>', 'Symbol type filter')
|
|
444
|
+
.description('Search the code index with operator syntax: calls:<fn>, dep:<module>, lang:<lang>, complexity:>N, etc.')
|
|
104
445
|
.option('-l, --limit <limit>', 'Result limit', '20')
|
|
446
|
+
.option('--language <lang>', 'Filter by language (typescript, javascript, go)')
|
|
447
|
+
.option('--json', 'Output results as JSON')
|
|
448
|
+
.option('--definition', 'Look up a specific symbol definition by name')
|
|
105
449
|
.action(async (query, options) => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
450
|
+
try {
|
|
451
|
+
await initParsers();
|
|
452
|
+
await runSearch(query, options);
|
|
453
|
+
}
|
|
454
|
+
catch (error) {
|
|
455
|
+
console.error(chalk.red('Error:'), error);
|
|
456
|
+
process.exit(1);
|
|
457
|
+
}
|
|
109
458
|
});
|
|
110
459
|
// Test command (placeholder - will be implemented later)
|
|
111
460
|
program
|
|
@@ -142,6 +491,285 @@ program
|
|
|
142
491
|
process.exit(1);
|
|
143
492
|
}
|
|
144
493
|
});
|
|
494
|
+
// Tasks command — thin adapter over MCP service layer
|
|
495
|
+
const tasksCmd = program
|
|
496
|
+
.command('tasks')
|
|
497
|
+
.description('Manage the per-project task queue')
|
|
498
|
+
.action(() => {
|
|
499
|
+
console.log(chalk.yellow('Use a tasks subcommand: list, create, get, update, complete, delete, from-audit'));
|
|
500
|
+
console.log(chalk.gray(' code-audit tasks list List all tasks'));
|
|
501
|
+
console.log(chalk.gray(' code-audit tasks create --title "Fix SQL injection"'));
|
|
502
|
+
console.log(chalk.gray(' code-audit tasks get <taskId> Get task details'));
|
|
503
|
+
console.log(chalk.gray(' code-audit tasks update <taskId> --status in_progress'));
|
|
504
|
+
console.log(chalk.gray(' code-audit tasks complete <taskId> Mark task done'));
|
|
505
|
+
console.log(chalk.gray(' code-audit tasks delete <taskId> Delete a task'));
|
|
506
|
+
console.log(chalk.gray(' code-audit tasks from-audit Create tasks from audit violations'));
|
|
507
|
+
});
|
|
508
|
+
tasksCmd
|
|
509
|
+
.command('list')
|
|
510
|
+
.description('List project tasks')
|
|
511
|
+
.option('--status <status>', 'Filter by status (open, in_progress, completed)')
|
|
512
|
+
.option('--source <source>', 'Filter by source (manual, audit)')
|
|
513
|
+
.option('--priority <priority>', 'Filter by priority (low, medium, high)')
|
|
514
|
+
.option('--label <label>', 'Filter by label')
|
|
515
|
+
.option('--limit <limit>', 'Result limit', '50')
|
|
516
|
+
.option('--json', 'Output as JSON')
|
|
517
|
+
.action(async (options) => {
|
|
518
|
+
try {
|
|
519
|
+
const args = { action: 'list' };
|
|
520
|
+
if (options.status)
|
|
521
|
+
args.status = options.status;
|
|
522
|
+
if (options.source)
|
|
523
|
+
args.source = options.source;
|
|
524
|
+
if (options.priority)
|
|
525
|
+
args.priority = options.priority;
|
|
526
|
+
if (options.label)
|
|
527
|
+
args.label = options.label;
|
|
528
|
+
if (options.limit)
|
|
529
|
+
args.limit = parseInt(options.limit, 10);
|
|
530
|
+
const { handleProjectTasks } = await import('./mcp-tools/projectTasks.js');
|
|
531
|
+
const result = await handleProjectTasks(args);
|
|
532
|
+
if (options.json) {
|
|
533
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
534
|
+
}
|
|
535
|
+
else if (result.success) {
|
|
536
|
+
const tasks = result.tasks || [];
|
|
537
|
+
if (tasks.length === 0) {
|
|
538
|
+
console.log(chalk.yellow('No tasks found.'));
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
for (const t of tasks) {
|
|
542
|
+
const icon = t.status === 'completed' ? '✅' : t.status === 'in_progress' ? '🔄' : '📋';
|
|
543
|
+
const priority = t.priority ? chalk.dim(` [${t.priority}]`) : '';
|
|
544
|
+
console.log(`${icon} ${chalk.bold(t.title ?? t.id)}${priority}`);
|
|
545
|
+
if (t.description)
|
|
546
|
+
console.log(chalk.dim(` ${t.description}`));
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
console.error(chalk.red(result.error || 'Unknown error'));
|
|
552
|
+
process.exit(1);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
catch (error) {
|
|
556
|
+
console.error(chalk.red('Error:'), error);
|
|
557
|
+
process.exit(1);
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
tasksCmd
|
|
561
|
+
.command('create')
|
|
562
|
+
.description('Create a project task')
|
|
563
|
+
.requiredOption('--title <title>', 'Task title')
|
|
564
|
+
.option('--description <description>', 'Task description')
|
|
565
|
+
.option('--priority <priority>', 'Priority (low, medium, high)')
|
|
566
|
+
.option('--status <status>', 'Status (open, in_progress)')
|
|
567
|
+
.option('--labels <labels>', 'Comma-separated labels')
|
|
568
|
+
.option('--json', 'Output as JSON')
|
|
569
|
+
.action(async (options) => {
|
|
570
|
+
try {
|
|
571
|
+
const args = {
|
|
572
|
+
action: 'create',
|
|
573
|
+
title: options.title,
|
|
574
|
+
};
|
|
575
|
+
if (options.description)
|
|
576
|
+
args.description = options.description;
|
|
577
|
+
if (options.priority)
|
|
578
|
+
args.priority = options.priority;
|
|
579
|
+
if (options.status)
|
|
580
|
+
args.status = options.status;
|
|
581
|
+
if (options.labels)
|
|
582
|
+
args.labels = options.labels.split(',').map((s) => s.trim());
|
|
583
|
+
const { handleProjectTasks } = await import('./mcp-tools/projectTasks.js');
|
|
584
|
+
const result = await handleProjectTasks(args);
|
|
585
|
+
if (options.json) {
|
|
586
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
587
|
+
}
|
|
588
|
+
else if (result.success) {
|
|
589
|
+
const task = result.task || {};
|
|
590
|
+
console.log(chalk.green(`✓ Task created: ${task.title || task.taskId || 'unknown'}`));
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
console.error(chalk.red(result.error || 'Unknown error'));
|
|
594
|
+
process.exit(1);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
catch (error) {
|
|
598
|
+
console.error(chalk.red('Error:'), error);
|
|
599
|
+
process.exit(1);
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
tasksCmd
|
|
603
|
+
.command('get <taskId>')
|
|
604
|
+
.description('Get a task by ID')
|
|
605
|
+
.option('--json', 'Output as JSON')
|
|
606
|
+
.action(async (taskId, options) => {
|
|
607
|
+
try {
|
|
608
|
+
const { handleProjectTasks } = await import('./mcp-tools/projectTasks.js');
|
|
609
|
+
const result = await handleProjectTasks({ action: 'get', taskId });
|
|
610
|
+
if (options.json) {
|
|
611
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
612
|
+
}
|
|
613
|
+
else if (result.success) {
|
|
614
|
+
const t = result.task;
|
|
615
|
+
console.log(chalk.blue(`\nTask: ${t.title}`));
|
|
616
|
+
console.log(chalk.gray('──────────────────────────────────────────'));
|
|
617
|
+
console.log(`${chalk.bold('ID:')} ${t.id}`);
|
|
618
|
+
console.log(`${chalk.bold('Status:')} ${t.status}`);
|
|
619
|
+
if (t.priority)
|
|
620
|
+
console.log(`${chalk.bold('Priority:')} ${t.priority}`);
|
|
621
|
+
if (t.description)
|
|
622
|
+
console.log(`${chalk.bold('Description:')}\n${t.description}`);
|
|
623
|
+
if (t.labels?.length)
|
|
624
|
+
console.log(`${chalk.bold('Labels:')} ${t.labels.join(', ')}`);
|
|
625
|
+
if (t.relatedFiles?.length)
|
|
626
|
+
console.log(`${chalk.bold('Files:')} ${t.relatedFiles.join(', ')}`);
|
|
627
|
+
if (t.fingerprint)
|
|
628
|
+
console.log(chalk.dim(`\nfingerprint: ${t.fingerprint}`));
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
console.error(chalk.red(result.error || 'Unknown error'));
|
|
632
|
+
process.exit(1);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
catch (error) {
|
|
636
|
+
console.error(chalk.red('Error:'), error);
|
|
637
|
+
process.exit(1);
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
tasksCmd
|
|
641
|
+
.command('update <taskId>')
|
|
642
|
+
.description('Update a task')
|
|
643
|
+
.option('--title <title>', 'New title')
|
|
644
|
+
.option('--description <description>', 'New description')
|
|
645
|
+
.option('--status <status>', 'New status (open, in_progress, completed)')
|
|
646
|
+
.option('--priority <priority>', 'New priority (low, medium, high)')
|
|
647
|
+
.option('--labels <labels>', 'Comma-separated labels')
|
|
648
|
+
.option('--json', 'Output as JSON')
|
|
649
|
+
.action(async (taskId, options) => {
|
|
650
|
+
try {
|
|
651
|
+
const patch = {};
|
|
652
|
+
if (options.title)
|
|
653
|
+
patch.title = options.title;
|
|
654
|
+
if (options.description)
|
|
655
|
+
patch.description = options.description;
|
|
656
|
+
if (options.status)
|
|
657
|
+
patch.status = options.status;
|
|
658
|
+
if (options.priority)
|
|
659
|
+
patch.priority = options.priority;
|
|
660
|
+
if (options.labels)
|
|
661
|
+
patch.labels = options.labels.split(',').map((s) => s.trim());
|
|
662
|
+
if (Object.keys(patch).length === 0) {
|
|
663
|
+
console.error(chalk.yellow('No update fields provided. Use --title, --description, --status, --priority, or --labels.'));
|
|
664
|
+
process.exit(1);
|
|
665
|
+
}
|
|
666
|
+
const { handleProjectTasks } = await import('./mcp-tools/projectTasks.js');
|
|
667
|
+
const result = await handleProjectTasks({ action: 'update', taskId, patch });
|
|
668
|
+
if (options.json) {
|
|
669
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
670
|
+
}
|
|
671
|
+
else if (result.success) {
|
|
672
|
+
console.log(chalk.green(`✓ Task updated`));
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
console.error(chalk.red(result.error || 'Unknown error'));
|
|
676
|
+
process.exit(1);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
catch (error) {
|
|
680
|
+
console.error(chalk.red('Error:'), error);
|
|
681
|
+
process.exit(1);
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
tasksCmd
|
|
685
|
+
.command('complete <taskId>')
|
|
686
|
+
.description('Mark a task as completed')
|
|
687
|
+
.option('--json', 'Output as JSON')
|
|
688
|
+
.action(async (taskId, options) => {
|
|
689
|
+
try {
|
|
690
|
+
const { handleProjectTasks } = await import('./mcp-tools/projectTasks.js');
|
|
691
|
+
const result = await handleProjectTasks({ action: 'complete_task', taskId });
|
|
692
|
+
if (options.json) {
|
|
693
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
694
|
+
}
|
|
695
|
+
else if (result.success) {
|
|
696
|
+
console.log(chalk.green(`✓ Task completed`));
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
console.error(chalk.red(result.error || 'Unknown error'));
|
|
700
|
+
process.exit(1);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
catch (error) {
|
|
704
|
+
console.error(chalk.red('Error:'), error);
|
|
705
|
+
process.exit(1);
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
tasksCmd
|
|
709
|
+
.command('delete <taskId>')
|
|
710
|
+
.description('Delete a task')
|
|
711
|
+
.option('--json', 'Output as JSON')
|
|
712
|
+
.action(async (taskId, options) => {
|
|
713
|
+
try {
|
|
714
|
+
const { handleProjectTasks } = await import('./mcp-tools/projectTasks.js');
|
|
715
|
+
const result = await handleProjectTasks({ action: 'delete', taskId });
|
|
716
|
+
if (options.json) {
|
|
717
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
718
|
+
}
|
|
719
|
+
else if (result.success) {
|
|
720
|
+
console.log(chalk.green(`✓ Task deleted`));
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
console.error(chalk.red(result.error || 'Unknown error'));
|
|
724
|
+
process.exit(1);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
catch (error) {
|
|
728
|
+
console.error(chalk.red('Error:'), error);
|
|
729
|
+
process.exit(1);
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
tasksCmd
|
|
733
|
+
.command('from-audit')
|
|
734
|
+
.description('Populate tasks from audit violations')
|
|
735
|
+
.option('--auditJobId <id>', 'Specific audit result ID')
|
|
736
|
+
.option('--severities <severities>', 'Comma-separated severities (critical,warning,suggestion)', 'critical,warning')
|
|
737
|
+
.option('--json', 'Output as JSON')
|
|
738
|
+
.action(async (options) => {
|
|
739
|
+
try {
|
|
740
|
+
const args = { action: 'from_audit' };
|
|
741
|
+
if (options.auditJobId)
|
|
742
|
+
args.auditJobId = options.auditJobId;
|
|
743
|
+
if (options.severities)
|
|
744
|
+
args.severities = options.severities.split(',').map((s) => s.trim());
|
|
745
|
+
const { handleProjectTasks } = await import('./mcp-tools/projectTasks.js');
|
|
746
|
+
const result = await handleProjectTasks(args);
|
|
747
|
+
if (options.json) {
|
|
748
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
749
|
+
}
|
|
750
|
+
else if (result.success) {
|
|
751
|
+
const r = result;
|
|
752
|
+
console.log(chalk.green(`✓ Created ${r.created || 0} task(s), skipped ${r.skipped || 0} (duplicates)`));
|
|
753
|
+
if (r.tasks?.length) {
|
|
754
|
+
for (const t of r.tasks) {
|
|
755
|
+
console.log(` 📋 ${chalk.bold(t.title)}`);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
else if (result.error === 'No audit results found. Run an audit first, or provide an auditJobId.') {
|
|
760
|
+
// Not a real error — just nothing to convert. Exit 0 so scripts don't break.
|
|
761
|
+
console.log(chalk.yellow(result.error));
|
|
762
|
+
}
|
|
763
|
+
else {
|
|
764
|
+
console.error(chalk.red(result.error || 'Unknown error'));
|
|
765
|
+
process.exit(1);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
catch (error) {
|
|
769
|
+
console.error(chalk.red('Error:'), error);
|
|
770
|
+
process.exit(1);
|
|
771
|
+
}
|
|
772
|
+
});
|
|
145
773
|
// Parse command line arguments
|
|
146
774
|
program.parse(process.argv);
|
|
147
775
|
// If no command was provided, show help
|
|
@@ -335,7 +963,8 @@ async function generateCodeMap(options) {
|
|
|
335
963
|
console.log(chalk.gray(` • Functions found: ${codeMap.stats.totalFunctions}`));
|
|
336
964
|
console.log(chalk.gray(` • Components found: ${codeMap.stats.totalComponents}`));
|
|
337
965
|
if (documentation) {
|
|
338
|
-
|
|
966
|
+
const docMetrics = documentation;
|
|
967
|
+
console.log(chalk.gray(` • Documentation coverage: ${docMetrics.coverageScore}%`));
|
|
339
968
|
}
|
|
340
969
|
}
|
|
341
970
|
else {
|
|
@@ -357,4 +986,97 @@ async function generateCodeMap(options) {
|
|
|
357
986
|
}
|
|
358
987
|
}
|
|
359
988
|
}
|
|
989
|
+
/**
|
|
990
|
+
* Run a search query against the code index.
|
|
991
|
+
*/
|
|
992
|
+
async function runSearch(query, options) {
|
|
993
|
+
const limit = parseInt(options.limit || '20', 10);
|
|
994
|
+
const db = CodeIndexDB.getInstance();
|
|
995
|
+
await db.initialize();
|
|
996
|
+
// --definition: look up a specific symbol
|
|
997
|
+
if (options.definition) {
|
|
998
|
+
const func = await db.findDefinition(query);
|
|
999
|
+
if (!func) {
|
|
1000
|
+
console.log(chalk.yellow(`No definition found for "${query}"`));
|
|
1001
|
+
return;
|
|
1002
|
+
}
|
|
1003
|
+
if (options.json) {
|
|
1004
|
+
process.stdout.write(JSON.stringify(func, null, 2) + '\n');
|
|
1005
|
+
}
|
|
1006
|
+
else {
|
|
1007
|
+
console.log(chalk.blue(`\nDefinition: ${func.name}`));
|
|
1008
|
+
console.log(chalk.gray('──────────────────────────────────────────'));
|
|
1009
|
+
console.log(`${chalk.bold('File:')} ${func.filePath}${func.lineNumber ? `:${func.lineNumber}` : ''}`);
|
|
1010
|
+
if (func.signature) {
|
|
1011
|
+
console.log(`${chalk.bold('Signature:')} ${func.signature}`);
|
|
1012
|
+
}
|
|
1013
|
+
if (func.purpose) {
|
|
1014
|
+
console.log(`${chalk.bold('Purpose:')} ${func.purpose}`);
|
|
1015
|
+
}
|
|
1016
|
+
if (func.language) {
|
|
1017
|
+
console.log(`${chalk.bold('Language:')} ${func.language}`);
|
|
1018
|
+
}
|
|
1019
|
+
if (func.dependencies?.length) {
|
|
1020
|
+
console.log(`${chalk.bold('Dependencies:')} ${func.dependencies.join(', ')}`);
|
|
1021
|
+
}
|
|
1022
|
+
if (func.jsDoc) {
|
|
1023
|
+
console.log(`${chalk.bold('JSDoc:')} ${func.jsDoc}`);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
// Full search: parse the query, build SearchOptions, run search
|
|
1029
|
+
const parsed = queryParser.parse(query);
|
|
1030
|
+
const searchOptions = {
|
|
1031
|
+
query,
|
|
1032
|
+
parsedQuery: parsed,
|
|
1033
|
+
limit,
|
|
1034
|
+
offset: 0,
|
|
1035
|
+
searchStrategy: parsed.fuzzy ? 'fuzzy' : 'exact',
|
|
1036
|
+
};
|
|
1037
|
+
// Apply --language filter
|
|
1038
|
+
if (options.language) {
|
|
1039
|
+
if (!searchOptions.filters) {
|
|
1040
|
+
searchOptions.filters = {};
|
|
1041
|
+
}
|
|
1042
|
+
searchOptions.filters.language = options.language;
|
|
1043
|
+
}
|
|
1044
|
+
const result = await db.searchFunctions(searchOptions);
|
|
1045
|
+
if (options.json) {
|
|
1046
|
+
process.stdout.write(JSON.stringify({
|
|
1047
|
+
query,
|
|
1048
|
+
totalCount: result.totalCount,
|
|
1049
|
+
executionTime: result.executionTime,
|
|
1050
|
+
functions: result.functions,
|
|
1051
|
+
}, null, 2) + '\n');
|
|
1052
|
+
}
|
|
1053
|
+
else {
|
|
1054
|
+
console.log(chalk.blue(`\nSearch: "${query}"`));
|
|
1055
|
+
console.log(chalk.gray('──────────────────────────────────────────'));
|
|
1056
|
+
console.log(chalk.gray(`Found ${result.totalCount} result${result.totalCount !== 1 ? 's' : ''} in ${result.executionTime}ms`));
|
|
1057
|
+
console.log('');
|
|
1058
|
+
if (result.functions.length === 0) {
|
|
1059
|
+
console.log(chalk.yellow('No results found.'));
|
|
1060
|
+
console.log(chalk.gray('Tip: Run an audit first if the index is empty: code-audit audit'));
|
|
1061
|
+
}
|
|
1062
|
+
else {
|
|
1063
|
+
for (const func of result.functions) {
|
|
1064
|
+
const lang = func.language ? chalk.dim(` [${func.language}]`) : '';
|
|
1065
|
+
const lineInfo = func.lineNumber ? chalk.dim(`:${func.lineNumber}`) : '';
|
|
1066
|
+
console.log(`${chalk.bold(func.name)}${lang} — ${chalk.green(func.filePath)}${lineInfo}`);
|
|
1067
|
+
if (func.signature) {
|
|
1068
|
+
console.log(chalk.dim(` ${func.signature}`));
|
|
1069
|
+
}
|
|
1070
|
+
if (func.purpose) {
|
|
1071
|
+
console.log(chalk.dim(` ${func.purpose}`));
|
|
1072
|
+
}
|
|
1073
|
+
// Show score for relevance-sorted results
|
|
1074
|
+
if (func.score) {
|
|
1075
|
+
console.log(chalk.dim(` score: ${func.score.toFixed(2)}`));
|
|
1076
|
+
}
|
|
1077
|
+
console.log('');
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
360
1082
|
//# sourceMappingURL=cli.js.map
|