devintelligence 1.0.0 → 1.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/.env.example +14 -14
- package/LICENSE +22 -22
- package/README.md +146 -146
- package/bin/devintelligence.js +2481 -12
- package/bin/devintelligence.ts +244 -103
- package/dist/App.d.ts +3 -0
- package/dist/ai.js +366 -0
- package/dist/ai.js.map +7 -0
- package/dist/components/DeepAnalysisViews.d.ts +13 -0
- package/dist/components/MobileAndPlatformViews.d.ts +22 -0
- package/dist/components/OverviewAndExplorerViews.d.ts +20 -0
- package/dist/components/RepairAndGateViews.d.ts +25 -0
- package/dist/engine/aiEngine.d.ts +62 -0
- package/dist/engine/analyzerEngine.d.ts +19 -0
- package/dist/engine/repairEngine.d.ts +42 -0
- package/dist/engine.js +1541 -0
- package/dist/engine.js.map +7 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +2344 -0
- package/dist/index.js.map +7 -0
- package/dist/main.d.ts +1 -0
- package/dist/repair.js +2052 -0
- package/dist/repair.js.map +7 -0
- package/dist/src/App.d.ts +3 -0
- package/dist/src/components/DeepAnalysisViews.d.ts +13 -0
- package/dist/src/components/MobileAndPlatformViews.d.ts +22 -0
- package/dist/src/components/OverviewAndExplorerViews.d.ts +20 -0
- package/dist/src/components/RepairAndGateViews.d.ts +25 -0
- package/dist/src/engine/aiEngine.d.ts +62 -0
- package/dist/src/engine/analyzerEngine.d.ts +19 -0
- package/dist/src/engine/repairEngine.d.ts +42 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/main.d.ts +1 -0
- package/dist/src/types/devintelligence.d.ts +250 -0
- package/dist/types/devintelligence.d.ts +250 -0
- package/fixtures/django-analytics-service/requirements.txt +4 -4
- package/fixtures/django-analytics-service/settings.py +16 -16
- package/fixtures/express-api-gateway/package.json +14 -14
- package/fixtures/express-api-gateway/src/server.ts +16 -16
- package/fixtures/nextjs-saas-portal/package.json +21 -21
- package/fixtures/nextjs-saas-portal/src/app/dashboard/page.tsx +26 -26
- package/fixtures/rn-bare-fitness/android/build.gradle +19 -19
- package/fixtures/rn-bare-fitness/ios/Info.plist +14 -14
- package/fixtures/rn-bare-fitness/package.json +23 -23
- package/fixtures/rn-bare-fitness/src/WorkoutTracker.tsx +31 -31
- package/fixtures/rn-expo-commerce/android/app/build.gradle +20 -20
- package/fixtures/rn-expo-commerce/android/app/src/main/AndroidManifest.xml +21 -21
- package/fixtures/rn-expo-commerce/android/gradle.properties +6 -6
- package/fixtures/rn-expo-commerce/app.json +17 -17
- package/fixtures/rn-expo-commerce/babel.config.js +10 -10
- package/fixtures/rn-expo-commerce/ios/Podfile +13 -13
- package/fixtures/rn-expo-commerce/metro.config.js +7 -7
- package/fixtures/rn-expo-commerce/package.json +31 -31
- package/fixtures/rn-expo-commerce/src/components/LegacyPromoBanner.tsx +11 -11
- package/fixtures/rn-expo-commerce/src/screens/ProductFeedScreen.tsx +48 -48
- package/fixtures/rn-expo-commerce/src/services/api.ts +15 -15
- package/package.json +89 -77
- package/index.html +0 -21
- package/server.ts +0 -275
- package/src/App.tsx +0 -783
- package/src/components/DeepAnalysisViews.tsx +0 -526
- package/src/components/MobileAndPlatformViews.tsx +0 -625
- package/src/components/OverviewAndExplorerViews.tsx +0 -753
- package/src/components/RepairAndGateViews.tsx +0 -814
- package/src/engine/aiEngine.test.ts +0 -86
- package/src/engine/aiEngine.ts +0 -346
- package/src/engine/analyzerEngine.test.ts +0 -110
- package/src/engine/analyzerEngine.ts +0 -1579
- package/src/engine/repairEngine.ts +0 -545
- package/src/index.css +0 -44
- package/src/index.ts +0 -59
- package/src/main.tsx +0 -5
- package/src/types/devintelligence.ts +0 -310
- package/tsconfig.json +0 -28
- package/vite.config.ts +0 -22
|
@@ -1,814 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
Wrench,
|
|
4
|
-
RotateCcw,
|
|
5
|
-
CheckCircle2,
|
|
6
|
-
AlertTriangle,
|
|
7
|
-
XCircle,
|
|
8
|
-
Eye,
|
|
9
|
-
ShieldCheck,
|
|
10
|
-
History,
|
|
11
|
-
Server,
|
|
12
|
-
Terminal,
|
|
13
|
-
RefreshCw,
|
|
14
|
-
Play,
|
|
15
|
-
} from 'lucide-react';
|
|
16
|
-
import {
|
|
17
|
-
EnvironmentCheckItem,
|
|
18
|
-
ProjectIntelligenceReport,
|
|
19
|
-
QualityGateConfig,
|
|
20
|
-
RepairTier,
|
|
21
|
-
} from '../types/devintelligence.ts';
|
|
22
|
-
import { SeverityText } from './OverviewAndExplorerViews.tsx';
|
|
23
|
-
import { StatusIndicator } from './MobileAndPlatformViews.tsx';
|
|
24
|
-
|
|
25
|
-
interface RepairGateProps {
|
|
26
|
-
report: ProjectIntelligenceReport;
|
|
27
|
-
environmentChecks: EnvironmentCheckItem[];
|
|
28
|
-
mcpTools: { name: string; description: string; parameters: string[] }[];
|
|
29
|
-
onFixIssue: (issueId: string, allowReview?: boolean) => void;
|
|
30
|
-
onFixAllSafe: () => void;
|
|
31
|
-
onRollbackRepair: (repairId: string) => void;
|
|
32
|
-
onUpdateQualityGate: (cfg: Partial<QualityGateConfig>) => Promise<void>;
|
|
33
|
-
onRefreshEnvironment: () => Promise<void>;
|
|
34
|
-
onCallMcpTool: (toolName: string, args: Record<string, string>) => Promise<unknown>;
|
|
35
|
-
isBusy: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function AutoRepairCenterView({
|
|
39
|
-
report,
|
|
40
|
-
onFixIssue,
|
|
41
|
-
onFixAllSafe,
|
|
42
|
-
onRollbackRepair,
|
|
43
|
-
isBusy,
|
|
44
|
-
}: RepairGateProps) {
|
|
45
|
-
const [tierFilter, setTierFilter] = useState<'ALL' | RepairTier>('ALL');
|
|
46
|
-
const [selectedIssueId, setSelectedIssueId] = useState<string | null>(
|
|
47
|
-
report.issues[0]?.id || null
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
const filteredIssues = report.issues.filter((i) =>
|
|
51
|
-
tierFilter === 'ALL' ? true : i.repairTier === tierFilter
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
const activeIssue =
|
|
55
|
-
filteredIssues.find((i) => i.id === selectedIssueId) || filteredIssues[0] || null;
|
|
56
|
-
|
|
57
|
-
const safeFixableCount = report.issues.filter(
|
|
58
|
-
(i) => i.fixAvailable && i.repairTier === 'SAFE'
|
|
59
|
-
).length;
|
|
60
|
-
|
|
61
|
-
return (
|
|
62
|
-
<div className="space-y-8">
|
|
63
|
-
<div className="pb-5 border-b border-slate-800/80 flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4">
|
|
64
|
-
<div>
|
|
65
|
-
<h1 className="text-xl font-bold text-slate-100">
|
|
66
|
-
Automatic Repair Center & Backup Rollback Engine
|
|
67
|
-
</h1>
|
|
68
|
-
<p className="text-xs text-slate-400 mt-1">
|
|
69
|
-
Every repair creates a timestamped backup snapshot in <code className="font-mono text-slate-200">.devintelligence/backups/</code>, applies the patch on disk, and re-scans the repository to verify resolution.
|
|
70
|
-
</p>
|
|
71
|
-
</div>
|
|
72
|
-
|
|
73
|
-
<div className="flex flex-wrap items-center gap-3 shrink-0">
|
|
74
|
-
{safeFixableCount > 0 && (
|
|
75
|
-
<button
|
|
76
|
-
type="button"
|
|
77
|
-
disabled={isBusy}
|
|
78
|
-
onClick={onFixAllSafe}
|
|
79
|
-
className="inline-flex items-center gap-2 px-4 py-2 text-xs font-semibold text-white bg-blue-600 hover:bg-blue-500 disabled:opacity-50 rounded-lg transition-colors cursor-pointer whitespace-nowrap"
|
|
80
|
-
>
|
|
81
|
-
<Wrench className="w-3.5 h-3.5" />
|
|
82
|
-
<span>Fix All Safe Issues ({safeFixableCount})</span>
|
|
83
|
-
</button>
|
|
84
|
-
)}
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
|
|
88
|
-
{/* Interactive Tier Filter Segmented Control */}
|
|
89
|
-
<div className="flex flex-wrap items-center justify-between gap-4">
|
|
90
|
-
<div className="flex items-center gap-1 p-1 bg-slate-900 border border-slate-800 rounded-lg">
|
|
91
|
-
{(['ALL', 'SAFE', 'REVIEW_REQUIRED', 'RISKY'] as const).map((tier) => (
|
|
92
|
-
<button
|
|
93
|
-
key={tier}
|
|
94
|
-
type="button"
|
|
95
|
-
onClick={() => setTierFilter(tier)}
|
|
96
|
-
className={`px-3 py-1.5 text-xs font-medium rounded-md transition-colors cursor-pointer whitespace-nowrap ${
|
|
97
|
-
tierFilter === tier
|
|
98
|
-
? 'bg-blue-600 text-white'
|
|
99
|
-
: 'text-slate-400 hover:text-slate-100'
|
|
100
|
-
}`}
|
|
101
|
-
>
|
|
102
|
-
{tier === 'ALL'
|
|
103
|
-
? `All Findings (${report.issues.length})`
|
|
104
|
-
: `${tier} (${report.issues.filter((i) => i.repairTier === tier).length})`}
|
|
105
|
-
</button>
|
|
106
|
-
))}
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
|
-
<div className="text-xs text-slate-400 font-mono tabular-nums">
|
|
110
|
-
Applied Repairs in Session: {report.repairHistory.filter((r) => !r.rolledBack).length}
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
|
|
114
|
-
{/* Master-Detail Issue List & Before/After Code Diff Preview */}
|
|
115
|
-
{filteredIssues.length === 0 ? (
|
|
116
|
-
<div className="p-8 bg-slate-900/50 border border-slate-800 rounded-lg text-center space-y-2">
|
|
117
|
-
<CheckCircle2 className="w-6 h-6 text-emerald-400 mx-auto" />
|
|
118
|
-
<div className="text-sm font-semibold text-slate-100">
|
|
119
|
-
No Pending Issues in {tierFilter} Category
|
|
120
|
-
</div>
|
|
121
|
-
<p className="text-xs text-slate-400">
|
|
122
|
-
All matching issues have been repaired and verified. Check the Applied Repairs & Rollback log below to undo any modification.
|
|
123
|
-
</p>
|
|
124
|
-
</div>
|
|
125
|
-
) : (
|
|
126
|
-
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6 items-start">
|
|
127
|
-
{/* Left Column: Issue Queue */}
|
|
128
|
-
<div className="lg:col-span-5 bg-slate-900/70 border border-slate-800/80 rounded-lg divide-y divide-slate-800/70">
|
|
129
|
-
{filteredIssues.map((issue) => {
|
|
130
|
-
const isSelected = activeIssue?.id === issue.id;
|
|
131
|
-
return (
|
|
132
|
-
<button
|
|
133
|
-
key={issue.id}
|
|
134
|
-
type="button"
|
|
135
|
-
onClick={() => setSelectedIssueId(issue.id)}
|
|
136
|
-
className={`w-full p-4 text-left transition-colors cursor-pointer ${
|
|
137
|
-
isSelected ? 'bg-blue-950/35' : 'hover:bg-slate-800/50'
|
|
138
|
-
}`}
|
|
139
|
-
>
|
|
140
|
-
<div className="flex items-center justify-between gap-2 text-xs">
|
|
141
|
-
<SeverityText severity={issue.severity} />
|
|
142
|
-
<span className="font-mono text-slate-400">
|
|
143
|
-
{issue.repairTier} · {issue.confidence}%
|
|
144
|
-
</span>
|
|
145
|
-
</div>
|
|
146
|
-
<div className="mt-1.5 text-xs font-semibold text-slate-100">
|
|
147
|
-
{issue.title}
|
|
148
|
-
</div>
|
|
149
|
-
<div className="mt-1 text-[11px] font-mono text-slate-400 truncate">
|
|
150
|
-
{issue.filePath}:{issue.line}
|
|
151
|
-
</div>
|
|
152
|
-
</button>
|
|
153
|
-
);
|
|
154
|
-
})}
|
|
155
|
-
</div>
|
|
156
|
-
|
|
157
|
-
{/* Right Column: Before / After Comparison & Execute Fix */}
|
|
158
|
-
{activeIssue && (
|
|
159
|
-
<div className="lg:col-span-7 p-6 bg-slate-900/70 border border-slate-800/80 rounded-lg space-y-5">
|
|
160
|
-
<div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4 pb-4 border-b border-slate-800">
|
|
161
|
-
<div className="space-y-1">
|
|
162
|
-
<div className="flex items-center gap-2 text-xs font-mono text-slate-400">
|
|
163
|
-
<span>{activeIssue.ruleId}</span>
|
|
164
|
-
<span>·</span>
|
|
165
|
-
<span>{activeIssue.filePath}:{activeIssue.line}</span>
|
|
166
|
-
<span>·</span>
|
|
167
|
-
<span>Confidence {activeIssue.confidence}%</span>
|
|
168
|
-
</div>
|
|
169
|
-
<h2 className="text-base font-bold text-slate-100">
|
|
170
|
-
{activeIssue.title}
|
|
171
|
-
</h2>
|
|
172
|
-
</div>
|
|
173
|
-
|
|
174
|
-
{activeIssue.fixAvailable && (
|
|
175
|
-
<button
|
|
176
|
-
type="button"
|
|
177
|
-
disabled={isBusy}
|
|
178
|
-
onClick={() =>
|
|
179
|
-
onFixIssue(
|
|
180
|
-
activeIssue.id,
|
|
181
|
-
activeIssue.repairTier !== 'SAFE'
|
|
182
|
-
)
|
|
183
|
-
}
|
|
184
|
-
className="px-4 py-2 text-xs font-semibold text-white bg-blue-600 hover:bg-blue-500 disabled:opacity-50 rounded-lg shrink-0 cursor-pointer whitespace-nowrap"
|
|
185
|
-
>
|
|
186
|
-
{activeIssue.repairTier === 'SAFE'
|
|
187
|
-
? 'Apply Safe Fix Now'
|
|
188
|
-
: 'Approve & Execute Fix'}
|
|
189
|
-
</button>
|
|
190
|
-
)}
|
|
191
|
-
</div>
|
|
192
|
-
|
|
193
|
-
<div className="space-y-2 text-xs">
|
|
194
|
-
<div>
|
|
195
|
-
<span className="font-semibold text-slate-200">Root Cause: </span>
|
|
196
|
-
<span className="text-slate-300">{activeIssue.rootCause}</span>
|
|
197
|
-
</div>
|
|
198
|
-
<div>
|
|
199
|
-
<span className="font-semibold text-slate-200">Engineering Explanation: </span>
|
|
200
|
-
<span className="text-slate-400">{activeIssue.explanation}</span>
|
|
201
|
-
</div>
|
|
202
|
-
<div>
|
|
203
|
-
<span className="font-semibold text-blue-300">Recommended Repair: </span>
|
|
204
|
-
<span className="text-slate-200">{activeIssue.recommendedRepair}</span>
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
|
|
208
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
209
|
-
<div className="space-y-1.5">
|
|
210
|
-
<div className="text-xs font-semibold text-red-400">
|
|
211
|
-
Before (Current File State)
|
|
212
|
-
</div>
|
|
213
|
-
<pre className="p-3 bg-slate-950 border border-slate-800 rounded text-[11px] font-mono text-red-200/90 overflow-x-auto">
|
|
214
|
-
{activeIssue.beforeSnippet}
|
|
215
|
-
</pre>
|
|
216
|
-
</div>
|
|
217
|
-
|
|
218
|
-
<div className="space-y-1.5">
|
|
219
|
-
<div className="text-xs font-semibold text-emerald-400">
|
|
220
|
-
After (Proposed Safe Patch)
|
|
221
|
-
</div>
|
|
222
|
-
<pre className="p-3 bg-slate-950 border border-slate-800 rounded text-[11px] font-mono text-emerald-200/90 overflow-x-auto">
|
|
223
|
-
{activeIssue.afterSnippet}
|
|
224
|
-
</pre>
|
|
225
|
-
</div>
|
|
226
|
-
</div>
|
|
227
|
-
|
|
228
|
-
<div className="space-y-1.5">
|
|
229
|
-
<div className="text-xs font-semibold text-slate-300">
|
|
230
|
-
Unified Git Patch Preview
|
|
231
|
-
</div>
|
|
232
|
-
<pre className="p-3 bg-slate-950 border border-slate-800 rounded text-[11px] font-mono text-slate-300 overflow-x-auto">
|
|
233
|
-
{activeIssue.unifiedDiff}
|
|
234
|
-
</pre>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
)}
|
|
238
|
-
</div>
|
|
239
|
-
)}
|
|
240
|
-
|
|
241
|
-
{/* Applied Repairs & 1-Click Rollback Section */}
|
|
242
|
-
<div className="space-y-3 pt-4 border-t border-slate-800/80">
|
|
243
|
-
<h2 className="text-base font-semibold text-slate-100">
|
|
244
|
-
Applied Repairs & Backup Snapshots ({report.repairHistory.length})
|
|
245
|
-
</h2>
|
|
246
|
-
{report.repairHistory.length === 0 ? (
|
|
247
|
-
<div className="p-5 bg-slate-900/40 border border-slate-800 rounded-lg text-xs text-slate-400">
|
|
248
|
-
No file modifications have been executed on {report.name} yet. Click "Apply Safe Fix" above to test automatic backup, patching, verification, and rollback.
|
|
249
|
-
</div>
|
|
250
|
-
) : (
|
|
251
|
-
<div className="space-y-3">
|
|
252
|
-
{report.repairHistory.map((rec) => (
|
|
253
|
-
<div
|
|
254
|
-
key={rec.id}
|
|
255
|
-
className="p-4 bg-slate-900/70 border border-slate-800/80 rounded-lg flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"
|
|
256
|
-
>
|
|
257
|
-
<div className="space-y-1">
|
|
258
|
-
<div className="flex items-center gap-2 text-xs font-mono">
|
|
259
|
-
<span
|
|
260
|
-
className={
|
|
261
|
-
rec.rolledBack
|
|
262
|
-
? 'text-amber-400 font-semibold'
|
|
263
|
-
: 'text-emerald-400 font-semibold'
|
|
264
|
-
}
|
|
265
|
-
>
|
|
266
|
-
{rec.rolledBack ? 'ROLLED BACK' : 'VERIFIED FIXED'}
|
|
267
|
-
</span>
|
|
268
|
-
<span className="text-slate-500">·</span>
|
|
269
|
-
<span className="text-slate-300">{rec.filePath}</span>
|
|
270
|
-
<span className="text-slate-500">·</span>
|
|
271
|
-
<span className="text-slate-400">{new Date(rec.appliedAt).toLocaleTimeString()}</span>
|
|
272
|
-
</div>
|
|
273
|
-
<div className="text-sm font-semibold text-slate-100">{rec.issueTitle}</div>
|
|
274
|
-
<div className="text-[11px] font-mono text-slate-400">
|
|
275
|
-
Backup Snapshot: {rec.backupPath}
|
|
276
|
-
</div>
|
|
277
|
-
</div>
|
|
278
|
-
|
|
279
|
-
{!rec.rolledBack && (
|
|
280
|
-
<button
|
|
281
|
-
type="button"
|
|
282
|
-
disabled={isBusy}
|
|
283
|
-
onClick={() => onRollbackRepair(rec.id)}
|
|
284
|
-
className="inline-flex items-center gap-1.5 px-3.5 py-2 text-xs font-medium text-amber-300 bg-slate-800 hover:bg-slate-700 border border-slate-700 rounded-lg shrink-0 cursor-pointer whitespace-nowrap"
|
|
285
|
-
>
|
|
286
|
-
<RotateCcw className="w-3.5 h-3.5" />
|
|
287
|
-
<span>Rollback Repair</span>
|
|
288
|
-
</button>
|
|
289
|
-
)}
|
|
290
|
-
</div>
|
|
291
|
-
))}
|
|
292
|
-
</div>
|
|
293
|
-
)}
|
|
294
|
-
</div>
|
|
295
|
-
</div>
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export function VisualTestingView({ report }: RepairGateProps) {
|
|
300
|
-
return (
|
|
301
|
-
<div className="space-y-8">
|
|
302
|
-
<div className="pb-5 border-b border-slate-800/80">
|
|
303
|
-
<h1 className="text-xl font-bold text-slate-100">
|
|
304
|
-
Visual Regression & Responsive Viewport Testing
|
|
305
|
-
</h1>
|
|
306
|
-
<p className="text-xs text-slate-400 mt-1">
|
|
307
|
-
Engine: {report.visualTesting.engine} · Inspects layout overflow, broken/unoptimized image assets, and responsive geometry across Desktop (1440×900) and Mobile (390×844).
|
|
308
|
-
</p>
|
|
309
|
-
</div>
|
|
310
|
-
|
|
311
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
312
|
-
{report.visualTesting.viewportsTested.map((vp) => (
|
|
313
|
-
<div
|
|
314
|
-
key={vp.label}
|
|
315
|
-
className="p-5 bg-slate-900/70 border border-slate-800/80 rounded-lg space-y-4"
|
|
316
|
-
>
|
|
317
|
-
<div className="flex items-center justify-between border-b border-slate-800 pb-3">
|
|
318
|
-
<div>
|
|
319
|
-
<div className="text-sm font-semibold text-slate-100">{vp.label}</div>
|
|
320
|
-
<div className="text-xs font-mono text-slate-400">
|
|
321
|
-
{vp.width}px × {vp.height}px
|
|
322
|
-
</div>
|
|
323
|
-
</div>
|
|
324
|
-
<span
|
|
325
|
-
className={`text-xs font-mono font-semibold ${
|
|
326
|
-
vp.status === 'pass' ? 'text-emerald-400' : 'text-amber-400'
|
|
327
|
-
}`}
|
|
328
|
-
>
|
|
329
|
-
{vp.status === 'pass' ? 'PASS (0.0% diff)' : `WARNING (${vp.diffPercentage}% diff)`}
|
|
330
|
-
</span>
|
|
331
|
-
</div>
|
|
332
|
-
|
|
333
|
-
<div className="grid grid-cols-2 gap-3 text-xs font-mono tabular-nums">
|
|
334
|
-
<div className="p-3 bg-slate-950 rounded border border-slate-800/70">
|
|
335
|
-
<div className="text-slate-400">Horizontal Overflow</div>
|
|
336
|
-
<div className="mt-1 text-slate-200">
|
|
337
|
-
{vp.overflowDetected ? 'Detected' : 'None (0px)'}
|
|
338
|
-
</div>
|
|
339
|
-
</div>
|
|
340
|
-
<div className="p-3 bg-slate-950 rounded border border-slate-800/70">
|
|
341
|
-
<div className="text-slate-400">Unoptimized / Broken Images</div>
|
|
342
|
-
<div className="mt-1 text-slate-200">{vp.brokenImagesCount}</div>
|
|
343
|
-
</div>
|
|
344
|
-
<div className="p-3 bg-slate-950 rounded border border-slate-800/70">
|
|
345
|
-
<div className="text-slate-400">Runtime Console Risks</div>
|
|
346
|
-
<div className="mt-1 text-slate-200">{vp.consoleErrorsCount}</div>
|
|
347
|
-
</div>
|
|
348
|
-
<div className="p-3 bg-slate-950 rounded border border-slate-800/70">
|
|
349
|
-
<div className="text-slate-400">Network Failures</div>
|
|
350
|
-
<div className="mt-1 text-slate-200">{vp.networkFailuresCount}</div>
|
|
351
|
-
</div>
|
|
352
|
-
</div>
|
|
353
|
-
</div>
|
|
354
|
-
))}
|
|
355
|
-
</div>
|
|
356
|
-
|
|
357
|
-
<div className="space-y-3">
|
|
358
|
-
<h2 className="text-base font-semibold text-slate-100">
|
|
359
|
-
Visual & DOM Layout Regression Findings ({report.visualTesting.findings.length})
|
|
360
|
-
</h2>
|
|
361
|
-
{report.visualTesting.findings.length === 0 ? (
|
|
362
|
-
<div className="p-6 bg-slate-900/50 border border-slate-800 rounded-lg text-xs text-emerald-400">
|
|
363
|
-
Zero layout overflow, broken image, or icon baseline regressions detected.
|
|
364
|
-
</div>
|
|
365
|
-
) : (
|
|
366
|
-
<div className="space-y-3">
|
|
367
|
-
{report.visualTesting.findings.map((f, idx) => (
|
|
368
|
-
<div
|
|
369
|
-
key={idx}
|
|
370
|
-
className="p-4 bg-slate-900/70 border border-slate-800/80 rounded-lg space-y-1.5 text-xs"
|
|
371
|
-
>
|
|
372
|
-
<div className="font-mono text-blue-400">
|
|
373
|
-
Viewport {f.viewport} · Selector: {f.selector}
|
|
374
|
-
</div>
|
|
375
|
-
<div className="font-semibold text-slate-100">{f.description}</div>
|
|
376
|
-
<div className="text-slate-400">Recommendation: {f.recommendation}</div>
|
|
377
|
-
</div>
|
|
378
|
-
))}
|
|
379
|
-
</div>
|
|
380
|
-
)}
|
|
381
|
-
</div>
|
|
382
|
-
</div>
|
|
383
|
-
);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
export function QualityGateView({
|
|
387
|
-
report,
|
|
388
|
-
onUpdateQualityGate,
|
|
389
|
-
isBusy,
|
|
390
|
-
}: RepairGateProps) {
|
|
391
|
-
const [minCode, setMinCode] = useState(report.qualityGateConfig.minCodeQuality);
|
|
392
|
-
const [minDesign, setMinDesign] = useState(report.qualityGateConfig.minDesignQuality);
|
|
393
|
-
const [minPerf, setMinPerf] = useState(report.qualityGateConfig.minPerformanceScore);
|
|
394
|
-
const [maxCrit, setMaxCrit] = useState(report.qualityGateConfig.maxCriticalIssues);
|
|
395
|
-
const [maxSec, setMaxSec] = useState(report.qualityGateConfig.maxSecurityIssues);
|
|
396
|
-
|
|
397
|
-
async function handleSaveGate(e: React.FormEvent) {
|
|
398
|
-
e.preventDefault();
|
|
399
|
-
await onUpdateQualityGate({
|
|
400
|
-
minCodeQuality: Number(minCode),
|
|
401
|
-
minDesignQuality: Number(minDesign),
|
|
402
|
-
minPerformanceScore: Number(minPerf),
|
|
403
|
-
maxCriticalIssues: Number(maxCrit),
|
|
404
|
-
maxSecurityIssues: Number(maxSec),
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
const evalState = report.qualityGateEvaluation;
|
|
409
|
-
|
|
410
|
-
return (
|
|
411
|
-
<div className="space-y-8">
|
|
412
|
-
<div className="pb-5 border-b border-slate-800/80 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
|
413
|
-
<div>
|
|
414
|
-
<h1 className="text-xl font-bold text-slate-100">
|
|
415
|
-
Quality Gate & CI/CD Pipeline Integration
|
|
416
|
-
</h1>
|
|
417
|
-
<p className="text-xs text-slate-400 mt-1">
|
|
418
|
-
Enforces minimum engineering quality thresholds in pre-commit hooks and GitHub Actions with deterministic exit codes.
|
|
419
|
-
</p>
|
|
420
|
-
</div>
|
|
421
|
-
|
|
422
|
-
<div className="font-mono text-xs tabular-nums">
|
|
423
|
-
Gate Status:{' '}
|
|
424
|
-
<strong className={evalState.passed ? 'text-emerald-400' : 'text-red-400'}>
|
|
425
|
-
{evalState.passed ? 'PASSING (Exit Code 0)' : 'FAILING (Exit Code 1)'}
|
|
426
|
-
</strong>
|
|
427
|
-
</div>
|
|
428
|
-
</div>
|
|
429
|
-
|
|
430
|
-
{/* Evaluation Table */}
|
|
431
|
-
<div className="overflow-x-auto border border-slate-800/80 rounded-lg bg-slate-900/50">
|
|
432
|
-
<table className="w-full text-left border-collapse text-xs">
|
|
433
|
-
<thead>
|
|
434
|
-
<tr className="border-b border-slate-800 text-[11px] text-slate-400">
|
|
435
|
-
<th className="py-2.5 px-4">Quality Gate Metric</th>
|
|
436
|
-
<th className="py-2.5 px-4">Measured Value</th>
|
|
437
|
-
<th className="py-2.5 px-4">Required Threshold</th>
|
|
438
|
-
<th className="py-2.5 px-4">Evaluation</th>
|
|
439
|
-
</tr>
|
|
440
|
-
</thead>
|
|
441
|
-
<tbody className="divide-y divide-slate-800/60 font-mono tabular-nums">
|
|
442
|
-
{evalState.checks.map((c) => (
|
|
443
|
-
<tr key={c.name}>
|
|
444
|
-
<td className="py-3 px-4 font-sans font-semibold text-slate-100">{c.name}</td>
|
|
445
|
-
<td className="py-3 px-4 text-slate-200">{c.actual}</td>
|
|
446
|
-
<td className="py-3 px-4 text-slate-400">{c.threshold}</td>
|
|
447
|
-
<td className="py-3 px-4">
|
|
448
|
-
<span className={c.passed ? 'text-emerald-400' : 'text-red-400'}>
|
|
449
|
-
{c.passed ? 'PASS' : 'FAIL'}
|
|
450
|
-
</span>
|
|
451
|
-
</td>
|
|
452
|
-
</tr>
|
|
453
|
-
))}
|
|
454
|
-
</tbody>
|
|
455
|
-
</table>
|
|
456
|
-
</div>
|
|
457
|
-
|
|
458
|
-
{/* Configure Thresholds Form */}
|
|
459
|
-
<form
|
|
460
|
-
onSubmit={handleSaveGate}
|
|
461
|
-
className="p-5 bg-slate-900/70 border border-slate-800/80 rounded-lg space-y-4"
|
|
462
|
-
>
|
|
463
|
-
<div className="text-sm font-semibold text-slate-100">
|
|
464
|
-
Configure Quality Gate Thresholds for {report.name}
|
|
465
|
-
</div>
|
|
466
|
-
<div className="grid grid-cols-2 md:grid-cols-5 gap-4 text-xs">
|
|
467
|
-
<div>
|
|
468
|
-
<label htmlFor="gate-code" className="block text-slate-400 mb-1">
|
|
469
|
-
Min Code Quality
|
|
470
|
-
</label>
|
|
471
|
-
<input
|
|
472
|
-
id="gate-code"
|
|
473
|
-
type="number"
|
|
474
|
-
min={0}
|
|
475
|
-
max={100}
|
|
476
|
-
value={minCode}
|
|
477
|
-
onChange={(e) => setMinCode(Number(e.target.value))}
|
|
478
|
-
className="w-full px-3 py-2 font-mono bg-slate-950 border border-slate-800 rounded text-slate-100"
|
|
479
|
-
/>
|
|
480
|
-
</div>
|
|
481
|
-
<div>
|
|
482
|
-
<label htmlFor="gate-design" className="block text-slate-400 mb-1">
|
|
483
|
-
Min Design Score
|
|
484
|
-
</label>
|
|
485
|
-
<input
|
|
486
|
-
id="gate-design"
|
|
487
|
-
type="number"
|
|
488
|
-
min={0}
|
|
489
|
-
max={100}
|
|
490
|
-
value={minDesign}
|
|
491
|
-
onChange={(e) => setMinDesign(Number(e.target.value))}
|
|
492
|
-
className="w-full px-3 py-2 font-mono bg-slate-950 border border-slate-800 rounded text-slate-100"
|
|
493
|
-
/>
|
|
494
|
-
</div>
|
|
495
|
-
<div>
|
|
496
|
-
<label htmlFor="gate-perf" className="block text-slate-400 mb-1">
|
|
497
|
-
Min Performance
|
|
498
|
-
</label>
|
|
499
|
-
<input
|
|
500
|
-
id="gate-perf"
|
|
501
|
-
type="number"
|
|
502
|
-
min={0}
|
|
503
|
-
max={100}
|
|
504
|
-
value={minPerf}
|
|
505
|
-
onChange={(e) => setMinPerf(Number(e.target.value))}
|
|
506
|
-
className="w-full px-3 py-2 font-mono bg-slate-950 border border-slate-800 rounded text-slate-100"
|
|
507
|
-
/>
|
|
508
|
-
</div>
|
|
509
|
-
<div>
|
|
510
|
-
<label htmlFor="gate-crit" className="block text-slate-400 mb-1">
|
|
511
|
-
Max Critical Issues
|
|
512
|
-
</label>
|
|
513
|
-
<input
|
|
514
|
-
id="gate-crit"
|
|
515
|
-
type="number"
|
|
516
|
-
min={0}
|
|
517
|
-
max={50}
|
|
518
|
-
value={maxCrit}
|
|
519
|
-
onChange={(e) => setMaxCrit(Number(e.target.value))}
|
|
520
|
-
className="w-full px-3 py-2 font-mono bg-slate-950 border border-slate-800 rounded text-slate-100"
|
|
521
|
-
/>
|
|
522
|
-
</div>
|
|
523
|
-
<div>
|
|
524
|
-
<label htmlFor="gate-sec" className="block text-slate-400 mb-1">
|
|
525
|
-
Max Security Issues
|
|
526
|
-
</label>
|
|
527
|
-
<input
|
|
528
|
-
id="gate-sec"
|
|
529
|
-
type="number"
|
|
530
|
-
min={0}
|
|
531
|
-
max={50}
|
|
532
|
-
value={maxSec}
|
|
533
|
-
onChange={(e) => setMaxSec(Number(e.target.value))}
|
|
534
|
-
className="w-full px-3 py-2 font-mono bg-slate-950 border border-slate-800 rounded text-slate-100"
|
|
535
|
-
/>
|
|
536
|
-
</div>
|
|
537
|
-
</div>
|
|
538
|
-
<div className="flex justify-end">
|
|
539
|
-
<button
|
|
540
|
-
type="submit"
|
|
541
|
-
disabled={isBusy}
|
|
542
|
-
className="px-4 py-2 text-xs font-semibold text-white bg-blue-600 hover:bg-blue-500 rounded-lg cursor-pointer"
|
|
543
|
-
>
|
|
544
|
-
Save & Re-Evaluate Quality Gate
|
|
545
|
-
</button>
|
|
546
|
-
</div>
|
|
547
|
-
</form>
|
|
548
|
-
|
|
549
|
-
{/* CI/CD YAML & Pre-Commit Hook */}
|
|
550
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
551
|
-
<div className="space-y-2">
|
|
552
|
-
<div className="text-xs font-semibold text-slate-200">
|
|
553
|
-
GitHub Actions Workflow (.github/workflows/devintelligence-gate.yml)
|
|
554
|
-
</div>
|
|
555
|
-
<pre className="p-4 bg-slate-950 border border-slate-800 rounded-lg text-[11px] font-mono text-slate-300 overflow-x-auto">
|
|
556
|
-
{evalState.githubActionsYaml}
|
|
557
|
-
</pre>
|
|
558
|
-
</div>
|
|
559
|
-
|
|
560
|
-
<div className="space-y-2">
|
|
561
|
-
<div className="text-xs font-semibold text-slate-200">
|
|
562
|
-
Git Pre-Commit Hook (.git/hooks/pre-commit)
|
|
563
|
-
</div>
|
|
564
|
-
<pre className="p-4 bg-slate-950 border border-slate-800 rounded-lg text-[11px] font-mono text-slate-300 overflow-x-auto">
|
|
565
|
-
{evalState.preCommitHookScript}
|
|
566
|
-
</pre>
|
|
567
|
-
</div>
|
|
568
|
-
</div>
|
|
569
|
-
</div>
|
|
570
|
-
);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
export function ProjectHistoryView({
|
|
574
|
-
report,
|
|
575
|
-
onRollbackRepair,
|
|
576
|
-
isBusy,
|
|
577
|
-
}: RepairGateProps) {
|
|
578
|
-
return (
|
|
579
|
-
<div className="space-y-8">
|
|
580
|
-
<div className="pb-5 border-b border-slate-800/80">
|
|
581
|
-
<h1 className="text-xl font-bold text-slate-100">
|
|
582
|
-
Project Scan & Repair History ({report.name})
|
|
583
|
-
</h1>
|
|
584
|
-
<p className="text-xs text-slate-400 mt-1">
|
|
585
|
-
Isolated per-project audit trail of scan snapshots, score progression, and reversible file repairs.
|
|
586
|
-
</p>
|
|
587
|
-
</div>
|
|
588
|
-
|
|
589
|
-
<div className="space-y-3">
|
|
590
|
-
<h2 className="text-base font-semibold text-slate-100">
|
|
591
|
-
Scan History Snapshots ({report.scanHistory.length})
|
|
592
|
-
</h2>
|
|
593
|
-
<div className="overflow-x-auto border border-slate-800/80 rounded-lg bg-slate-900/50">
|
|
594
|
-
<table className="w-full text-left border-collapse text-xs font-mono tabular-nums">
|
|
595
|
-
<thead>
|
|
596
|
-
<tr className="border-b border-slate-800 text-[11px] font-sans text-slate-400">
|
|
597
|
-
<th className="py-2.5 px-4">Snapshot ID</th>
|
|
598
|
-
<th className="py-2.5 px-4">Timestamp</th>
|
|
599
|
-
<th className="py-2.5 px-4">Duration</th>
|
|
600
|
-
<th className="py-2.5 px-4">Issues</th>
|
|
601
|
-
<th className="py-2.5 px-4">Critical</th>
|
|
602
|
-
<th className="py-2.5 px-4">Overall Score</th>
|
|
603
|
-
</tr>
|
|
604
|
-
</thead>
|
|
605
|
-
<tbody className="divide-y divide-slate-800/60">
|
|
606
|
-
{report.scanHistory.map((snap) => (
|
|
607
|
-
<tr key={snap.id}>
|
|
608
|
-
<td className="py-3 px-4 text-slate-200">{snap.id}</td>
|
|
609
|
-
<td className="py-3 px-4 text-slate-400">
|
|
610
|
-
{new Date(snap.scannedAt).toLocaleTimeString()}
|
|
611
|
-
</td>
|
|
612
|
-
<td className="py-3 px-4 text-slate-300">{snap.durationMs}ms</td>
|
|
613
|
-
<td className="py-3 px-4 text-amber-400">{snap.totalIssues}</td>
|
|
614
|
-
<td className="py-3 px-4 text-red-400">{snap.criticalCount}</td>
|
|
615
|
-
<td className="py-3 px-4 font-bold text-blue-400">{snap.scores.overall}/100</td>
|
|
616
|
-
</tr>
|
|
617
|
-
))}
|
|
618
|
-
</tbody>
|
|
619
|
-
</table>
|
|
620
|
-
</div>
|
|
621
|
-
</div>
|
|
622
|
-
|
|
623
|
-
<div className="space-y-3">
|
|
624
|
-
<h2 className="text-base font-semibold text-slate-100">
|
|
625
|
-
Repair & Backup Ledger ({report.repairHistory.length})
|
|
626
|
-
</h2>
|
|
627
|
-
{report.repairHistory.length === 0 ? (
|
|
628
|
-
<div className="p-6 bg-slate-900/50 border border-slate-800 rounded-lg text-xs text-slate-400">
|
|
629
|
-
No repairs executed on {report.name} yet.
|
|
630
|
-
</div>
|
|
631
|
-
) : (
|
|
632
|
-
<div className="space-y-3">
|
|
633
|
-
{report.repairHistory.map((r) => (
|
|
634
|
-
<div
|
|
635
|
-
key={r.id}
|
|
636
|
-
className="p-4 bg-slate-900/70 border border-slate-800/80 rounded-lg flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"
|
|
637
|
-
>
|
|
638
|
-
<div className="space-y-1 text-xs">
|
|
639
|
-
<div className="font-semibold text-slate-100">{r.issueTitle}</div>
|
|
640
|
-
<div className="font-mono text-slate-400">
|
|
641
|
-
File: {r.filePath} · Status: {r.rolledBack ? 'Rolled Back' : 'Active'}
|
|
642
|
-
</div>
|
|
643
|
-
</div>
|
|
644
|
-
{!r.rolledBack && (
|
|
645
|
-
<button
|
|
646
|
-
type="button"
|
|
647
|
-
disabled={isBusy}
|
|
648
|
-
onClick={() => onRollbackRepair(r.id)}
|
|
649
|
-
className="px-3 py-1.5 text-xs font-medium text-amber-300 bg-slate-800 hover:bg-slate-700 rounded cursor-pointer whitespace-nowrap"
|
|
650
|
-
>
|
|
651
|
-
Undo & Restore Backup
|
|
652
|
-
</button>
|
|
653
|
-
)}
|
|
654
|
-
</div>
|
|
655
|
-
))}
|
|
656
|
-
</div>
|
|
657
|
-
)}
|
|
658
|
-
</div>
|
|
659
|
-
</div>
|
|
660
|
-
);
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
export function EnvironmentManagerView({
|
|
664
|
-
environmentChecks,
|
|
665
|
-
onRefreshEnvironment,
|
|
666
|
-
isBusy,
|
|
667
|
-
}: RepairGateProps) {
|
|
668
|
-
return (
|
|
669
|
-
<div className="space-y-8">
|
|
670
|
-
<div className="pb-5 border-b border-slate-800/80 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
|
671
|
-
<div>
|
|
672
|
-
<h1 className="text-xl font-bold text-slate-100">
|
|
673
|
-
Host Environment & Toolchain Manager
|
|
674
|
-
</h1>
|
|
675
|
-
<p className="text-xs text-slate-400 mt-1">
|
|
676
|
-
Live verification of Node.js, package managers, Python, JDK, Android SDK/adb, Gradle, and macOS/Xcode OS boundaries.
|
|
677
|
-
</p>
|
|
678
|
-
</div>
|
|
679
|
-
<button
|
|
680
|
-
type="button"
|
|
681
|
-
disabled={isBusy}
|
|
682
|
-
onClick={onRefreshEnvironment}
|
|
683
|
-
className="inline-flex items-center gap-2 px-4 py-2 text-xs font-semibold text-white bg-blue-600 hover:bg-blue-500 rounded-lg cursor-pointer whitespace-nowrap"
|
|
684
|
-
>
|
|
685
|
-
<RefreshCw className="w-3.5 h-3.5" />
|
|
686
|
-
<span>Re-Probe Host Binaries</span>
|
|
687
|
-
</button>
|
|
688
|
-
</div>
|
|
689
|
-
|
|
690
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
691
|
-
{environmentChecks.map((chk) => (
|
|
692
|
-
<div
|
|
693
|
-
key={chk.id}
|
|
694
|
-
className="p-4 bg-slate-900/70 border border-slate-800/80 rounded-lg space-y-2"
|
|
695
|
-
>
|
|
696
|
-
<div className="flex items-center justify-between gap-2">
|
|
697
|
-
<span className="text-sm font-semibold text-slate-100">{chk.name}</span>
|
|
698
|
-
<StatusIndicator status={chk.status} />
|
|
699
|
-
</div>
|
|
700
|
-
<div className="text-xs font-mono tabular-nums text-slate-300">
|
|
701
|
-
Detected: <strong>{chk.detectedVersion}</strong> · Required: {chk.requiredVersion}
|
|
702
|
-
</div>
|
|
703
|
-
<p className="text-xs text-slate-400 leading-relaxed">{chk.explanation}</p>
|
|
704
|
-
{chk.remediationCommand && (
|
|
705
|
-
<div className="p-2 bg-slate-950 border border-slate-800 rounded font-mono text-[11px] text-blue-300">
|
|
706
|
-
$ {chk.remediationCommand}
|
|
707
|
-
</div>
|
|
708
|
-
)}
|
|
709
|
-
</div>
|
|
710
|
-
))}
|
|
711
|
-
</div>
|
|
712
|
-
</div>
|
|
713
|
-
);
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
export function SettingsAndMcpView({
|
|
717
|
-
report,
|
|
718
|
-
mcpTools,
|
|
719
|
-
onCallMcpTool,
|
|
720
|
-
}: RepairGateProps) {
|
|
721
|
-
const [selectedTool, setSelectedTool] = useState<string>(
|
|
722
|
-
mcpTools[0]?.name || 'inspect_project'
|
|
723
|
-
);
|
|
724
|
-
const [mcpOutput, setMcpOutput] = useState<string>('');
|
|
725
|
-
const [runningMcp, setRunningMcp] = useState(false);
|
|
726
|
-
|
|
727
|
-
async function handleInvokeMcp(toolName: string) {
|
|
728
|
-
setSelectedTool(toolName);
|
|
729
|
-
setRunningMcp(true);
|
|
730
|
-
try {
|
|
731
|
-
const res = await onCallMcpTool(toolName, { projectId: report.id });
|
|
732
|
-
setMcpOutput(JSON.stringify(res, null, 2));
|
|
733
|
-
} finally {
|
|
734
|
-
setRunningMcp(false);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
return (
|
|
739
|
-
<div className="space-y-8">
|
|
740
|
-
<div className="pb-5 border-b border-slate-800/80">
|
|
741
|
-
<h1 className="text-xl font-bold text-slate-100">
|
|
742
|
-
MCP Agent Server, CLI Distribution & Workstation Settings
|
|
743
|
-
</h1>
|
|
744
|
-
<p className="text-xs text-slate-400 mt-1">
|
|
745
|
-
Core DEVINTELLIGENCE analysis and safe repairs run 100% locally without mandatory external AI API keys. Compatible AI agents can connect via the local Model Context Protocol (MCP) server.
|
|
746
|
-
</p>
|
|
747
|
-
</div>
|
|
748
|
-
|
|
749
|
-
{/* CLI Reference */}
|
|
750
|
-
<div className="p-5 bg-slate-900/70 border border-slate-800/80 rounded-lg space-y-3">
|
|
751
|
-
<div className="text-sm font-semibold text-slate-100">
|
|
752
|
-
Local CLI Commands (Executable via bin/devintelligence.ts)
|
|
753
|
-
</div>
|
|
754
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs font-mono text-slate-300">
|
|
755
|
-
<div className="p-2.5 bg-slate-950 border border-slate-800 rounded">
|
|
756
|
-
$ npx devintelligence init
|
|
757
|
-
</div>
|
|
758
|
-
<div className="p-2.5 bg-slate-950 border border-slate-800 rounded">
|
|
759
|
-
$ npx devintelligence scan --project={report.id}
|
|
760
|
-
</div>
|
|
761
|
-
<div className="p-2.5 bg-slate-950 border border-slate-800 rounded">
|
|
762
|
-
$ npx devintelligence doctor
|
|
763
|
-
</div>
|
|
764
|
-
<div className="p-2.5 bg-slate-950 border border-slate-800 rounded">
|
|
765
|
-
$ npx devintelligence fix --project={report.id}
|
|
766
|
-
</div>
|
|
767
|
-
</div>
|
|
768
|
-
</div>
|
|
769
|
-
|
|
770
|
-
{/* Interactive MCP Tool Server Console */}
|
|
771
|
-
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6 items-start">
|
|
772
|
-
<div className="lg:col-span-5 bg-slate-900/70 border border-slate-800/80 rounded-lg divide-y divide-slate-800/70">
|
|
773
|
-
<div className="px-4 py-3 text-xs font-semibold text-slate-200">
|
|
774
|
-
Exposed Local MCP Server Tools ({mcpTools.length})
|
|
775
|
-
</div>
|
|
776
|
-
{mcpTools.map((tool) => (
|
|
777
|
-
<div
|
|
778
|
-
key={tool.name}
|
|
779
|
-
className="p-3.5 flex items-center justify-between gap-3 hover:bg-slate-800/40"
|
|
780
|
-
>
|
|
781
|
-
<div className="min-w-0">
|
|
782
|
-
<div className="text-xs font-mono font-semibold text-blue-400">
|
|
783
|
-
{tool.name}
|
|
784
|
-
</div>
|
|
785
|
-
<div className="text-[11px] text-slate-400 mt-0.5">{tool.description}</div>
|
|
786
|
-
</div>
|
|
787
|
-
<button
|
|
788
|
-
type="button"
|
|
789
|
-
disabled={runningMcp}
|
|
790
|
-
onClick={() => handleInvokeMcp(tool.name)}
|
|
791
|
-
className="px-3 py-1.5 text-xs font-medium text-white bg-blue-600 hover:bg-blue-500 rounded shrink-0 cursor-pointer whitespace-nowrap"
|
|
792
|
-
>
|
|
793
|
-
Invoke
|
|
794
|
-
</button>
|
|
795
|
-
</div>
|
|
796
|
-
))}
|
|
797
|
-
</div>
|
|
798
|
-
|
|
799
|
-
<div className="lg:col-span-7 bg-slate-900/70 border border-slate-800/80 rounded-lg overflow-hidden">
|
|
800
|
-
<div className="px-4 py-3 border-b border-slate-800 flex items-center justify-between text-xs font-mono text-slate-300">
|
|
801
|
-
<span>MCP JSON-RPC Response ({selectedTool})</span>
|
|
802
|
-
<span>Target: {report.id}</span>
|
|
803
|
-
</div>
|
|
804
|
-
<pre className="p-4 bg-slate-950 text-xs font-mono text-emerald-300 overflow-x-auto min-h-[380px] max-h-[520px]">
|
|
805
|
-
{runningMcp
|
|
806
|
-
? 'Executing local MCP tool call...'
|
|
807
|
-
: mcpOutput ||
|
|
808
|
-
'// Click "Invoke" on any MCP tool on the left to execute it against the active project and inspect the real JSON-RPC payload.'}
|
|
809
|
-
</pre>
|
|
810
|
-
</div>
|
|
811
|
-
</div>
|
|
812
|
-
</div>
|
|
813
|
-
);
|
|
814
|
-
}
|