@noorm/marie-cli 0.1.0
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/JOY_ZONING.md +200 -0
- package/LICENSE.md +190 -0
- package/README.md +94 -0
- package/dist/cli-new/components/App.js +138 -0
- package/dist/cli-new/components/App.js.map +1 -0
- package/dist/cli-new/components/ApprovalDialog.js +31 -0
- package/dist/cli-new/components/ApprovalDialog.js.map +1 -0
- package/dist/cli-new/components/Banner.js +23 -0
- package/dist/cli-new/components/Banner.js.map +1 -0
- package/dist/cli-new/components/ChatArea.js +49 -0
- package/dist/cli-new/components/ChatArea.js.map +1 -0
- package/dist/cli-new/components/Header.js +20 -0
- package/dist/cli-new/components/Header.js.map +1 -0
- package/dist/cli-new/components/InputArea.js +97 -0
- package/dist/cli-new/components/InputArea.js.map +1 -0
- package/dist/cli-new/components/MessageBubble.js +114 -0
- package/dist/cli-new/components/MessageBubble.js.map +1 -0
- package/dist/cli-new/components/SessionSwitcher.js +46 -0
- package/dist/cli-new/components/SessionSwitcher.js.map +1 -0
- package/dist/cli-new/components/SetupWizard.js +283 -0
- package/dist/cli-new/components/SetupWizard.js.map +1 -0
- package/dist/cli-new/components/ToolCallDisplay.js +45 -0
- package/dist/cli-new/components/ToolCallDisplay.js.map +1 -0
- package/dist/cli-new/hooks/useGit.js +99 -0
- package/dist/cli-new/hooks/useGit.js.map +1 -0
- package/dist/cli-new/hooks/useMarie.js +249 -0
- package/dist/cli-new/hooks/useMarie.js.map +1 -0
- package/dist/cli-new/hooks/useSessions.js +75 -0
- package/dist/cli-new/hooks/useSessions.js.map +1 -0
- package/dist/cli-new/index.js +52 -0
- package/dist/cli-new/index.js.map +1 -0
- package/dist/cli-new/styles/theme.js +68 -0
- package/dist/cli-new/styles/theme.js.map +1 -0
- package/dist/cli-new/types/cli.js +2 -0
- package/dist/cli-new/types/cli.js.map +1 -0
- package/dist/extension.cjs +655 -0
- package/dist/monolith/adapters/CliMarieAdapter.js +72 -0
- package/dist/monolith/adapters/CliMarieAdapter.js.map +1 -0
- package/dist/monolith/adapters/VscodeMarieAdapter.js +81 -0
- package/dist/monolith/adapters/VscodeMarieAdapter.js.map +1 -0
- package/dist/monolith/cli/CliFileSystemPort.js +83 -0
- package/dist/monolith/cli/CliFileSystemPort.js.map +1 -0
- package/dist/monolith/cli/MarieToolDefinitionsCLI.js +438 -0
- package/dist/monolith/cli/MarieToolDefinitionsCLI.js.map +1 -0
- package/dist/monolith/cli/index.js +272 -0
- package/dist/monolith/cli/index.js.map +1 -0
- package/dist/monolith/cli/services/JoyAutomationServiceCLI.js +80 -0
- package/dist/monolith/cli/services/JoyAutomationServiceCLI.js.map +1 -0
- package/dist/monolith/cli/services/JoyServiceCLI.js +63 -0
- package/dist/monolith/cli/services/JoyServiceCLI.js.map +1 -0
- package/dist/monolith/cli/storage.js +119 -0
- package/dist/monolith/cli/storage.js.map +1 -0
- package/dist/monolith/domain/joy/JoyTools.js +513 -0
- package/dist/monolith/domain/joy/JoyTools.js.map +1 -0
- package/dist/monolith/domain/joy/RitualService.js +51 -0
- package/dist/monolith/domain/joy/RitualService.js.map +1 -0
- package/dist/monolith/domain/marie/MarieTypes.js +2 -0
- package/dist/monolith/domain/marie/MarieTypes.js.map +1 -0
- package/dist/monolith/infrastructure/ai/agents/MarieAscendant.js +230 -0
- package/dist/monolith/infrastructure/ai/agents/MarieAscendant.js.map +1 -0
- package/dist/monolith/infrastructure/ai/agents/MarieYOLO.js +207 -0
- package/dist/monolith/infrastructure/ai/agents/MarieYOLO.js.map +1 -0
- package/dist/monolith/infrastructure/ai/context/ContextArchiveService.js +129 -0
- package/dist/monolith/infrastructure/ai/context/ContextArchiveService.js.map +1 -0
- package/dist/monolith/infrastructure/ai/context/ContextManager.js +118 -0
- package/dist/monolith/infrastructure/ai/context/ContextManager.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/FileSystemPort.js +2 -0
- package/dist/monolith/infrastructure/ai/core/FileSystemPort.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/GhostPort.js +2 -0
- package/dist/monolith/infrastructure/ai/core/GhostPort.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieAscensionTypes.js +2 -0
- package/dist/monolith/infrastructure/ai/core/MarieAscensionTypes.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieEngine.js +590 -0
- package/dist/monolith/infrastructure/ai/core/MarieEngine.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieEventDispatcher.js +161 -0
- package/dist/monolith/infrastructure/ai/core/MarieEventDispatcher.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieLockManager.js +121 -0
- package/dist/monolith/infrastructure/ai/core/MarieLockManager.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieProgressTracker.js +256 -0
- package/dist/monolith/infrastructure/ai/core/MarieProgressTracker.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MariePulseService.js +67 -0
- package/dist/monolith/infrastructure/ai/core/MariePulseService.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieResponse.js +101 -0
- package/dist/monolith/infrastructure/ai/core/MarieResponse.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieSanitizer.js +86 -0
- package/dist/monolith/infrastructure/ai/core/MarieSanitizer.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieSession.js +202 -0
- package/dist/monolith/infrastructure/ai/core/MarieSession.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieStabilityMonitor.js +58 -0
- package/dist/monolith/infrastructure/ai/core/MarieStabilityMonitor.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolMender.js +127 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolMender.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js +548 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieYOLOTypes.js +2 -0
- package/dist/monolith/infrastructure/ai/core/MarieYOLOTypes.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/ReasoningBudget.js +125 -0
- package/dist/monolith/infrastructure/ai/core/ReasoningBudget.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js +30 -0
- package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/AIProvider.js +2 -0
- package/dist/monolith/infrastructure/ai/providers/AIProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/AnthropicProvider.js +148 -0
- package/dist/monolith/infrastructure/ai/providers/AnthropicProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/CerebrasProvider.js +208 -0
- package/dist/monolith/infrastructure/ai/providers/CerebrasProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterProvider.js +404 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterStreamParser.js +283 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterStreamParser.js.map +1 -0
- package/dist/monolith/infrastructure/config/ConfigService.js +398 -0
- package/dist/monolith/infrastructure/config/ConfigService.js.map +1 -0
- package/dist/monolith/infrastructure/services/MarieMemoryStore.js +140 -0
- package/dist/monolith/infrastructure/services/MarieMemoryStore.js.map +1 -0
- package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js +1568 -0
- package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js.map +1 -0
- package/dist/monolith/infrastructure/tools/PureStreamParser.js +147 -0
- package/dist/monolith/infrastructure/tools/PureStreamParser.js.map +1 -0
- package/dist/monolith/infrastructure/tools/SharedToolDefinitions.js +223 -0
- package/dist/monolith/infrastructure/tools/SharedToolDefinitions.js.map +1 -0
- package/dist/monolith/infrastructure/tools/ToolRegistry.js +29 -0
- package/dist/monolith/infrastructure/tools/ToolRegistry.js.map +1 -0
- package/dist/monolith/infrastructure/tools/ToolUtils.js +59 -0
- package/dist/monolith/infrastructure/tools/ToolUtils.js.map +1 -0
- package/dist/monolith/plumbing/analysis/CodeHealthService.js +146 -0
- package/dist/monolith/plumbing/analysis/CodeHealthService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/ComplexityService.js +43 -0
- package/dist/monolith/plumbing/analysis/ComplexityService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/DependencyService.js +51 -0
- package/dist/monolith/plumbing/analysis/DependencyService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/DiscoveryService.js +49 -0
- package/dist/monolith/plumbing/analysis/DiscoveryService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/JoyMapService.js +66 -0
- package/dist/monolith/plumbing/analysis/JoyMapService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/LintService.js +132 -0
- package/dist/monolith/plumbing/analysis/LintService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/MarieSentinelService.js +276 -0
- package/dist/monolith/plumbing/analysis/MarieSentinelService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/QualityGuardrailService.js +119 -0
- package/dist/monolith/plumbing/analysis/QualityGuardrailService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/SurgicalMender.js +70 -0
- package/dist/monolith/plumbing/analysis/SurgicalMender.js.map +1 -0
- package/dist/monolith/plumbing/analysis/TestService.js +104 -0
- package/dist/monolith/plumbing/analysis/TestService.js.map +1 -0
- package/dist/monolith/plumbing/filesystem/FileService.js +406 -0
- package/dist/monolith/plumbing/filesystem/FileService.js.map +1 -0
- package/dist/monolith/plumbing/filesystem/PathResolver.js +26 -0
- package/dist/monolith/plumbing/filesystem/PathResolver.js.map +1 -0
- package/dist/monolith/plumbing/git/GitService.js +71 -0
- package/dist/monolith/plumbing/git/GitService.js.map +1 -0
- package/dist/monolith/plumbing/lsp/SymbolService.js +36 -0
- package/dist/monolith/plumbing/lsp/SymbolService.js.map +1 -0
- package/dist/monolith/plumbing/terminal/ProcessRegistry.js +31 -0
- package/dist/monolith/plumbing/terminal/ProcessRegistry.js.map +1 -0
- package/dist/monolith/plumbing/terminal/TerminalService.js +180 -0
- package/dist/monolith/plumbing/terminal/TerminalService.js.map +1 -0
- package/dist/monolith/plumbing/ui/DecorationService.js +54 -0
- package/dist/monolith/plumbing/ui/DecorationService.js.map +1 -0
- package/dist/monolith/plumbing/utils/ErrorUtils.js +11 -0
- package/dist/monolith/plumbing/utils/ErrorUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/JsonUtils.js +360 -0
- package/dist/monolith/plumbing/utils/JsonUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/PrefixTree.js +153 -0
- package/dist/monolith/plumbing/utils/PrefixTree.js.map +1 -0
- package/dist/monolith/plumbing/utils/RetryUtils.js +141 -0
- package/dist/monolith/plumbing/utils/RetryUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/StreamTagDetector.js +128 -0
- package/dist/monolith/plumbing/utils/StreamTagDetector.js.map +1 -0
- package/dist/monolith/plumbing/utils/StringUtils.js +97 -0
- package/dist/monolith/plumbing/utils/StringUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/TimeoutUtils.js +21 -0
- package/dist/monolith/plumbing/utils/TimeoutUtils.js.map +1 -0
- package/dist/monolith/runtime/MarieRuntime.js +354 -0
- package/dist/monolith/runtime/MarieRuntime.js.map +1 -0
- package/dist/monolith/runtime/RuntimeAdapterBase.js +59 -0
- package/dist/monolith/runtime/RuntimeAdapterBase.js.map +1 -0
- package/dist/monolith/runtime/providerFactory.js +11 -0
- package/dist/monolith/runtime/providerFactory.js.map +1 -0
- package/dist/monolith/runtime/types.js +2 -0
- package/dist/monolith/runtime/types.js.map +1 -0
- package/dist/monolith/services/HealthService.js +38 -0
- package/dist/monolith/services/HealthService.js.map +1 -0
- package/dist/monolith/services/JoyAutomationService.js +131 -0
- package/dist/monolith/services/JoyAutomationService.js.map +1 -0
- package/dist/monolith/services/JoyLogService.js +48 -0
- package/dist/monolith/services/JoyLogService.js.map +1 -0
- package/dist/monolith/services/JoyService.js +190 -0
- package/dist/monolith/services/JoyService.js.map +1 -0
- package/dist/monolith/services/MarieGhostService.js +168 -0
- package/dist/monolith/services/MarieGhostService.js.map +1 -0
- package/dist/monolith/services/MarieSCMProvider.js +41 -0
- package/dist/monolith/services/MarieSCMProvider.js.map +1 -0
- package/package.json +168 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as crypto from "crypto";
|
|
4
|
+
import { LintService } from "./LintService.js";
|
|
5
|
+
import { ComplexityService } from "./ComplexityService.js";
|
|
6
|
+
/**
|
|
7
|
+
* MARIE SENTINEL v3.1: THE GROUNDED GUARDIAN
|
|
8
|
+
* Improved accuracy in resolution, duplication, and graph fidelity.
|
|
9
|
+
*/
|
|
10
|
+
export class MarieSentinelService {
|
|
11
|
+
static ZONES = {
|
|
12
|
+
DOMAIN: "domain",
|
|
13
|
+
INFRASTRUCTURE: "infrastructure",
|
|
14
|
+
PLUMBING: "plumbing",
|
|
15
|
+
};
|
|
16
|
+
static STATE_FILE = ".marie/sentinel_state.json";
|
|
17
|
+
static async audit(workingDir, specificFile) {
|
|
18
|
+
const allFiles = await this.getAllFiles(workingDir);
|
|
19
|
+
const targetFiles = specificFile ? [specificFile] : allFiles;
|
|
20
|
+
const zoneViolations = [];
|
|
21
|
+
const circularDependencies = [];
|
|
22
|
+
const leakyAbstractions = [];
|
|
23
|
+
const duplication = [];
|
|
24
|
+
const toxicFiles = [];
|
|
25
|
+
// 1. Precise Dependency Graph & Semantic Content Maps
|
|
26
|
+
const dependencyGraph = new Map();
|
|
27
|
+
const semanticHashMap = new Map(); // Hash -> FilePath
|
|
28
|
+
for (const file of allFiles) {
|
|
29
|
+
const content = await fs.readFile(file, "utf8");
|
|
30
|
+
const relativePath = path.relative(workingDir, file);
|
|
31
|
+
// A. Semantic Duplication (Token-based hash to ignore naming/formatting)
|
|
32
|
+
const semanticHash = this.computeSemanticHash(content);
|
|
33
|
+
if (semanticHashMap.has(semanticHash)) {
|
|
34
|
+
const original = semanticHashMap.get(semanticHash);
|
|
35
|
+
if (original !== relativePath) {
|
|
36
|
+
duplication.push(`[Semantic Duplicate] ${relativePath} matches ${original}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
semanticHashMap.set(semanticHash, relativePath);
|
|
41
|
+
}
|
|
42
|
+
// B. Robust Import Extraction & Resolution
|
|
43
|
+
const rawImports = this.extractImports(content);
|
|
44
|
+
const resolvedImports = await Promise.all(rawImports.map(i => this.resolveImportDeep(i, file, workingDir)));
|
|
45
|
+
const validImports = resolvedImports.filter(Boolean);
|
|
46
|
+
dependencyGraph.set(relativePath, validImports);
|
|
47
|
+
// C. Target Analysis
|
|
48
|
+
if (targetFiles.includes(file)) {
|
|
49
|
+
await this.analyzeFile(file, workingDir, content, validImports, zoneViolations, leakyAbstractions, toxicFiles);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// 2. Cycle Detection (Global)
|
|
53
|
+
const cycles = this.detectCycles(dependencyGraph);
|
|
54
|
+
circularDependencies.push(...cycles);
|
|
55
|
+
// 3. Score Normalization & Ratchet
|
|
56
|
+
const lintErrors = await LintService.runLint(workingDir);
|
|
57
|
+
const entropyScore = (zoneViolations.length * 8) + // Weighted higher
|
|
58
|
+
(lintErrors.length * 1) +
|
|
59
|
+
(circularDependencies.length * 15) + // Structural rot is expensive
|
|
60
|
+
(toxicFiles.length * 6) +
|
|
61
|
+
(leakyAbstractions.length * 5) +
|
|
62
|
+
(duplication.length * 10); // DRY is law
|
|
63
|
+
const state = await this.loadState(workingDir);
|
|
64
|
+
const entropyDelta = entropyScore - state.lastEntropy;
|
|
65
|
+
await this.saveState(workingDir, {
|
|
66
|
+
lastEntropy: entropyScore,
|
|
67
|
+
history: [...state.history, { date: new Date().toISOString(), entropy: entropyScore }].slice(-20)
|
|
68
|
+
});
|
|
69
|
+
let stability = "Stable";
|
|
70
|
+
if (entropyScore > 30)
|
|
71
|
+
stability = "Toxic";
|
|
72
|
+
else if (entropyScore > 15)
|
|
73
|
+
stability = "Fragile";
|
|
74
|
+
else if (entropyScore > 7)
|
|
75
|
+
stability = "Fluid";
|
|
76
|
+
const report = {
|
|
77
|
+
timestamp: new Date().toISOString(),
|
|
78
|
+
zoneViolations,
|
|
79
|
+
circularDependencies,
|
|
80
|
+
leakyAbstractions,
|
|
81
|
+
duplication,
|
|
82
|
+
entropyScore,
|
|
83
|
+
entropyDelta,
|
|
84
|
+
stability,
|
|
85
|
+
hotspots: Array.from(new Set([...zoneViolations.map(v => v.split(" ")[1]), ...toxicFiles])).slice(0, 5),
|
|
86
|
+
quarantineCandidates: toxicFiles,
|
|
87
|
+
graphDefinition: this.generateMermaidGraph(dependencyGraph, zoneViolations),
|
|
88
|
+
passed: entropyScore < 20 && entropyDelta <= 0,
|
|
89
|
+
};
|
|
90
|
+
await this.writeToSentinelLog(workingDir, report);
|
|
91
|
+
return report;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Computes a "Semantic Hash" by tokenizing the code and stripping noise.
|
|
95
|
+
* This catches duplication even if variables are renamed (shallowly).
|
|
96
|
+
*/
|
|
97
|
+
static computeSemanticHash(content) {
|
|
98
|
+
const tokens = content
|
|
99
|
+
.replace(/\/\/.*$/gm, '') // Strip line comments
|
|
100
|
+
.replace(/\/\*[\s\S]*?\*\//g, '') // Strip block comments
|
|
101
|
+
.replace(/\s+/g, ' ') // Normalize whitespace
|
|
102
|
+
.replace(/\b(const|let|var)\s+\w+\b/g, 'VAR') // Normalize variable declarations
|
|
103
|
+
.replace(/\bfunction\s+\w+\b/g, 'FUNC') // Normalize function names
|
|
104
|
+
.trim();
|
|
105
|
+
return crypto.createHash('sha256').update(tokens).digest('hex');
|
|
106
|
+
}
|
|
107
|
+
static async resolveImportDeep(imp, sourceFile, workingDir) {
|
|
108
|
+
if (!imp.startsWith("."))
|
|
109
|
+
return null; // Ignore external for now
|
|
110
|
+
const baseDir = path.dirname(sourceFile);
|
|
111
|
+
const candidatePaths = [
|
|
112
|
+
path.resolve(baseDir, imp),
|
|
113
|
+
path.resolve(baseDir, `${imp}.ts`),
|
|
114
|
+
path.resolve(baseDir, `${imp}.tsx`),
|
|
115
|
+
path.resolve(baseDir, `${imp}.js`),
|
|
116
|
+
path.resolve(baseDir, imp, "index.ts"),
|
|
117
|
+
path.resolve(baseDir, imp, "index.js"),
|
|
118
|
+
];
|
|
119
|
+
for (const p of candidatePaths) {
|
|
120
|
+
try {
|
|
121
|
+
const stats = await fs.stat(p);
|
|
122
|
+
if (stats.isFile()) {
|
|
123
|
+
return path.relative(workingDir, p);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
static async analyzeFile(file, workingDir, content, resolvedImports, zoneViolations, leakyAbstractions, toxicFiles) {
|
|
133
|
+
const relativePath = path.relative(workingDir, file);
|
|
134
|
+
const zone = this.getZone(relativePath);
|
|
135
|
+
if (!zone)
|
|
136
|
+
return;
|
|
137
|
+
// A. Real Zone Verification (based on RESOLVED paths)
|
|
138
|
+
for (const impPath of resolvedImports) {
|
|
139
|
+
const impZone = this.getZone(impPath);
|
|
140
|
+
if (!impZone)
|
|
141
|
+
continue;
|
|
142
|
+
if (zone === this.ZONES.DOMAIN && impZone !== this.ZONES.DOMAIN) {
|
|
143
|
+
zoneViolations.push(`[Purity Breach] ${relativePath} -> ${impPath} (${impZone})`);
|
|
144
|
+
}
|
|
145
|
+
if (zone === this.ZONES.INFRASTRUCTURE && impZone === this.ZONES.PLUMBING) {
|
|
146
|
+
zoneViolations.push(`[Architecture Leak] ${relativePath} -> ${impPath} (Infrastructure cannot use Plumbing)`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// B. Purity Scan (System Types in Domain)
|
|
150
|
+
if (zone === this.ZONES.DOMAIN) {
|
|
151
|
+
const systemKeywords = /\b(fs|path|os|vscode|express|React|HTMLElement|Buffer|process|window|document)\b/;
|
|
152
|
+
if (systemKeywords.test(content)) {
|
|
153
|
+
leakyAbstractions.push(`[System Leak] ${relativePath} references non-domain types.`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// C. Complexity Guard
|
|
157
|
+
const metrics = await ComplexityService.analyze(file);
|
|
158
|
+
if (metrics.cyclomaticComplexity > 20 || metrics.clutterLevel === "Toxic") {
|
|
159
|
+
toxicFiles.push(relativePath);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
static getZone(filePath) {
|
|
163
|
+
if (filePath.includes("src/domain") || filePath.includes("/domain/"))
|
|
164
|
+
return this.ZONES.DOMAIN;
|
|
165
|
+
if (filePath.includes("src/infrastructure") || filePath.includes("/infrastructure/"))
|
|
166
|
+
return this.ZONES.INFRASTRUCTURE;
|
|
167
|
+
if (filePath.includes("src/plumbing") || filePath.includes("/plumbing/"))
|
|
168
|
+
return this.ZONES.PLUMBING;
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
static extractImports(content) {
|
|
172
|
+
const imports = [];
|
|
173
|
+
const importRegex = /from\s+['"](.*?)['"]/g;
|
|
174
|
+
const requireRegex = /require\(['"](.*?)['"]\)/g;
|
|
175
|
+
let match;
|
|
176
|
+
while ((match = importRegex.exec(content)) !== null)
|
|
177
|
+
imports.push(match[1]);
|
|
178
|
+
while ((match = requireRegex.exec(content)) !== null)
|
|
179
|
+
imports.push(match[1]);
|
|
180
|
+
return Array.from(new Set(imports));
|
|
181
|
+
}
|
|
182
|
+
static detectCycles(graph) {
|
|
183
|
+
const cycles = [];
|
|
184
|
+
const visited = new Set();
|
|
185
|
+
const stack = new Set();
|
|
186
|
+
const dfs = (node, path) => {
|
|
187
|
+
visited.add(node);
|
|
188
|
+
stack.add(node);
|
|
189
|
+
for (const neighbor of graph.get(node) || []) {
|
|
190
|
+
if (stack.has(neighbor)) {
|
|
191
|
+
cycles.push(`🔄 ${path.join(" -> ")} -> ${neighbor}`);
|
|
192
|
+
}
|
|
193
|
+
else if (!visited.has(neighbor)) {
|
|
194
|
+
dfs(neighbor, [...path, neighbor]);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
stack.delete(node);
|
|
198
|
+
};
|
|
199
|
+
for (const node of graph.keys()) {
|
|
200
|
+
if (!visited.has(node))
|
|
201
|
+
dfs(node, [node]);
|
|
202
|
+
}
|
|
203
|
+
return cycles;
|
|
204
|
+
}
|
|
205
|
+
static generateMermaidGraph(graph, violations) {
|
|
206
|
+
let mermaid = "graph TD;\n";
|
|
207
|
+
const nodes = Array.from(graph.keys()).slice(0, 40);
|
|
208
|
+
nodes.forEach(node => {
|
|
209
|
+
const id = node.replace(/[^a-zA-Z0-9]/g, '_');
|
|
210
|
+
const name = path.basename(node);
|
|
211
|
+
graph.get(node)?.forEach(dep => {
|
|
212
|
+
const depId = dep.replace(/[^a-zA-Z0-9]/g, '_');
|
|
213
|
+
const isViolated = violations.some(v => v.includes(node) && v.includes(dep));
|
|
214
|
+
mermaid += ` ${id}[${name}] --> ${depId}[${path.basename(dep)}];\n`;
|
|
215
|
+
if (isViolated)
|
|
216
|
+
mermaid += ` style ${id} fill:#f96,stroke:#333,stroke-width:2px\n`;
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
return mermaid;
|
|
220
|
+
}
|
|
221
|
+
static async loadState(workingDir) {
|
|
222
|
+
try {
|
|
223
|
+
const content = await fs.readFile(path.join(workingDir, this.STATE_FILE), "utf8");
|
|
224
|
+
return JSON.parse(content);
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return { lastEntropy: 0, history: [] };
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
static async saveState(workingDir, state) {
|
|
231
|
+
const dir = path.join(workingDir, ".marie");
|
|
232
|
+
await fs.mkdir(dir, { recursive: true });
|
|
233
|
+
await fs.writeFile(path.join(workingDir, this.STATE_FILE), JSON.stringify(state, null, 2));
|
|
234
|
+
}
|
|
235
|
+
static async getAllFiles(dir) {
|
|
236
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
237
|
+
const files = await Promise.all(entries.map((entry) => {
|
|
238
|
+
const res = path.resolve(dir, entry.name);
|
|
239
|
+
if (res.includes("node_modules") || res.includes(".git") || res.includes("dist"))
|
|
240
|
+
return [];
|
|
241
|
+
return entry.isDirectory() ? this.getAllFiles(res) : res;
|
|
242
|
+
}));
|
|
243
|
+
return files.flat().filter(f => /\.(ts|tsx)$/.test(f));
|
|
244
|
+
}
|
|
245
|
+
static async writeToSentinelLog(workingDir, report) {
|
|
246
|
+
const logPath = path.join(workingDir, "SENTINEL.md");
|
|
247
|
+
const summary = `
|
|
248
|
+
# 🛡️ Sentinel Report: ${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}
|
|
249
|
+
|
|
250
|
+
**Stability**: ${report.stability}
|
|
251
|
+
**Entropy**: ${report.entropyScore} (${report.entropyDelta > 0 ? "⚠️ Regression" : "✅ Monotonic"})
|
|
252
|
+
**Ratchet**: ${report.entropyDelta > 0 ? "🚫 LOCKED" : "🔓 OPEN"}
|
|
253
|
+
|
|
254
|
+
## 📊 Metrics
|
|
255
|
+
- **Zoning Law**: ${report.zoneViolations.length} violations
|
|
256
|
+
- **Cyclic Rot**: ${report.circularDependencies.length} cycles
|
|
257
|
+
- **Duplication**: ${report.duplication.length} instances
|
|
258
|
+
- **Toxicity**: ${report.quarantineCandidates.length} hotspots
|
|
259
|
+
|
|
260
|
+
## 🗺️ Visual Architecture
|
|
261
|
+
\`\`\`mermaid
|
|
262
|
+
${report.graphDefinition}
|
|
263
|
+
\`\`\`
|
|
264
|
+
|
|
265
|
+
## 📜 High-Priority Alerts
|
|
266
|
+
${report.zoneViolations.slice(0, 5).map(v => `- ❌ ${v}`).join("\n")}
|
|
267
|
+
${report.circularDependencies.slice(0, 3).map(c => `- 🔄 ${c}`).join("\n")}
|
|
268
|
+
${report.duplication.slice(0, 3).map(d => `- 👯 ${d}`).join("\n")}
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
*Marie Sentinel v3.1 — Grounded Architectural Guardian*
|
|
272
|
+
`;
|
|
273
|
+
await fs.writeFile(logPath, summary);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=MarieSentinelService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarieSentinelService.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/analysis/MarieSentinelService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { LintService } from "./LintService.js";
|
|
2
|
+
import { TestService } from "./TestService.js";
|
|
3
|
+
import { ComplexityService } from "./ComplexityService.js";
|
|
4
|
+
import { SurgicalMender } from "./SurgicalMender.js";
|
|
5
|
+
import { MarieSentinelService } from "./MarieSentinelService.js";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import * as fs from "node:fs/promises";
|
|
8
|
+
/**
|
|
9
|
+
* PRODUCTION GUARDRAIL: Sub-Atomic Integrity Edition.
|
|
10
|
+
* Marie's final word on whether code is worthy of the Garden.
|
|
11
|
+
*/
|
|
12
|
+
export class QualityGuardrailService {
|
|
13
|
+
/**
|
|
14
|
+
* Evaluates a modified file against production-level quality standards with surgical precision.
|
|
15
|
+
*/
|
|
16
|
+
static async evaluate(cwd, filePath) {
|
|
17
|
+
const violations = [];
|
|
18
|
+
let passed = true;
|
|
19
|
+
let autoFixed = false;
|
|
20
|
+
let surgicalMends = 0;
|
|
21
|
+
// 1. 🛡️ SENTINEL V3.0 ARCHITECTURAL AUDIT
|
|
22
|
+
const sentinelReport = await MarieSentinelService.audit(cwd, filePath);
|
|
23
|
+
if (sentinelReport.zoneViolations.length > 0) {
|
|
24
|
+
violations.push(...sentinelReport.zoneViolations);
|
|
25
|
+
passed = false;
|
|
26
|
+
}
|
|
27
|
+
if (sentinelReport.circularDependencies.length > 0) {
|
|
28
|
+
violations.push(...sentinelReport.circularDependencies);
|
|
29
|
+
passed = false;
|
|
30
|
+
}
|
|
31
|
+
if (sentinelReport.leakyAbstractions.length > 0) {
|
|
32
|
+
violations.push(...sentinelReport.leakyAbstractions);
|
|
33
|
+
passed = false;
|
|
34
|
+
}
|
|
35
|
+
if (sentinelReport.duplication.length > 0) {
|
|
36
|
+
violations.push(...sentinelReport.duplication);
|
|
37
|
+
passed = false; // Duplication is a hard rejection in the Domain
|
|
38
|
+
}
|
|
39
|
+
// The Ratchet Protocol: Entropy must not rise
|
|
40
|
+
if (sentinelReport.entropyDelta > 0) {
|
|
41
|
+
violations.push(`RATCHET LOCK: Entropy increased by +${sentinelReport.entropyDelta}. Changes must maintain or lower entropy.`);
|
|
42
|
+
passed = false;
|
|
43
|
+
}
|
|
44
|
+
if (sentinelReport.quarantineCandidates.includes(path.relative(cwd, filePath))) {
|
|
45
|
+
violations.push(`TOXICITY ALERT: This file is a quarantine candidate. Immediate refactor required.`);
|
|
46
|
+
passed = false;
|
|
47
|
+
}
|
|
48
|
+
// 2. TYPE SOVEREIGNTY (Surgical Enforcement)
|
|
49
|
+
surgicalMends += await SurgicalMender.enforceTypeSovereignty(filePath);
|
|
50
|
+
// 3. LINTING & SURGICAL MENDING
|
|
51
|
+
let lintErrors = await LintService.runLintOnFile(cwd, filePath);
|
|
52
|
+
if (lintErrors.length > 0) {
|
|
53
|
+
// Step A: Attempt standard fixer (ESLint --fix)
|
|
54
|
+
const fixResult = await LintService.fixFile(cwd, filePath);
|
|
55
|
+
if (fixResult.success)
|
|
56
|
+
autoFixed = true;
|
|
57
|
+
// Step B: Apply high-precision surgical mending
|
|
58
|
+
const mendResult = await SurgicalMender.mend(filePath, lintErrors);
|
|
59
|
+
if (mendResult.mended) {
|
|
60
|
+
surgicalMends += mendResult.fixedCount;
|
|
61
|
+
// Re-scan after surgical intervention
|
|
62
|
+
lintErrors = await LintService.runLintOnFile(cwd, filePath);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const finalCriticalLint = lintErrors.filter(e => e.severity === "error");
|
|
66
|
+
if (finalCriticalLint.length > 0) {
|
|
67
|
+
passed = false;
|
|
68
|
+
violations.push(`Lint Regression: ${finalCriticalLint.length} persistent error(s) found.`);
|
|
69
|
+
}
|
|
70
|
+
// 4. SUB-ATOMIC COMPLEXITY
|
|
71
|
+
const complexity = await ComplexityService.analyze(filePath);
|
|
72
|
+
if (complexity.clutterLevel === "Toxic") {
|
|
73
|
+
passed = false;
|
|
74
|
+
violations.push(`Complexity Alert: Cyclomatic complexity (${complexity.cyclomaticComplexity}) exceeds production safety limits.`);
|
|
75
|
+
}
|
|
76
|
+
// Hard rejection for 'any' in new code
|
|
77
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
78
|
+
const anyUsage = (content.match(/:\s*any\b|as\s+any\b|<\s*any\s*>/gi) || []).length;
|
|
79
|
+
if (anyUsage > 0) {
|
|
80
|
+
passed = false;
|
|
81
|
+
violations.push(`Type Sovereignty Breach: ${anyUsage} instance(s) of 'any' detected. Be more precise.`);
|
|
82
|
+
}
|
|
83
|
+
// 5. TARGETED TEST REGRESSIONS
|
|
84
|
+
const testReport = await TestService.runTargetedTests(cwd, filePath);
|
|
85
|
+
if (testReport && !testReport.success) {
|
|
86
|
+
passed = false;
|
|
87
|
+
violations.push(`Test Regression: ${testReport.failedTests.length} related test(s) failed.`);
|
|
88
|
+
}
|
|
89
|
+
// Scoring (0-100)
|
|
90
|
+
let score = 100;
|
|
91
|
+
score -= sentinelReport.zoneViolations.length * 15;
|
|
92
|
+
score -= sentinelReport.circularDependencies.length * 20;
|
|
93
|
+
score -= sentinelReport.leakyAbstractions.length * 10;
|
|
94
|
+
score -= sentinelReport.duplication.length * 10;
|
|
95
|
+
score -= sentinelReport.entropyDelta > 0 ? 50 : 0; // Heavy penalty for regression
|
|
96
|
+
score -= finalCriticalLint.length * 10;
|
|
97
|
+
score -= complexity.cyclomaticComplexity > 10 ? 20 : 0;
|
|
98
|
+
score -= anyUsage * 5;
|
|
99
|
+
if (testReport && !testReport.success)
|
|
100
|
+
score -= 40;
|
|
101
|
+
score = Math.max(0, score);
|
|
102
|
+
return {
|
|
103
|
+
passed,
|
|
104
|
+
score,
|
|
105
|
+
violations,
|
|
106
|
+
autoFixed,
|
|
107
|
+
surgicalMends,
|
|
108
|
+
metrics: {
|
|
109
|
+
lintErrors: finalCriticalLint.length,
|
|
110
|
+
complexity: complexity.cyclomaticComplexity,
|
|
111
|
+
testsPassed: testReport ? testReport.success : null,
|
|
112
|
+
zoningHealthy: sentinelReport.zoneViolations.length === 0,
|
|
113
|
+
typeSovereignty: anyUsage === 0,
|
|
114
|
+
entropy: sentinelReport.entropyScore,
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=QualityGuardrailService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QualityGuardrailService.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/analysis/QualityGuardrailService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
/**
|
|
3
|
+
* SURGICAL MENDER: High-precision code remediation.
|
|
4
|
+
* Applies sub-atomic fixes to source code based on structured error data.
|
|
5
|
+
*/
|
|
6
|
+
export class SurgicalMender {
|
|
7
|
+
/**
|
|
8
|
+
* Applies surgical fixes to a file based on provided lint errors.
|
|
9
|
+
*/
|
|
10
|
+
static async mend(filePath, errors) {
|
|
11
|
+
let content = await fs.readFile(filePath, "utf-8");
|
|
12
|
+
let lines = content.split("\n");
|
|
13
|
+
let fixedCount = 0;
|
|
14
|
+
// Sort errors bottom-to-top to avoid offset issues
|
|
15
|
+
const sortedErrors = [...errors].sort((a, b) => b.line - a.line);
|
|
16
|
+
for (const err of sortedErrors) {
|
|
17
|
+
const lineIdx = err.line - 1;
|
|
18
|
+
if (lineIdx < 0 || lineIdx >= lines.length)
|
|
19
|
+
continue;
|
|
20
|
+
let line = lines[lineIdx];
|
|
21
|
+
const originalLine = line;
|
|
22
|
+
// Precision Fix 1: Unused Variables (Prefix with _)
|
|
23
|
+
if (err.message.includes("is defined but never used") || err.message.includes("unused")) {
|
|
24
|
+
// Try to find the variable name in the error or line
|
|
25
|
+
const varMatch = err.message.match(/'([^']+)'/);
|
|
26
|
+
const varName = varMatch ? varMatch[1] : null;
|
|
27
|
+
if (varName && line.includes(varName)) {
|
|
28
|
+
line = line.replace(new RegExp(`\\b${varName}\\b`), `_${varName}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Precision Fix 2: Prefer Const
|
|
32
|
+
if (err.ruleId === "prefer-const" || err.message.includes("should be a const")) {
|
|
33
|
+
line = line.replace(/\blet\b/, "const");
|
|
34
|
+
}
|
|
35
|
+
// Precision Fix 3: Missing Semicolon
|
|
36
|
+
if (err.ruleId === "semi" && err.message.includes("Missing semicolon")) {
|
|
37
|
+
if (!line.trim().endsWith(";")) {
|
|
38
|
+
line = line.trimEnd() + ";";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Precision Fix 4: No Var
|
|
42
|
+
if (err.ruleId === "no-var") {
|
|
43
|
+
line = line.replace(/\bvar\b/, "let");
|
|
44
|
+
}
|
|
45
|
+
if (line !== originalLine) {
|
|
46
|
+
lines[lineIdx] = line;
|
|
47
|
+
fixedCount++;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (fixedCount > 0) {
|
|
51
|
+
await fs.writeFile(filePath, lines.join("\n"), "utf-8");
|
|
52
|
+
return { mended: true, fixedCount };
|
|
53
|
+
}
|
|
54
|
+
return { mended: false, fixedCount: 0 };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Type-Sovereignty Guard: Strips 'as any' casts to force proper typing.
|
|
58
|
+
* (Intimidatingly precise enforcement)
|
|
59
|
+
*/
|
|
60
|
+
static async enforceTypeSovereignty(filePath) {
|
|
61
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
62
|
+
const sovereignContent = content.replace(/\s+as\s+any\b/g, " /* 🚩 Type sovereignty breach corrected */");
|
|
63
|
+
if (content !== sovereignContent) {
|
|
64
|
+
await fs.writeFile(filePath, sovereignContent, "utf-8");
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=SurgicalMender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SurgicalMender.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/analysis/SurgicalMender.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import * as fs from "node:fs/promises";
|
|
5
|
+
const execAsync = promisify(exec);
|
|
6
|
+
export class TestService {
|
|
7
|
+
/**
|
|
8
|
+
* Executes a test suite and parses the output into a structured Triage Report.
|
|
9
|
+
*/
|
|
10
|
+
static async runAndTriage(command, cwd = process.cwd()) {
|
|
11
|
+
try {
|
|
12
|
+
const { stdout, stderr } = await execAsync(command, { cwd });
|
|
13
|
+
const rawOutput = stdout + stderr;
|
|
14
|
+
const report = this.parseOutput(rawOutput);
|
|
15
|
+
let result = `# 🏥 Test Triage Report\n\n`;
|
|
16
|
+
result += `**Status**: ${report.success ? "Success ✨" : "Regressions Detected ⚠️"}\n`;
|
|
17
|
+
if (!report.success) {
|
|
18
|
+
result += `\n## ❌ Failing Tests\n`;
|
|
19
|
+
report.failedTests.forEach((t) => (result += `- \`${t}\`\n`));
|
|
20
|
+
result += `\n## 🔍 Top Errors\n`;
|
|
21
|
+
report.errors
|
|
22
|
+
.slice(0, 3)
|
|
23
|
+
.forEach((e) => (result += `\`\`\`\n${e}\n\`\`\`\n`));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
result += `\nAll tests passed across the target suite. The project remains stable. ✨\n`;
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
const rawOutput = (error.stdout || "") + (error.stderr || "");
|
|
32
|
+
const report = this.parseOutput(rawOutput);
|
|
33
|
+
if (report.failedTests.length > 0) {
|
|
34
|
+
// It failed because of test failures, not a crash
|
|
35
|
+
let result = `# 🏥 Test Triage Report\n\n`;
|
|
36
|
+
result += `**Status**: Regressions Detected ⚠️\n`;
|
|
37
|
+
result += `\n## ❌ Failing Tests\n`;
|
|
38
|
+
report.failedTests.forEach((t) => (result += `- \`${t}\`\n`));
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
return `Failed to execute test suite: ${error.message}\n${rawOutput}`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Discovers and runs tests related to a specific file.
|
|
46
|
+
*/
|
|
47
|
+
static async runTargetedTests(cwd, filePath) {
|
|
48
|
+
const fileName = path.basename(filePath, path.extname(filePath));
|
|
49
|
+
const testPattern = `**/${fileName}*test*`;
|
|
50
|
+
// Simple heuristic: look for neighboring test files or in a 'tests' folder
|
|
51
|
+
const possibleTestFiles = [
|
|
52
|
+
path.join(path.dirname(filePath), `${fileName}.test.ts`),
|
|
53
|
+
path.join(path.dirname(filePath), `${fileName}.spec.ts`),
|
|
54
|
+
path.join(path.dirname(filePath), "tests", `${fileName}.test.ts`),
|
|
55
|
+
path.join(cwd, "tests", `${fileName}.test.ts`),
|
|
56
|
+
];
|
|
57
|
+
for (const testFile of possibleTestFiles) {
|
|
58
|
+
try {
|
|
59
|
+
await fs.access(testFile);
|
|
60
|
+
const { stdout, stderr } = await execAsync(`npm test -- "${testFile}"`, { cwd });
|
|
61
|
+
return this.parseOutput(stdout + stderr);
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
if (e.code === "ENOENT")
|
|
65
|
+
continue;
|
|
66
|
+
return this.parseOutput((e.stdout || "") + (e.stderr || ""));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return null; // No targeted tests found
|
|
70
|
+
}
|
|
71
|
+
static parseOutput(output) {
|
|
72
|
+
const failedTests = [];
|
|
73
|
+
const errors = [];
|
|
74
|
+
const lines = output.split("\n");
|
|
75
|
+
let capturingError = false;
|
|
76
|
+
let currentError = "";
|
|
77
|
+
for (const line of lines) {
|
|
78
|
+
if (line.includes(" ❌ ") || line.includes(" FAIL ") || line.includes("FAILED")) {
|
|
79
|
+
failedTests.push(line.trim());
|
|
80
|
+
}
|
|
81
|
+
if (line.includes("AssertionError") || line.includes("Error: ")) {
|
|
82
|
+
capturingError = true;
|
|
83
|
+
currentError = line.trim() + "\n";
|
|
84
|
+
}
|
|
85
|
+
else if (capturingError) {
|
|
86
|
+
if (line.trim() === "" || line.startsWith(" at ")) {
|
|
87
|
+
currentError += line + "\n";
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
errors.push(currentError.trim());
|
|
91
|
+
capturingError = false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
success: failedTests.length === 0 && output.toLowerCase().includes("pass"),
|
|
97
|
+
totalTests: lines.length,
|
|
98
|
+
failedTests,
|
|
99
|
+
errors,
|
|
100
|
+
rawOutput: output,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=TestService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestService.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/analysis/TestService.ts"],"names":[],"mappings":"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"}
|