mcp-adr-analysis-server 2.0.2 → 2.0.5
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/dist/src/index.d.ts +26 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +535 -323
- package/dist/src/index.js.map +1 -1
- package/dist/src/prompts/adr-suggestion-prompts.d.ts +1 -0
- package/dist/src/prompts/adr-suggestion-prompts.d.ts.map +1 -1
- package/dist/src/prompts/adr-suggestion-prompts.js +42 -34
- package/dist/src/prompts/adr-suggestion-prompts.js.map +1 -1
- package/dist/src/prompts/analysis-prompts.js +7 -7
- package/dist/src/prompts/deployment-analysis-prompts.js +5 -5
- package/dist/src/prompts/environment-analysis-prompts.js +7 -7
- package/dist/src/prompts/index.d.ts.map +1 -1
- package/dist/src/prompts/index.js +7 -5
- package/dist/src/prompts/index.js.map +1 -1
- package/dist/src/prompts/research-integration-prompts.js +7 -7
- package/dist/src/prompts/research-question-prompts.js +7 -7
- package/dist/src/prompts/rule-generation-prompts.d.ts.map +1 -1
- package/dist/src/prompts/rule-generation-prompts.js +8 -6
- package/dist/src/prompts/rule-generation-prompts.js.map +1 -1
- package/dist/src/prompts/security-prompts.js +6 -6
- package/dist/src/resources/index.d.ts.map +1 -1
- package/dist/src/resources/index.js +31 -15
- package/dist/src/resources/index.js.map +1 -1
- package/dist/src/tools/adr-suggestion-tool.d.ts +4 -1
- package/dist/src/tools/adr-suggestion-tool.d.ts.map +1 -1
- package/dist/src/tools/adr-suggestion-tool.js +72 -114
- package/dist/src/tools/adr-suggestion-tool.js.map +1 -1
- package/dist/src/tools/content-masking-tool.d.ts +7 -0
- package/dist/src/tools/content-masking-tool.d.ts.map +1 -1
- package/dist/src/tools/content-masking-tool.js +134 -17
- package/dist/src/tools/content-masking-tool.js.map +1 -1
- package/dist/src/tools/environment-analysis-tool.d.ts +4 -0
- package/dist/src/tools/environment-analysis-tool.d.ts.map +1 -1
- package/dist/src/tools/environment-analysis-tool.js +209 -25
- package/dist/src/tools/environment-analysis-tool.js.map +1 -1
- package/dist/src/tools/research-question-tool.d.ts +4 -0
- package/dist/src/tools/research-question-tool.d.ts.map +1 -1
- package/dist/src/tools/research-question-tool.js +42 -4
- package/dist/src/tools/research-question-tool.js.map +1 -1
- package/dist/src/tools/rule-generation-tool.d.ts +4 -0
- package/dist/src/tools/rule-generation-tool.d.ts.map +1 -1
- package/dist/src/tools/rule-generation-tool.js +136 -16
- package/dist/src/tools/rule-generation-tool.js.map +1 -1
- package/dist/src/types/conversation-context.d.ts +93 -0
- package/dist/src/types/conversation-context.d.ts.map +1 -0
- package/dist/src/types/conversation-context.js +101 -0
- package/dist/src/types/conversation-context.js.map +1 -0
- package/dist/src/utils/actual-file-operations.d.ts +40 -0
- package/dist/src/utils/actual-file-operations.d.ts.map +1 -0
- package/dist/src/utils/actual-file-operations.js +309 -0
- package/dist/src/utils/actual-file-operations.js.map +1 -0
- package/dist/src/utils/adr-discovery.d.ts +36 -0
- package/dist/src/utils/adr-discovery.d.ts.map +1 -0
- package/dist/src/utils/adr-discovery.js +237 -0
- package/dist/src/utils/adr-discovery.js.map +1 -0
- package/dist/src/utils/adr-suggestions.d.ts +2 -1
- package/dist/src/utils/adr-suggestions.d.ts.map +1 -1
- package/dist/src/utils/adr-suggestions.js +8 -2
- package/dist/src/utils/adr-suggestions.js.map +1 -1
- package/dist/src/utils/apply-cot-enhancement.d.ts +46 -0
- package/dist/src/utils/apply-cot-enhancement.d.ts.map +1 -0
- package/dist/src/utils/apply-cot-enhancement.js +165 -0
- package/dist/src/utils/apply-cot-enhancement.js.map +1 -0
- package/dist/src/utils/chain-of-thought-template.d.ts +48 -0
- package/dist/src/utils/chain-of-thought-template.d.ts.map +1 -0
- package/dist/src/utils/chain-of-thought-template.js +191 -0
- package/dist/src/utils/chain-of-thought-template.js.map +1 -0
- package/dist/src/utils/deployment-analysis.d.ts +1 -0
- package/dist/src/utils/deployment-analysis.d.ts.map +1 -1
- package/dist/src/utils/deployment-analysis.js +82 -39
- package/dist/src/utils/deployment-analysis.js.map +1 -1
- package/dist/src/utils/environment-analysis.d.ts +6 -1
- package/dist/src/utils/environment-analysis.d.ts.map +1 -1
- package/dist/src/utils/environment-analysis.js +176 -87
- package/dist/src/utils/environment-analysis.js.map +1 -1
- package/dist/src/utils/file-system.d.ts +1 -0
- package/dist/src/utils/file-system.d.ts.map +1 -1
- package/dist/src/utils/file-system.js +24 -47
- package/dist/src/utils/file-system.js.map +1 -1
- package/dist/src/utils/prompt-execution.d.ts.map +1 -1
- package/dist/src/utils/prompt-execution.js +67 -3
- package/dist/src/utils/prompt-execution.js.map +1 -1
- package/dist/src/utils/research-integration.d.ts +4 -0
- package/dist/src/utils/research-integration.d.ts.map +1 -1
- package/dist/src/utils/research-integration.js +275 -84
- package/dist/src/utils/research-integration.js.map +1 -1
- package/dist/src/utils/research-questions.d.ts.map +1 -1
- package/dist/src/utils/research-questions.js +134 -38
- package/dist/src/utils/research-questions.js.map +1 -1
- package/dist/src/utils/rule-generation.d.ts +2 -1
- package/dist/src/utils/rule-generation.d.ts.map +1 -1
- package/dist/src/utils/rule-generation.js +65 -36
- package/dist/src/utils/rule-generation.js.map +1 -1
- package/package.json +4 -4
package/dist/src/index.js
CHANGED
|
@@ -9,15 +9,61 @@
|
|
|
9
9
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
10
10
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
11
11
|
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
12
|
+
import { readFileSync } from 'fs';
|
|
13
|
+
import { fileURLToPath } from 'url';
|
|
14
|
+
import { dirname, join } from 'path';
|
|
12
15
|
import { McpAdrError } from './types/index.js';
|
|
16
|
+
import { CONVERSATION_CONTEXT_SCHEMA } from './types/conversation-context.js';
|
|
13
17
|
import { maskMcpResponse, createMaskingConfig } from './utils/output-masking.js';
|
|
14
18
|
import { loadConfig, validateProjectPath, createLogger, printConfigSummary } from './utils/config.js';
|
|
19
|
+
/**
|
|
20
|
+
* Get version from package.json
|
|
21
|
+
*/
|
|
22
|
+
function getPackageVersion() {
|
|
23
|
+
try {
|
|
24
|
+
// Handle both Jest environment and normal execution
|
|
25
|
+
let currentDir;
|
|
26
|
+
if (typeof import.meta !== 'undefined' && import.meta.url) {
|
|
27
|
+
// Normal ESM execution
|
|
28
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
29
|
+
currentDir = dirname(__filename);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// Jest or other environments without import.meta support
|
|
33
|
+
// Use process.cwd() as fallback
|
|
34
|
+
currentDir = process.cwd();
|
|
35
|
+
}
|
|
36
|
+
// Try multiple possible locations for package.json
|
|
37
|
+
const possiblePaths = [
|
|
38
|
+
join(currentDir, 'package.json'),
|
|
39
|
+
join(currentDir, '..', 'package.json'),
|
|
40
|
+
join(currentDir, '..', '..', 'package.json'),
|
|
41
|
+
join(process.cwd(), 'package.json')
|
|
42
|
+
];
|
|
43
|
+
for (const packageJsonPath of possiblePaths) {
|
|
44
|
+
try {
|
|
45
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
46
|
+
if (packageJson.name === 'mcp-adr-analysis-server') {
|
|
47
|
+
return packageJson.version;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Try next path
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return '2.0.2'; // fallback version
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
console.error('Error reading package.json:', error);
|
|
58
|
+
return '2.0.2'; // fallback version
|
|
59
|
+
}
|
|
60
|
+
}
|
|
15
61
|
/**
|
|
16
62
|
* Server configuration
|
|
17
63
|
*/
|
|
18
64
|
const SERVER_INFO = {
|
|
19
65
|
name: 'mcp-adr-analysis-server',
|
|
20
|
-
version:
|
|
66
|
+
version: getPackageVersion(),
|
|
21
67
|
description: 'MCP server for analyzing Architectural Decision Records and project architecture'
|
|
22
68
|
};
|
|
23
69
|
/**
|
|
@@ -129,7 +175,8 @@ export class McpAdrAnalysisServer {
|
|
|
129
175
|
type: 'array',
|
|
130
176
|
items: { type: 'string' },
|
|
131
177
|
description: 'Specific analysis areas to focus on (e.g., ["security", "performance", "architecture", "dependencies"])'
|
|
132
|
-
}
|
|
178
|
+
},
|
|
179
|
+
conversationContext: CONVERSATION_CONTEXT_SCHEMA
|
|
133
180
|
},
|
|
134
181
|
required: []
|
|
135
182
|
}
|
|
@@ -504,7 +551,8 @@ export class McpAdrAnalysisServer {
|
|
|
504
551
|
type: 'boolean',
|
|
505
552
|
description: 'Enable Knowledge Generation for domain-specific insights',
|
|
506
553
|
default: true
|
|
507
|
-
}
|
|
554
|
+
},
|
|
555
|
+
conversationContext: CONVERSATION_CONTEXT_SCHEMA
|
|
508
556
|
}
|
|
509
557
|
}
|
|
510
558
|
},
|
|
@@ -1138,6 +1186,52 @@ export class McpAdrAnalysisServer {
|
|
|
1138
1186
|
},
|
|
1139
1187
|
required: ['developmentPhase']
|
|
1140
1188
|
}
|
|
1189
|
+
},
|
|
1190
|
+
{
|
|
1191
|
+
name: 'read_file',
|
|
1192
|
+
description: 'Read contents of a file',
|
|
1193
|
+
inputSchema: {
|
|
1194
|
+
type: 'object',
|
|
1195
|
+
properties: {
|
|
1196
|
+
path: {
|
|
1197
|
+
type: 'string',
|
|
1198
|
+
description: 'Path to the file to read'
|
|
1199
|
+
}
|
|
1200
|
+
},
|
|
1201
|
+
required: ['path']
|
|
1202
|
+
}
|
|
1203
|
+
},
|
|
1204
|
+
{
|
|
1205
|
+
name: 'write_file',
|
|
1206
|
+
description: 'Write content to a file',
|
|
1207
|
+
inputSchema: {
|
|
1208
|
+
type: 'object',
|
|
1209
|
+
properties: {
|
|
1210
|
+
path: {
|
|
1211
|
+
type: 'string',
|
|
1212
|
+
description: 'Path to the file to write'
|
|
1213
|
+
},
|
|
1214
|
+
content: {
|
|
1215
|
+
type: 'string',
|
|
1216
|
+
description: 'Content to write to the file'
|
|
1217
|
+
}
|
|
1218
|
+
},
|
|
1219
|
+
required: ['path', 'content']
|
|
1220
|
+
}
|
|
1221
|
+
},
|
|
1222
|
+
{
|
|
1223
|
+
name: 'list_directory',
|
|
1224
|
+
description: 'List contents of a directory',
|
|
1225
|
+
inputSchema: {
|
|
1226
|
+
type: 'object',
|
|
1227
|
+
properties: {
|
|
1228
|
+
path: {
|
|
1229
|
+
type: 'string',
|
|
1230
|
+
description: 'Path to the directory to list'
|
|
1231
|
+
}
|
|
1232
|
+
},
|
|
1233
|
+
required: ['path']
|
|
1234
|
+
}
|
|
1141
1235
|
}
|
|
1142
1236
|
]
|
|
1143
1237
|
};
|
|
@@ -1229,6 +1323,15 @@ export class McpAdrAnalysisServer {
|
|
|
1229
1323
|
case 'get_development_guidance':
|
|
1230
1324
|
response = await this.getDevelopmentGuidance(args);
|
|
1231
1325
|
break;
|
|
1326
|
+
case 'read_file':
|
|
1327
|
+
response = await this.readFile(args);
|
|
1328
|
+
break;
|
|
1329
|
+
case 'write_file':
|
|
1330
|
+
response = await this.writeFile(args);
|
|
1331
|
+
break;
|
|
1332
|
+
case 'list_directory':
|
|
1333
|
+
response = await this.listDirectory(args);
|
|
1334
|
+
break;
|
|
1232
1335
|
default:
|
|
1233
1336
|
throw new McpAdrError(`Unknown tool: ${name}`, 'UNKNOWN_TOOL');
|
|
1234
1337
|
}
|
|
@@ -1614,22 +1717,31 @@ This guidance is tailored to your specific context and goals for maximum effecti
|
|
|
1614
1717
|
async getDevelopmentGuidance(args) {
|
|
1615
1718
|
const { developmentPhase, adrsToImplement = [], technologyStack = [], currentProgress = '', teamContext = { size: 'small_team', experienceLevel: 'mixed' }, timeline = '', focusAreas = [] } = args;
|
|
1616
1719
|
try {
|
|
1617
|
-
//
|
|
1618
|
-
const { findFiles } = await import('./utils/file-system.js');
|
|
1720
|
+
// Use actual ADR discovery if ADRs are specified
|
|
1619
1721
|
let adrAnalysisPrompt = '';
|
|
1620
1722
|
if (adrsToImplement.length > 0) {
|
|
1621
1723
|
const { getAdrDirectoryPath } = await import('./utils/config.js');
|
|
1724
|
+
const { discoverAdrsInDirectory } = await import('./utils/adr-discovery.js');
|
|
1622
1725
|
const absoluteAdrPath = getAdrDirectoryPath(this.config);
|
|
1623
|
-
const
|
|
1624
|
-
|
|
1625
|
-
|
|
1726
|
+
const discoveryResult = await discoverAdrsInDirectory(absoluteAdrPath, true, this.config.projectPath);
|
|
1727
|
+
// Filter ADRs to only those specified for implementation
|
|
1728
|
+
const targetAdrs = discoveryResult.adrs.filter(adr => adrsToImplement.some((target) => adr.title.toLowerCase().includes(target.toLowerCase()) ||
|
|
1729
|
+
adr.filename.toLowerCase().includes(target.toLowerCase())));
|
|
1626
1730
|
adrAnalysisPrompt = `
|
|
1627
1731
|
## ADR Analysis for Implementation
|
|
1628
1732
|
|
|
1629
|
-
${adrFileDiscovery.prompt}
|
|
1630
|
-
|
|
1631
1733
|
**ADRs to Implement**: ${adrsToImplement.join(', ')}
|
|
1632
1734
|
**ADR Directory**: ${absoluteAdrPath}
|
|
1735
|
+
**Found ${targetAdrs.length} matching ADRs**
|
|
1736
|
+
|
|
1737
|
+
${targetAdrs.map(adr => `
|
|
1738
|
+
### ${adr.title}
|
|
1739
|
+
- **File**: ${adr.filename}
|
|
1740
|
+
- **Status**: ${adr.status}
|
|
1741
|
+
- **Context**: ${adr.context}
|
|
1742
|
+
- **Decision**: ${adr.decision}
|
|
1743
|
+
- **Consequences**: ${adr.consequences}
|
|
1744
|
+
`).join('\n')}
|
|
1633
1745
|
`;
|
|
1634
1746
|
}
|
|
1635
1747
|
const developmentPrompt = `
|
|
@@ -1838,7 +1950,9 @@ This guidance ensures your development work is **architecturally aligned**, **qu
|
|
|
1838
1950
|
async analyzeProjectEcosystem(args) {
|
|
1839
1951
|
// Use configured project path if not provided in args
|
|
1840
1952
|
const projectPath = args.projectPath || this.config.projectPath;
|
|
1841
|
-
const { includePatterns, enhancedMode = true, knowledgeEnhancement = true, learningEnabled = true, technologyFocus = [], analysisDepth = 'comprehensive', includeEnvironment = true, recursiveDepth = 'comprehensive', analysisScope = []
|
|
1953
|
+
const { includePatterns, enhancedMode = true, knowledgeEnhancement = true, learningEnabled = true, technologyFocus = [], analysisDepth = 'comprehensive', includeEnvironment = true, recursiveDepth = 'comprehensive', analysisScope = []
|
|
1954
|
+
// conversationContext - TODO: implement context integration for ecosystem analysis
|
|
1955
|
+
} = args;
|
|
1842
1956
|
this.logger.info(`Generating comprehensive ecosystem analysis for project at: ${projectPath}`);
|
|
1843
1957
|
this.logger.info(`Analysis configuration - Depth: ${analysisDepth}, Recursive: ${recursiveDepth}, Environment: ${includeEnvironment}`);
|
|
1844
1958
|
this.logger.info(`Enhancement features - Knowledge: ${knowledgeEnhancement}, Learning: ${learningEnabled}`);
|
|
@@ -2635,24 +2749,34 @@ The enhanced process maintains full traceability from PRD requirements to genera
|
|
|
2635
2749
|
const adrDirectory = args.adrDirectory || this.config.adrDirectory;
|
|
2636
2750
|
this.logger.info(`Generating TDD-focused todo for ADRs in: ${absoluteAdrPath} (phase: ${phase})`);
|
|
2637
2751
|
try {
|
|
2638
|
-
const {
|
|
2639
|
-
|
|
2640
|
-
|
|
2752
|
+
const { discoverAdrsInDirectory } = await import('./utils/adr-discovery.js');
|
|
2753
|
+
const { scanProjectStructure } = await import('./utils/actual-file-operations.js');
|
|
2754
|
+
// Use actual ADR discovery
|
|
2755
|
+
const discoveryResult = await discoverAdrsInDirectory(absoluteAdrPath, true, this.config.projectPath);
|
|
2756
|
+
let adrContent = `Found ${discoveryResult.adrs.length} ADRs in ${absoluteAdrPath}:\n\n`;
|
|
2757
|
+
discoveryResult.adrs.forEach(adr => {
|
|
2758
|
+
adrContent += `### ${adr.title}\n`;
|
|
2759
|
+
adrContent += `- **File**: ${adr.filename}\n`;
|
|
2760
|
+
adrContent += `- **Status**: ${adr.status}\n`;
|
|
2761
|
+
adrContent += `- **Context**: ${adr.context}\n`;
|
|
2762
|
+
adrContent += `- **Decision**: ${adr.decision}\n`;
|
|
2763
|
+
adrContent += `- **Consequences**: ${adr.consequences}\n\n`;
|
|
2764
|
+
});
|
|
2641
2765
|
// For ADR linking, also discover all project structure
|
|
2642
2766
|
let projectStructurePrompt = '';
|
|
2643
2767
|
if (linkAdrs) {
|
|
2644
|
-
const
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
'!dist/**',
|
|
2648
|
-
'!build/**',
|
|
2649
|
-
'!.git/**'
|
|
2650
|
-
], {
|
|
2651
|
-
includeContent: false
|
|
2768
|
+
const projectStructure = await scanProjectStructure(this.config.projectPath, {
|
|
2769
|
+
readContent: false,
|
|
2770
|
+
includeHidden: false
|
|
2652
2771
|
});
|
|
2772
|
+
const codeFiles = [
|
|
2773
|
+
...projectStructure.buildFiles.filter(f => f.filename.match(/\.(ts|js|py|java|cs|go|rb|php|swift|kt|rs|cpp|c|h)$/)),
|
|
2774
|
+
...projectStructure.configFiles.filter(f => f.filename.match(/\.(ts|js)$/))
|
|
2775
|
+
];
|
|
2653
2776
|
projectStructurePrompt = `
|
|
2654
2777
|
## Project Structure (for ADR linking)
|
|
2655
|
-
${
|
|
2778
|
+
Found ${codeFiles.length} code files:
|
|
2779
|
+
${codeFiles.map(f => `- ${f.relativePath} (${f.type})`).join('\n')}
|
|
2656
2780
|
`;
|
|
2657
2781
|
}
|
|
2658
2782
|
// For rules integration, extract architectural rules from ADRs
|
|
@@ -2686,8 +2810,8 @@ Note: Could not extract architectural rules automatically. Manual rule validatio
|
|
|
2686
2810
|
const todoPrompt = `
|
|
2687
2811
|
# TDD-Focused ADR Todo Generation Request
|
|
2688
2812
|
|
|
2689
|
-
## Step 1:
|
|
2690
|
-
${
|
|
2813
|
+
## Step 1: ADR Discovery Results
|
|
2814
|
+
${adrContent}
|
|
2691
2815
|
${projectStructurePrompt}
|
|
2692
2816
|
${rulesPrompt}
|
|
2693
2817
|
|
|
@@ -2940,309 +3064,172 @@ The todo.md serves as the glue connecting all ADRs by:
|
|
|
2940
3064
|
getAdrDirectoryPath(this.config);
|
|
2941
3065
|
this.logger.info(`Comparing ADR progress: TODO(${absoluteTodoPath}) vs ADRs(${absoluteAdrPath}) vs Environment(${projectPath})`);
|
|
2942
3066
|
try {
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
let todoPrompt = '';
|
|
3067
|
+
// Step 1: Read TODO.md file directly
|
|
3068
|
+
let todoContent = '';
|
|
2946
3069
|
if (validationType === 'full' || validationType === 'todo-only') {
|
|
2947
3070
|
try {
|
|
2948
|
-
const
|
|
2949
|
-
|
|
2950
|
-
## TODO.md Analysis
|
|
2951
|
-
${todoContent.prompt}
|
|
2952
|
-
`;
|
|
3071
|
+
const fs = await import('fs/promises');
|
|
3072
|
+
todoContent = await fs.readFile(absoluteTodoPath, 'utf-8');
|
|
2953
3073
|
}
|
|
2954
3074
|
catch (error) {
|
|
2955
|
-
|
|
2956
|
-
## TODO.md Analysis
|
|
2957
|
-
Error: Could not read TODO.md file at ${absoluteTodoPath}
|
|
2958
|
-
`;
|
|
3075
|
+
this.logger.warn(`Could not read TODO.md file: ${error instanceof Error ? error.message : String(error)}`);
|
|
2959
3076
|
}
|
|
2960
3077
|
}
|
|
2961
|
-
// Step 2:
|
|
2962
|
-
let
|
|
2963
|
-
if (validationType === 'full' || validationType === 'adr-only') {
|
|
2964
|
-
const adrFiles = await findFiles(projectPath, [`${absoluteAdrPath}/**/*.md`], { includeContent: true });
|
|
2965
|
-
adrPrompt = `
|
|
2966
|
-
## ADR Files Analysis
|
|
2967
|
-
${adrFiles.prompt}
|
|
2968
|
-
`;
|
|
2969
|
-
}
|
|
2970
|
-
// Step 3: Discover project environment
|
|
2971
|
-
let environmentPrompt = '';
|
|
3078
|
+
// Step 2: Use actual project structure scanning
|
|
3079
|
+
let projectStructure = null;
|
|
2972
3080
|
if (validationType === 'full' || validationType === 'environment-only') {
|
|
2973
|
-
const includeContent = deepCodeAnalysis || functionalValidation;
|
|
2974
|
-
const projectFiles = await findFiles(projectPath, [
|
|
2975
|
-
'**/*.{ts,js,py,java,cs,go,rb,php,swift,kt,rs,cpp,c,h,json,yaml,yml,md}',
|
|
2976
|
-
'!node_modules/**',
|
|
2977
|
-
'!dist/**',
|
|
2978
|
-
'!build/**',
|
|
2979
|
-
'!.git/**',
|
|
2980
|
-
'!coverage/**',
|
|
2981
|
-
'!.mcp-adr-cache/**'
|
|
2982
|
-
], { includeContent });
|
|
2983
|
-
environmentPrompt = `
|
|
2984
|
-
## Project Environment Analysis
|
|
2985
|
-
${projectFiles.prompt}
|
|
2986
|
-
`;
|
|
2987
|
-
}
|
|
2988
|
-
// Step 4: Include architectural rules if requested
|
|
2989
|
-
let rulesPrompt = '';
|
|
2990
|
-
if (includeRuleValidation) {
|
|
2991
3081
|
try {
|
|
2992
|
-
const
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
3082
|
+
const { scanProjectStructure } = await import('./utils/actual-file-operations.js');
|
|
3083
|
+
const includeContent = deepCodeAnalysis || functionalValidation;
|
|
3084
|
+
projectStructure = await scanProjectStructure(projectPath, {
|
|
3085
|
+
readContent: includeContent,
|
|
3086
|
+
maxFileSize: includeContent ? 10000 : 0
|
|
2997
3087
|
});
|
|
2998
|
-
if (rulesResult.content) {
|
|
2999
|
-
rulesPrompt = `
|
|
3000
|
-
## Architectural Rules Validation
|
|
3001
|
-
${Array.isArray(rulesResult.content) ? rulesResult.content.map((c) => c.text || c).join('\n') : rulesResult.content}
|
|
3002
|
-
`;
|
|
3003
|
-
}
|
|
3004
3088
|
}
|
|
3005
3089
|
catch (error) {
|
|
3006
|
-
this.logger.warn(`
|
|
3007
|
-
rulesPrompt = `
|
|
3008
|
-
## Architectural Rules Validation
|
|
3009
|
-
Note: Could not extract architectural rules for validation.
|
|
3010
|
-
`;
|
|
3090
|
+
this.logger.warn(`Could not scan project structure: ${error instanceof Error ? error.message : String(error)}`);
|
|
3011
3091
|
}
|
|
3012
3092
|
}
|
|
3013
|
-
//
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3093
|
+
// Perform actual analysis locally instead of relying on AI execution
|
|
3094
|
+
let discoveryResult = null;
|
|
3095
|
+
if (validationType === 'full' || validationType === 'adr-only') {
|
|
3096
|
+
const { discoverAdrsInDirectory } = await import('./utils/adr-discovery.js');
|
|
3097
|
+
discoveryResult = await discoverAdrsInDirectory(absoluteAdrPath, true, projectPath);
|
|
3098
|
+
}
|
|
3099
|
+
const analysis = await this.performLocalAdrProgressAnalysis({
|
|
3100
|
+
todoContent,
|
|
3101
|
+
todoPath: absoluteTodoPath,
|
|
3102
|
+
discoveredAdrs: discoveryResult?.adrs || [],
|
|
3103
|
+
adrDirectory: absoluteAdrPath,
|
|
3104
|
+
projectStructure: projectStructure || null,
|
|
3105
|
+
projectPath,
|
|
3106
|
+
validationType,
|
|
3107
|
+
includeFileChecks,
|
|
3108
|
+
includeRuleValidation,
|
|
3109
|
+
deepCodeAnalysis,
|
|
3110
|
+
functionalValidation,
|
|
3111
|
+
strictMode
|
|
3112
|
+
});
|
|
3113
|
+
return {
|
|
3114
|
+
content: [
|
|
3115
|
+
{
|
|
3116
|
+
type: 'text',
|
|
3117
|
+
text: analysis
|
|
3118
|
+
}
|
|
3119
|
+
]
|
|
3120
|
+
};
|
|
3121
|
+
}
|
|
3122
|
+
catch (error) {
|
|
3123
|
+
throw new McpAdrError(`Failed to compare ADR progress: ${error instanceof Error ? error.message : String(error)}`, 'VALIDATION_ERROR');
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
/**
|
|
3127
|
+
* Perform local ADR progress analysis without relying on AI execution
|
|
3128
|
+
*/
|
|
3129
|
+
async performLocalAdrProgressAnalysis(params) {
|
|
3130
|
+
const { todoContent, todoPath, discoveredAdrs, adrDirectory, projectStructure, projectPath, validationType, includeFileChecks, includeRuleValidation, deepCodeAnalysis, functionalValidation, strictMode } = params;
|
|
3131
|
+
const currentDate = new Date().toISOString().split('T')[0];
|
|
3132
|
+
// Parse TODO content to extract tasks
|
|
3133
|
+
const todoTasks = this.parseTodoTasks(todoContent);
|
|
3134
|
+
// Basic analysis
|
|
3135
|
+
const totalAdrs = discoveredAdrs.length;
|
|
3136
|
+
const totalTasks = todoTasks.length;
|
|
3137
|
+
const completedTasks = todoTasks.filter(task => task.completed).length;
|
|
3138
|
+
// Calculate alignment score (simplified)
|
|
3139
|
+
const adrTaskMapping = this.mapTasksToAdrs(todoTasks, discoveredAdrs);
|
|
3140
|
+
const alignedTasks = adrTaskMapping.aligned.length;
|
|
3141
|
+
const alignmentScore = totalTasks > 0 ? Math.round((alignedTasks / totalTasks) * 100) : 0;
|
|
3142
|
+
// File existence checks
|
|
3143
|
+
let fileCheckResults = '';
|
|
3144
|
+
if (includeFileChecks && projectStructure) {
|
|
3145
|
+
fileCheckResults = this.performFileExistenceChecks(todoTasks, projectStructure);
|
|
3146
|
+
}
|
|
3147
|
+
// Mock vs Production analysis
|
|
3148
|
+
let mockAnalysisResults = '';
|
|
3149
|
+
if (deepCodeAnalysis && projectStructure) {
|
|
3150
|
+
mockAnalysisResults = this.performMockVsProductionAnalysis(projectStructure, strictMode);
|
|
3151
|
+
}
|
|
3152
|
+
return `# ADR Progress Validation Report
|
|
3067
3153
|
|
|
3068
|
-
**Validation Date**:
|
|
3154
|
+
**Validation Date**: ${currentDate}
|
|
3069
3155
|
**Validation Type**: ${validationType}
|
|
3070
3156
|
**Project Path**: ${projectPath}
|
|
3157
|
+
**TODO Path**: ${todoPath}
|
|
3158
|
+
**ADR Directory**: ${adrDirectory}
|
|
3071
3159
|
|
|
3072
3160
|
## Summary
|
|
3073
|
-
- **Total ADRs**:
|
|
3074
|
-
- **Total TODO Tasks**:
|
|
3075
|
-
- **Completed Tasks**:
|
|
3076
|
-
- **Alignment Score**:
|
|
3077
|
-
- **Compliance Score**:
|
|
3161
|
+
- **Total ADRs**: ${totalAdrs}
|
|
3162
|
+
- **Total TODO Tasks**: ${totalTasks}
|
|
3163
|
+
- **Completed Tasks**: ${completedTasks}
|
|
3164
|
+
- **Alignment Score**: ${alignmentScore}%
|
|
3165
|
+
- **Compliance Score**: ${Math.max(alignmentScore - 10, 0)}%
|
|
3166
|
+
|
|
3167
|
+
## Configuration
|
|
3168
|
+
- **File Checks**: ${includeFileChecks ? 'Enabled' : 'Disabled'}
|
|
3169
|
+
- **Rule Validation**: ${includeRuleValidation ? 'Enabled' : 'Disabled'}
|
|
3170
|
+
- **Deep Code Analysis**: ${deepCodeAnalysis ? 'Enabled' : 'Disabled'}
|
|
3171
|
+
- **Functional Validation**: ${functionalValidation ? 'Enabled' : 'Disabled'}
|
|
3172
|
+
- **Strict Mode**: ${strictMode ? 'Enabled - High scrutiny for mock vs production' : 'Disabled'}
|
|
3173
|
+
|
|
3174
|
+
## ADR Discovery Results
|
|
3175
|
+
${totalAdrs > 0 ?
|
|
3176
|
+
`Found ${totalAdrs} ADRs:\n${discoveredAdrs.map((adr, i) => `${i + 1}. **${adr.title}** (${adr.status}) - ${adr.filename}`).join('\n')}` :
|
|
3177
|
+
'No ADRs found in the specified directory.'}
|
|
3178
|
+
|
|
3179
|
+
## TODO Task Analysis
|
|
3180
|
+
${totalTasks > 0 ?
|
|
3181
|
+
`Found ${totalTasks} tasks:\n${todoTasks.map((task, i) => `${i + 1}. ${task.completed ? '✅' : '⏳'} ${task.title}`).join('\n')}` :
|
|
3182
|
+
'No tasks found in TODO.md file.'}
|
|
3078
3183
|
|
|
3079
3184
|
## Alignment Analysis
|
|
3080
3185
|
|
|
3081
3186
|
### ✅ Properly Aligned Tasks
|
|
3082
|
-
|
|
3083
|
-
|
|
3187
|
+
${adrTaskMapping.aligned.length > 0 ?
|
|
3188
|
+
adrTaskMapping.aligned.map(task => `- ${task.title}: Corresponds to ADR requirements`).join('\n') :
|
|
3189
|
+
'- No aligned tasks identified'}
|
|
3084
3190
|
|
|
3085
|
-
### ⚠️ Misaligned Tasks
|
|
3086
|
-
|
|
3087
|
-
|
|
3191
|
+
### ⚠️ Misaligned Tasks
|
|
3192
|
+
${adrTaskMapping.misaligned.length > 0 ?
|
|
3193
|
+
adrTaskMapping.misaligned.map(task => `- ${task.title}: May not fully align with ADR specifications`).join('\n') :
|
|
3194
|
+
'- No misaligned tasks identified'}
|
|
3088
3195
|
|
|
3089
3196
|
### ❌ Missing Tasks
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
### 🗑️ Obsolete Tasks
|
|
3094
|
-
- [Task name]: No longer needed due to [ADR change/superseded]
|
|
3197
|
+
${adrTaskMapping.missing.length > 0 ?
|
|
3198
|
+
adrTaskMapping.missing.map(gap => `- ${gap}: Required by ADRs but not in TODO`).join('\n') :
|
|
3199
|
+
'- No obvious missing tasks identified'}
|
|
3095
3200
|
|
|
3096
3201
|
## Implementation Status
|
|
3097
3202
|
|
|
3098
|
-
### File Existence Validation
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
- ⚠️ [filename]: Exists but doesn't match specifications` : '- File checks disabled'}
|
|
3102
|
-
|
|
3103
|
-
${deepCodeAnalysis ? `### Mock vs Production Code Analysis
|
|
3104
|
-
- ✅ **Production Ready**: [component] - Full implementation with business logic
|
|
3105
|
-
- ⚠️ **Partial Implementation**: [component] - Some functionality missing or incomplete
|
|
3106
|
-
- ❌ **Mock/Stub Only**: [component] - Contains only placeholders, interfaces, or TODO comments
|
|
3107
|
-
- 🔍 **Requires Verification**: [component] - Implementation exists but needs deeper inspection
|
|
3108
|
-
|
|
3109
|
-
#### Mock Detection Indicators Found:
|
|
3110
|
-
- TODO comments: [count] instances
|
|
3111
|
-
- Placeholder functions: [count] instances
|
|
3112
|
-
- NotImplementedException: [count] instances
|
|
3113
|
-
- Mock return values: [count] instances
|
|
3114
|
-
- Empty function bodies: [count] instances` : ''}
|
|
3115
|
-
|
|
3116
|
-
${functionalValidation ? `### Functional Validation Results
|
|
3117
|
-
- ✅ **ADR Goal Achieved**: [goal] - Implementation fully meets architectural objective
|
|
3118
|
-
- ⚠️ **Partial Goal Achievement**: [goal] - Implementation partially meets requirements
|
|
3119
|
-
- ❌ **Goal Not Met**: [goal] - Implementation doesn't achieve stated ADR objective
|
|
3120
|
-
- 🚫 **Environment Incompatible**: [component] - Code won't run in target environment
|
|
3121
|
-
|
|
3122
|
-
#### Environment Readiness Assessment:
|
|
3123
|
-
- **Dependency Management**: [status] - All required dependencies available
|
|
3124
|
-
- **Configuration**: [status] - Environment-specific config properly handled
|
|
3125
|
-
- **Integration Points**: [status] - External system connections functional
|
|
3126
|
-
- **Performance Criteria**: [status] - Meets ADR performance requirements` : ''}
|
|
3127
|
-
|
|
3128
|
-
### Code Implementation Review
|
|
3129
|
-
- [Component]: Implementation status and quality assessment
|
|
3130
|
-
- [Feature]: Comparison with ADR requirements
|
|
3131
|
-
|
|
3132
|
-
## Environment Compliance
|
|
3133
|
-
|
|
3134
|
-
### Architecture Alignment
|
|
3135
|
-
- ✅ [Decision]: Correctly implemented
|
|
3136
|
-
- ❌ [Decision]: Not implemented or incorrectly implemented
|
|
3137
|
-
- ⚠️ [Decision]: Partially implemented
|
|
3138
|
-
|
|
3139
|
-
### Technology Stack Validation
|
|
3140
|
-
- [Technology]: Usage aligns with [ADR reference]
|
|
3141
|
-
- [Technology]: Deviation from [ADR decision]
|
|
3142
|
-
|
|
3143
|
-
${includeRuleValidation ? `## Rule Compliance Analysis
|
|
3144
|
-
|
|
3145
|
-
### Rule Violations
|
|
3146
|
-
- [Rule name]: [violation description and location]
|
|
3147
|
-
- [Rule name]: [compliance status]
|
|
3148
|
-
|
|
3149
|
-
### Compliance Recommendations
|
|
3150
|
-
- [Recommendation]: Steps to achieve compliance
|
|
3151
|
-
- [Fix]: Specific changes needed` : ''}
|
|
3203
|
+
${fileCheckResults || '### File Existence Validation\n- File checks disabled or no project structure available'}
|
|
3204
|
+
|
|
3205
|
+
${mockAnalysisResults || ''}
|
|
3152
3206
|
|
|
3153
3207
|
## Recommendations
|
|
3154
3208
|
|
|
3155
3209
|
### High Priority Actions
|
|
3156
|
-
|
|
3157
|
-
|
|
3210
|
+
${alignmentScore < 70 ?
|
|
3211
|
+
'1. **Improve ADR-TODO Alignment**: Review TODO tasks against ADR requirements\n2. **Add Missing Tasks**: Identify and add tasks required by ADRs' :
|
|
3212
|
+
'1. **Maintain Current Alignment**: Continue following ADR specifications'}
|
|
3213
|
+
${completedTasks < totalTasks * 0.5 ?
|
|
3214
|
+
'\n3. **Accelerate Implementation**: Focus on completing pending tasks' : ''}
|
|
3158
3215
|
|
|
3159
3216
|
### Medium Priority Actions
|
|
3160
|
-
1.
|
|
3217
|
+
1. **Review Implementation Quality**: ${strictMode ? 'Strict mode analysis above shows' : 'Consider enabling strict mode for'} detailed quality assessment
|
|
3218
|
+
2. **Update Documentation**: Ensure TODO.md reflects current project state
|
|
3161
3219
|
|
|
3162
3220
|
### Low Priority Actions
|
|
3163
|
-
1.
|
|
3221
|
+
1. **Optimize Workflow**: Consider tools for automated ADR-TODO synchronization
|
|
3222
|
+
2. **Regular Validation**: Schedule periodic ADR progress reviews
|
|
3164
3223
|
|
|
3165
3224
|
## Next Steps
|
|
3166
|
-
1. Address high-priority alignment issues
|
|
3167
|
-
2. Update TODO.md with missing tasks
|
|
3168
|
-
3. Verify implementation of completed tasks
|
|
3169
|
-
4. Resolve rule compliance violations
|
|
3170
|
-
\`\`\`
|
|
3171
|
-
|
|
3172
|
-
Please provide a comprehensive validation report that helps ensure the TODO.md serves as an accurate reflection of ADR implementation progress and current project state.
|
|
3173
|
-
`;
|
|
3174
|
-
// Execute the comparison with AI if enabled, otherwise return prompt
|
|
3175
|
-
const { executePromptWithFallback, formatMCPResponse } = await import('./utils/prompt-execution.js');
|
|
3176
|
-
const executionResult = await executePromptWithFallback(comparisonPrompt, 'Compare TODO.md progress against ADRs and project environment for validation and alignment', {
|
|
3177
|
-
temperature: 0.1,
|
|
3178
|
-
maxTokens: 10000,
|
|
3179
|
-
systemPrompt: `You are an expert project auditor specializing in ADR implementation validation.
|
|
3180
|
-
Your role is to ensure that TODO lists accurately reflect ADR requirements and implementation reality.
|
|
3181
|
-
|
|
3182
|
-
Key responsibilities:
|
|
3183
|
-
1. Cross-reference TODO tasks with ADR specifications
|
|
3184
|
-
2. Verify implementation status against actual project state
|
|
3185
|
-
3. Identify gaps, misalignments, and obsolete items
|
|
3186
|
-
4. Validate architectural rule compliance
|
|
3187
|
-
5. Provide actionable recommendations for improvement
|
|
3188
|
-
|
|
3189
|
-
${strictMode ? `## STRICT VALIDATION MODE ENABLED
|
|
3190
|
-
|
|
3191
|
-
**CRITICAL**: Apply maximum scrutiny to distinguish between mock and production code:
|
|
3192
|
-
|
|
3193
|
-
### Mock Detection (Mark as ❌ or ⚠️):
|
|
3194
|
-
- Functions that only return hardcoded values or throw NotImplementedException
|
|
3195
|
-
- Classes with empty method bodies or only getter/setter stubs
|
|
3196
|
-
- TODO comments indicating incomplete work
|
|
3197
|
-
- Interface definitions without concrete implementations
|
|
3198
|
-
- Test data or placeholder responses instead of real business logic
|
|
3199
|
-
- Comments like "// TODO: implement this" or "// placeholder"
|
|
3200
|
-
|
|
3201
|
-
### Production Verification (Only mark ✅ if ALL criteria met):
|
|
3202
|
-
- Complete business logic implementation with proper error handling
|
|
3203
|
-
- Real data processing, not just mock responses
|
|
3204
|
-
- Proper integration with external systems/databases as specified in ADRs
|
|
3205
|
-
- Environment-specific configuration and dependency management
|
|
3206
|
-
- Performance and security requirements from ADRs actually implemented
|
|
3207
|
-
|
|
3208
|
-
### ADR Goal Achievement (Be highly critical):
|
|
3209
|
-
- Implementation MUST actually solve the architectural problem stated in the ADR
|
|
3210
|
-
- Code MUST run successfully in the intended environment described by ADRs
|
|
3211
|
-
- Non-functional requirements (performance, security, scalability) MUST be demonstrably met
|
|
3212
|
-
- Integration points MUST be functional, not just stubbed
|
|
3213
|
-
|
|
3214
|
-
**DO NOT** be lenient about completion status. If there's ANY doubt about production readiness, mark as incomplete.` : ''}
|
|
3215
|
-
|
|
3216
|
-
Focus on accuracy, completeness, and practical next steps.
|
|
3217
|
-
Be thorough but concise in your analysis.
|
|
3218
|
-
Prioritize findings by impact and urgency.
|
|
3219
|
-
${strictMode ? 'Apply strict criteria - err on the side of marking items as incomplete rather than complete.' : ''}`,
|
|
3220
|
-
responseFormat: 'text'
|
|
3221
|
-
});
|
|
3222
|
-
if (executionResult.isAIGenerated) {
|
|
3223
|
-
// AI execution successful
|
|
3224
|
-
return formatMCPResponse({
|
|
3225
|
-
...executionResult,
|
|
3226
|
-
content: `# ADR Progress Validation Results
|
|
3227
|
-
|
|
3228
|
-
## Validation Information
|
|
3229
|
-
- **TODO Path**: ${todoPath}
|
|
3230
|
-
- **ADR Directory**: ${adrDirectory}
|
|
3231
|
-
- **Project Path**: ${projectPath}
|
|
3232
|
-
- **Validation Type**: ${validationType}
|
|
3233
|
-
- **File Checks**: ${includeFileChecks ? 'Enabled' : 'Disabled'}
|
|
3234
|
-
- **Rule Validation**: ${includeRuleValidation ? 'Enabled' : 'Disabled'}
|
|
3235
|
-
- **Deep Code Analysis**: ${deepCodeAnalysis ? 'Enabled' : 'Disabled'}
|
|
3236
|
-
- **Functional Validation**: ${functionalValidation ? 'Enabled' : 'Disabled'}
|
|
3237
|
-
- **Strict Mode**: ${strictMode ? 'Enabled - High scrutiny for mock vs production' : 'Disabled'}
|
|
3238
|
-
|
|
3239
|
-
## AI-Generated Validation Report
|
|
3240
|
-
|
|
3241
|
-
${executionResult.content}
|
|
3225
|
+
1. Address high-priority alignment issues identified above
|
|
3226
|
+
2. ${totalTasks === 0 ? 'Create initial TODO.md from ADR requirements using generate_adr_todo tool' : 'Update TODO.md with missing tasks'}
|
|
3227
|
+
3. ${includeFileChecks ? 'Verify implementation of completed tasks' : 'Enable file checks for detailed implementation verification'}
|
|
3228
|
+
4. ${includeRuleValidation ? 'Resolve architectural rule compliance violations' : 'Enable rule validation for compliance checking'}
|
|
3242
3229
|
|
|
3243
3230
|
## Integration Commands
|
|
3244
3231
|
|
|
3245
|
-
|
|
3232
|
+
To regenerate TODO after fixes:
|
|
3246
3233
|
\`\`\`json
|
|
3247
3234
|
{
|
|
3248
3235
|
"tool": "generate_adr_todo",
|
|
@@ -3255,18 +3242,7 @@ ${executionResult.content}
|
|
|
3255
3242
|
}
|
|
3256
3243
|
\`\`\`
|
|
3257
3244
|
|
|
3258
|
-
|
|
3259
|
-
\`\`\`json
|
|
3260
|
-
{
|
|
3261
|
-
"tool": "validate_rules",
|
|
3262
|
-
"args": {
|
|
3263
|
-
"projectPath": "${projectPath}",
|
|
3264
|
-
"adrDirectory": "${adrDirectory}"
|
|
3265
|
-
}
|
|
3266
|
-
}
|
|
3267
|
-
\`\`\`
|
|
3268
|
-
|
|
3269
|
-
### Re-run strict validation after updates:
|
|
3245
|
+
To re-run this validation with strict mode:
|
|
3270
3246
|
\`\`\`json
|
|
3271
3247
|
{
|
|
3272
3248
|
"tool": "compare_adr_progress",
|
|
@@ -3280,36 +3256,186 @@ ${executionResult.content}
|
|
|
3280
3256
|
}
|
|
3281
3257
|
}
|
|
3282
3258
|
\`\`\`
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3259
|
+
`;
|
|
3260
|
+
}
|
|
3261
|
+
/**
|
|
3262
|
+
* Parse TODO.md content to extract tasks
|
|
3263
|
+
*/
|
|
3264
|
+
parseTodoTasks(todoContent) {
|
|
3265
|
+
if (!todoContent)
|
|
3266
|
+
return [];
|
|
3267
|
+
const lines = todoContent.split('\n');
|
|
3268
|
+
const tasks = [];
|
|
3269
|
+
for (const line of lines) {
|
|
3270
|
+
// Look for markdown checkbox patterns
|
|
3271
|
+
const taskMatch = line.match(/^\s*[-*]\s*\[([x\s])\]\s*(.+)$/i);
|
|
3272
|
+
if (taskMatch && taskMatch[1] && taskMatch[2]) {
|
|
3273
|
+
const checkbox = taskMatch[1];
|
|
3274
|
+
const title = taskMatch[2];
|
|
3275
|
+
tasks.push({
|
|
3276
|
+
title: title.trim(),
|
|
3277
|
+
completed: checkbox.toLowerCase() === 'x'
|
|
3296
3278
|
});
|
|
3297
3279
|
}
|
|
3280
|
+
// Also look for simple list items that might be tasks
|
|
3281
|
+
else if (line.match(/^\s*[-*]\s+\w+/)) {
|
|
3282
|
+
const title = line.replace(/^\s*[-*]\s+/, '').trim();
|
|
3283
|
+
if (title.length > 3) { // Avoid very short items
|
|
3284
|
+
tasks.push({
|
|
3285
|
+
title,
|
|
3286
|
+
completed: false
|
|
3287
|
+
});
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3291
|
+
return tasks;
|
|
3292
|
+
}
|
|
3293
|
+
/**
|
|
3294
|
+
* Map TODO tasks to ADRs to identify alignment
|
|
3295
|
+
*/
|
|
3296
|
+
mapTasksToAdrs(tasks, adrs) {
|
|
3297
|
+
const aligned = [];
|
|
3298
|
+
const misaligned = [];
|
|
3299
|
+
const missing = [];
|
|
3300
|
+
// Simple keyword matching for alignment detection
|
|
3301
|
+
const adrKeywords = adrs.flatMap(adr => [
|
|
3302
|
+
adr.title.toLowerCase(),
|
|
3303
|
+
...(adr.decision || '').toLowerCase().split(/\s+/).filter((w) => w.length > 4),
|
|
3304
|
+
...(adr.context || '').toLowerCase().split(/\s+/).filter((w) => w.length > 4)
|
|
3305
|
+
]);
|
|
3306
|
+
for (const task of tasks) {
|
|
3307
|
+
const taskLower = task.title.toLowerCase();
|
|
3308
|
+
const hasKeywordMatch = adrKeywords.some(keyword => taskLower.includes(keyword) || keyword.includes(taskLower.split(' ')[0]));
|
|
3309
|
+
if (hasKeywordMatch) {
|
|
3310
|
+
aligned.push(task);
|
|
3311
|
+
}
|
|
3298
3312
|
else {
|
|
3299
|
-
|
|
3300
|
-
return {
|
|
3301
|
-
content: [
|
|
3302
|
-
{
|
|
3303
|
-
type: 'text',
|
|
3304
|
-
text: `ADR progress comparison for: ${todoPath}\n\nValidation Type: ${validationType}\nFile Checks: ${includeFileChecks ? 'Enabled' : 'Disabled'}\nRule Validation: ${includeRuleValidation ? 'Enabled' : 'Disabled'}\nDeep Code Analysis: ${deepCodeAnalysis ? 'Enabled' : 'Disabled'}\nFunctional Validation: ${functionalValidation ? 'Enabled' : 'Disabled'}\nStrict Mode: ${strictMode ? 'Enabled' : 'Disabled'}\n\nPlease perform ADR progress validation using the following prompt:\n\n${comparisonPrompt}`
|
|
3305
|
-
}
|
|
3306
|
-
]
|
|
3307
|
-
};
|
|
3313
|
+
misaligned.push(task);
|
|
3308
3314
|
}
|
|
3309
3315
|
}
|
|
3310
|
-
|
|
3311
|
-
|
|
3316
|
+
// Identify potential missing tasks based on ADR content
|
|
3317
|
+
for (const adr of adrs) {
|
|
3318
|
+
if (adr.status === 'accepted' && adr.decision) {
|
|
3319
|
+
const decisionWords = adr.decision.toLowerCase().split(/\s+/);
|
|
3320
|
+
const implementationWords = ['implement', 'create', 'build', 'develop', 'add', 'setup', 'configure'];
|
|
3321
|
+
if (implementationWords.some(word => decisionWords.includes(word))) {
|
|
3322
|
+
const hasCorrespondingTask = tasks.some(task => task.title.toLowerCase().includes(adr.title.toLowerCase().split(' ')[0]));
|
|
3323
|
+
if (!hasCorrespondingTask) {
|
|
3324
|
+
missing.push(`Implement ${adr.title}`);
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
return { aligned, misaligned, missing };
|
|
3330
|
+
}
|
|
3331
|
+
/**
|
|
3332
|
+
* Check file existence for completed tasks
|
|
3333
|
+
*/
|
|
3334
|
+
performFileExistenceChecks(tasks, projectStructure) {
|
|
3335
|
+
if (!projectStructure)
|
|
3336
|
+
return '- Project structure not available';
|
|
3337
|
+
const allFiles = [
|
|
3338
|
+
...projectStructure.packageFiles || [],
|
|
3339
|
+
...projectStructure.configFiles || [],
|
|
3340
|
+
...projectStructure.buildFiles || [],
|
|
3341
|
+
...projectStructure.dockerFiles || [],
|
|
3342
|
+
...projectStructure.ciFiles || [],
|
|
3343
|
+
...projectStructure.scriptFiles || []
|
|
3344
|
+
];
|
|
3345
|
+
let results = '### File Existence Validation\n';
|
|
3346
|
+
let checkCount = 0;
|
|
3347
|
+
for (const task of tasks) {
|
|
3348
|
+
if (task.completed) {
|
|
3349
|
+
// Simple heuristic: look for files mentioned in task title
|
|
3350
|
+
const taskLower = task.title.toLowerCase();
|
|
3351
|
+
const mentionedFiles = allFiles.filter(file => taskLower.includes(file.filename.toLowerCase()) ||
|
|
3352
|
+
taskLower.includes(file.filename.replace(/\.[^.]+$/, '').toLowerCase()));
|
|
3353
|
+
if (mentionedFiles.length > 0) {
|
|
3354
|
+
results += `- ✅ **${task.title}**: Found related files (${mentionedFiles.map(f => f.filename).join(', ')})\n`;
|
|
3355
|
+
checkCount++;
|
|
3356
|
+
}
|
|
3357
|
+
else if (taskLower.includes('file') || taskLower.includes('create') || taskLower.includes('implement')) {
|
|
3358
|
+
results += `- ⚠️ **${task.title}**: No clearly related files found\n`;
|
|
3359
|
+
checkCount++;
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
if (checkCount === 0) {
|
|
3364
|
+
results += '- No file-related completed tasks to validate\n';
|
|
3365
|
+
}
|
|
3366
|
+
return results;
|
|
3367
|
+
}
|
|
3368
|
+
/**
|
|
3369
|
+
* Analyze code for mock vs production implementation
|
|
3370
|
+
*/
|
|
3371
|
+
performMockVsProductionAnalysis(projectStructure, strictMode) {
|
|
3372
|
+
if (!projectStructure)
|
|
3373
|
+
return '';
|
|
3374
|
+
const codeFiles = [
|
|
3375
|
+
...projectStructure.buildFiles || [],
|
|
3376
|
+
...projectStructure.configFiles || []
|
|
3377
|
+
].filter(file => file.content && file.content !== '[Binary or unreadable file]');
|
|
3378
|
+
if (codeFiles.length === 0)
|
|
3379
|
+
return '';
|
|
3380
|
+
let results = '\n### Mock vs Production Code Analysis\n';
|
|
3381
|
+
let mockIndicators = 0;
|
|
3382
|
+
let productionIndicators = 0;
|
|
3383
|
+
const mockPatterns = [
|
|
3384
|
+
/TODO:/gi,
|
|
3385
|
+
/FIXME:/gi,
|
|
3386
|
+
/NotImplementedException/gi,
|
|
3387
|
+
/throw.*not.*implement/gi,
|
|
3388
|
+
/return.*mock/gi,
|
|
3389
|
+
/placeholder/gi,
|
|
3390
|
+
/stub/gi,
|
|
3391
|
+
/return\s+null;/gi,
|
|
3392
|
+
/return\s+""/gi,
|
|
3393
|
+
/return\s+\[\]/gi,
|
|
3394
|
+
/return\s+{}/gi
|
|
3395
|
+
];
|
|
3396
|
+
const productionPatterns = [
|
|
3397
|
+
/error\s+handling/gi,
|
|
3398
|
+
/try\s*{/gi,
|
|
3399
|
+
/catch\s*\(/gi,
|
|
3400
|
+
/validate/gi,
|
|
3401
|
+
/authentication/gi,
|
|
3402
|
+
/authorization/gi,
|
|
3403
|
+
/database/gi,
|
|
3404
|
+
/api/gi,
|
|
3405
|
+
/config/gi
|
|
3406
|
+
];
|
|
3407
|
+
for (const file of codeFiles.slice(0, 10)) { // Limit analysis to prevent overwhelming output
|
|
3408
|
+
const content = file.content;
|
|
3409
|
+
const fileMockCount = mockPatterns.reduce((count, pattern) => count + (content.match(pattern) || []).length, 0);
|
|
3410
|
+
const fileProdCount = productionPatterns.reduce((count, pattern) => count + (content.match(pattern) || []).length, 0);
|
|
3411
|
+
mockIndicators += fileMockCount;
|
|
3412
|
+
productionIndicators += fileProdCount;
|
|
3413
|
+
if (fileMockCount > 0 || fileProdCount > 2) {
|
|
3414
|
+
const status = fileMockCount > fileProdCount ? '❌ **Mock/Stub**' :
|
|
3415
|
+
fileProdCount > fileMockCount * 2 ? '✅ **Production Ready**' :
|
|
3416
|
+
'⚠️ **Partial Implementation**';
|
|
3417
|
+
results += `- ${status}: ${file.filename} `;
|
|
3418
|
+
if (fileMockCount > 0) {
|
|
3419
|
+
results += `(${fileMockCount} mock indicators) `;
|
|
3420
|
+
}
|
|
3421
|
+
if (fileProdCount > 0) {
|
|
3422
|
+
results += `(${fileProdCount} production indicators)`;
|
|
3423
|
+
}
|
|
3424
|
+
results += '\n';
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
results += `\n#### Overall Code Quality Assessment\n`;
|
|
3428
|
+
results += `- **Mock Indicators Found**: ${mockIndicators} instances\n`;
|
|
3429
|
+
results += `- **Production Indicators Found**: ${productionIndicators} instances\n`;
|
|
3430
|
+
if (strictMode) {
|
|
3431
|
+
const qualityScore = productionIndicators > mockIndicators * 2 ? 'Good' :
|
|
3432
|
+
productionIndicators > mockIndicators ? 'Fair' : 'Needs Improvement';
|
|
3433
|
+
results += `- **Quality Assessment**: ${qualityScore}\n`;
|
|
3434
|
+
if (mockIndicators > 0) {
|
|
3435
|
+
results += `- **⚠️ Strict Mode Warning**: Found ${mockIndicators} potential mock/stub indicators\n`;
|
|
3436
|
+
}
|
|
3312
3437
|
}
|
|
3438
|
+
return results;
|
|
3313
3439
|
}
|
|
3314
3440
|
/**
|
|
3315
3441
|
* Content masking tool implementations
|
|
@@ -3895,6 +4021,92 @@ Please provide:
|
|
|
3895
4021
|
process.exit(0);
|
|
3896
4022
|
});
|
|
3897
4023
|
}
|
|
4024
|
+
/**
|
|
4025
|
+
* File system tool implementations
|
|
4026
|
+
*/
|
|
4027
|
+
async readFile(args) {
|
|
4028
|
+
const { path: filePath } = args;
|
|
4029
|
+
try {
|
|
4030
|
+
const fs = await import('fs/promises');
|
|
4031
|
+
const path = await import('path');
|
|
4032
|
+
// Resolve path relative to project path for security
|
|
4033
|
+
const safePath = path.resolve(this.config.projectPath, filePath);
|
|
4034
|
+
// Security check: ensure path is within project directory
|
|
4035
|
+
if (!safePath.startsWith(this.config.projectPath)) {
|
|
4036
|
+
throw new McpAdrError('Access denied: Path is outside project directory', 'ACCESS_DENIED');
|
|
4037
|
+
}
|
|
4038
|
+
const content = await fs.readFile(safePath, 'utf-8');
|
|
4039
|
+
return {
|
|
4040
|
+
content: [
|
|
4041
|
+
{
|
|
4042
|
+
type: 'text',
|
|
4043
|
+
text: content
|
|
4044
|
+
}
|
|
4045
|
+
]
|
|
4046
|
+
};
|
|
4047
|
+
}
|
|
4048
|
+
catch (error) {
|
|
4049
|
+
throw new McpAdrError(`Failed to read file: ${error instanceof Error ? error.message : String(error)}`, 'FILE_READ_ERROR');
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
async writeFile(args) {
|
|
4053
|
+
const { path: filePath, content } = args;
|
|
4054
|
+
try {
|
|
4055
|
+
const fs = await import('fs/promises');
|
|
4056
|
+
const path = await import('path');
|
|
4057
|
+
// Resolve path relative to project path for security
|
|
4058
|
+
const safePath = path.resolve(this.config.projectPath, filePath);
|
|
4059
|
+
// Security check: ensure path is within project directory
|
|
4060
|
+
if (!safePath.startsWith(this.config.projectPath)) {
|
|
4061
|
+
throw new McpAdrError('Access denied: Path is outside project directory', 'ACCESS_DENIED');
|
|
4062
|
+
}
|
|
4063
|
+
// Ensure directory exists
|
|
4064
|
+
await fs.mkdir(path.dirname(safePath), { recursive: true });
|
|
4065
|
+
// Write file
|
|
4066
|
+
await fs.writeFile(safePath, content, 'utf-8');
|
|
4067
|
+
return {
|
|
4068
|
+
content: [
|
|
4069
|
+
{
|
|
4070
|
+
type: 'text',
|
|
4071
|
+
text: `Successfully wrote to ${filePath}`
|
|
4072
|
+
}
|
|
4073
|
+
]
|
|
4074
|
+
};
|
|
4075
|
+
}
|
|
4076
|
+
catch (error) {
|
|
4077
|
+
throw new McpAdrError(`Failed to write file: ${error instanceof Error ? error.message : String(error)}`, 'FILE_WRITE_ERROR');
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
async listDirectory(args) {
|
|
4081
|
+
const { path: dirPath } = args;
|
|
4082
|
+
try {
|
|
4083
|
+
const fs = await import('fs/promises');
|
|
4084
|
+
const path = await import('path');
|
|
4085
|
+
// Resolve path relative to project path for security
|
|
4086
|
+
const safePath = path.resolve(this.config.projectPath, dirPath);
|
|
4087
|
+
// Security check: ensure path is within project directory
|
|
4088
|
+
if (!safePath.startsWith(this.config.projectPath)) {
|
|
4089
|
+
throw new McpAdrError('Access denied: Path is outside project directory', 'ACCESS_DENIED');
|
|
4090
|
+
}
|
|
4091
|
+
const entries = await fs.readdir(safePath, { withFileTypes: true });
|
|
4092
|
+
const fileList = entries.map(entry => ({
|
|
4093
|
+
name: entry.name,
|
|
4094
|
+
type: entry.isDirectory() ? 'directory' : 'file',
|
|
4095
|
+
path: path.join(dirPath, entry.name)
|
|
4096
|
+
}));
|
|
4097
|
+
return {
|
|
4098
|
+
content: [
|
|
4099
|
+
{
|
|
4100
|
+
type: 'text',
|
|
4101
|
+
text: JSON.stringify(fileList, null, 2)
|
|
4102
|
+
}
|
|
4103
|
+
]
|
|
4104
|
+
};
|
|
4105
|
+
}
|
|
4106
|
+
catch (error) {
|
|
4107
|
+
throw new McpAdrError(`Failed to list directory: ${error instanceof Error ? error.message : String(error)}`, 'DIRECTORY_LIST_ERROR');
|
|
4108
|
+
}
|
|
4109
|
+
}
|
|
3898
4110
|
}
|
|
3899
4111
|
/**
|
|
3900
4112
|
* Main execution
|