ruvnet-kb-first 6.1.0 → 6.2.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.
Files changed (3) hide show
  1. package/SKILL.md +44 -6
  2. package/package.json +1 -1
  3. package/src/mcp-server.js +418 -12
package/SKILL.md CHANGED
@@ -1,13 +1,51 @@
1
- Updated: 2026-01-02 10:15:00 EST | Version 6.0.0
1
+ Updated: 2026-01-02 10:35:00 EST | Version 6.2.0
2
2
  Created: 2026-01-01 15:00:00 EST
3
3
 
4
- # RuvNet KB-First Application Builder v6.0
4
+ # RuvNet KB-First Application Builder v6.2
5
5
 
6
- ## Score-Driven Architecture: Scoring IS Enforcement
6
+ ## Score-Driven Architecture: Scoring IS Enforcement + UX Excellence
7
7
 
8
- **Version:** 6.0.0
8
+ **Version:** 6.2.0
9
9
  **NPM Package:** `ruvnet-kb-first`
10
- **Philosophy:** Every operation requires baseline scoring. Every change shows delta. Negative delta BLOCKS progress. No shortcuts.
10
+ **Philosophy:** Every operation requires baseline scoring. Every change shows delta. Negative delta BLOCKS progress. No shortcuts. **NEW:** Applications must be excellent, not just functional.
11
+
12
+ ---
13
+
14
+ ## What's New in v6.2.0 - UX Excellence
15
+
16
+ | Feature | Description |
17
+ |---------|-------------|
18
+ | **UX Quality Dimension** | 7th KB dimension: Visual design, emotional appeal, user flow |
19
+ | **Phase 12: UX Quality Review** | Playwright-based end-user perspective audit |
20
+ | **`kb_first_ux_review` Tool** | Captures screenshots, checks versioning, critical review |
21
+ | **Version Display Check** | Verifies version in header/footer (major.minor.patch) |
22
+ | **Cache-Busting Check** | Ensures users see latest version, not cached content |
23
+ | **Critical Review Questions** | How good? How could it be better? Where falling down? What would excellent look like? |
24
+ | **Playwright Auto-Install** | Offers to install Playwright if not present |
25
+
26
+ ### The 6 MCP Tools (v6.2)
27
+
28
+ | Tool | Purpose | When to Use |
29
+ |------|---------|-------------|
30
+ | `kb_first_assess` | Score ALL dimensions (7 KB + 13 Phases) | **FIRST** - before any work |
31
+ | `kb_first_plan` | Generate enhancement plan with predictions | After assess, shows gaps |
32
+ | `kb_first_confirm` | User confirms readiness to proceed | Before execution |
33
+ | `kb_first_execute` | Execute plan phase by phase | After confirmation |
34
+ | `kb_first_verify` | Compare predicted vs actual, recursive until 98+ | After execution |
35
+ | `kb_first_ux_review` | Playwright-based visual quality audit | **NEW** - for UX excellence |
36
+
37
+ ### UX Quality Criteria (Scored in UX Review)
38
+
39
+ | Criterion | Weight | Checks |
40
+ |-----------|--------|--------|
41
+ | Version Display | 15% | Header/footer shows major.minor.patch |
42
+ | Cache Management | 10% | Version change detection, user notification |
43
+ | Visual Design Excellence | 20% | Typography, color, spacing, not generic AI look |
44
+ | Emotional Appeal | 15% | Creates confidence, celebrates success, softens errors |
45
+ | Loading States | 10% | Skeleton loaders, progress indicators, graceful |
46
+ | Error Handling UX | 10% | Clear messages, actionable, no technical jargon |
47
+ | User Flow | 10% | Intuitive navigation, clear CTAs, minimal friction |
48
+ | Accessibility | 10% | Keyboard nav, screen reader, contrast, focus |
11
49
 
12
50
  ---
13
51
 
@@ -22,7 +60,7 @@ Created: 2026-01-01 15:00:00 EST
22
60
  | **Baseline Requirement** | Cannot start work without establishing baseline |
23
61
  | **Automatic Refresh** | Baseline resets after each gate passage |
24
62
 
25
- ### The 4 MCP Tools
63
+ ### The Original 4 MCP Tools (v6.0)
26
64
 
27
65
  | Tool | Purpose | When to Use |
28
66
  |------|---------|-------------|
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ruvnet-kb-first",
3
- "version": "6.1.0",
3
+ "version": "6.2.0",
4
4
  "description": "RuvNet KB-First Application Builder - Build intelligent applications on expert knowledge",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/mcp-server.js CHANGED
@@ -1,20 +1,22 @@
1
1
  /**
2
2
  * RuvNet KB-First MCP Server - Granular Score-Driven Architecture
3
- * Version 6.1.0
3
+ * Version 6.2.0
4
4
  *
5
5
  * PHILOSOPHY: Granular scoring drives discipline.
6
- * - Score each KB dimension 1-100 (completeness, depth, comprehensiveness, accuracy, freshness)
7
- * - Score each phase readiness 1-100
6
+ * - Score each KB dimension 1-100 (completeness, depth, comprehensiveness, accuracy, freshness, attribution, ux_quality)
7
+ * - Score each phase readiness 1-100 (including Phase 12: UX Quality Review)
8
8
  * - Generate enhancement plan based on gaps
9
9
  * - User confirms before execution
10
10
  * - Post-verify: did we hit predicted scores?
11
+ * - Playwright UX Review: Visual quality audit from end-user perspective
11
12
  *
12
- * 5 Tools:
13
- * 1. kb_first_assess - Score ALL dimensions (KB quality + phase readiness)
14
- * 2. kb_first_plan - Generate enhancement plan with predicted improvements
15
- * 3. kb_first_confirm - User confirms readiness, locks in plan
16
- * 4. kb_first_execute - Execute plan phase by phase
17
- * 5. kb_first_verify - Post-verification: predicted vs actual, identify gaps
13
+ * 6 Tools:
14
+ * 1. kb_first_assess - Score ALL dimensions (KB quality + phase readiness)
15
+ * 2. kb_first_plan - Generate enhancement plan with predicted improvements
16
+ * 3. kb_first_confirm - User confirms readiness, locks in plan
17
+ * 4. kb_first_execute - Execute plan phase by phase
18
+ * 5. kb_first_verify - Post-verification: predicted vs actual, identify gaps
19
+ * 6. kb_first_ux_review - Playwright-based UX quality audit with screenshots
18
20
  *
19
21
  * Usage:
20
22
  * npx ruvnet-kb-first mcp
@@ -26,7 +28,7 @@ import { globSync } from 'glob';
26
28
 
27
29
  const MCP_VERSION = '0.1.0';
28
30
  const SERVER_NAME = 'ruvnet-kb-first';
29
- const SERVER_VERSION = '6.1.0';
31
+ const SERVER_VERSION = '6.2.0';
30
32
 
31
33
  /**
32
34
  * KB Quality Dimensions (each scored 1-100)
@@ -61,6 +63,11 @@ const KB_DIMENSIONS = {
61
63
  name: 'Attribution',
62
64
  description: 'Are sources and experts properly cited?',
63
65
  weight: 10
66
+ },
67
+ ux_quality: {
68
+ name: 'UX Quality',
69
+ description: 'Is the user experience excellent? Visual design, emotional appeal, user flow, versioning display, loading states, error handling, accessibility.',
70
+ weight: 15
64
71
  }
65
72
  };
66
73
 
@@ -119,6 +126,21 @@ const PHASES = {
119
126
  11: {
120
127
  name: 'Deployment',
121
128
  criteria: ['Infrastructure ready', 'Environments configured', 'CI/CD built', 'Migrations run', 'Monitoring active', 'Go-live complete']
129
+ },
130
+ 12: {
131
+ name: 'UX Quality Review',
132
+ criteria: [
133
+ 'Version displayed in header/footer (major.minor.patch)',
134
+ 'Cache-busting implemented with version notifications',
135
+ 'Visual design excellence (not just functional)',
136
+ 'Emotional appeal and user psychology considered',
137
+ 'Loading states are elegant',
138
+ 'Error messages are helpful and actionable',
139
+ 'User flow is intuitive and compelling',
140
+ 'Playwright screenshots reviewed and critiqued',
141
+ 'Accessibility verified (WCAG 2.1 AA)',
142
+ 'Mobile responsiveness tested'
143
+ ]
122
144
  }
123
145
  };
124
146
 
@@ -221,6 +243,53 @@ This closes the loop and ensures you delivered what you promised.`,
221
243
  detailed: { type: 'boolean', description: 'Show detailed comparison', default: true }
222
244
  }
223
245
  }
246
+ },
247
+ {
248
+ name: 'kb_first_ux_review',
249
+ description: `Playwright-based UX Quality Audit - End-user perspective review.
250
+
251
+ Walks through the application as an end user, capturing screenshots.
252
+ Then critically reviews EACH screenshot:
253
+
254
+ For each screen:
255
+ - How good is this? (1-100 score)
256
+ - How could we make it better? (specific recommendations)
257
+ - Where is it falling down? (issues identified)
258
+ - What would EXCELLENT look like? (vision for improvement)
259
+ - Recommendations with priority
260
+
261
+ Also checks critical UX requirements:
262
+ - Version number displayed in header/footer (major.minor.patch)
263
+ - Cache-busting with version change notifications
264
+ - Loading states are elegant, not jarring
265
+ - Error messages are helpful and guide user to resolution
266
+ - Visual design creates emotional appeal, not just functional
267
+ - User psychology leveraged for compelling flow
268
+
269
+ This ensures the application isn't just functional—it's EXCELLENT.`,
270
+ inputSchema: {
271
+ type: 'object',
272
+ properties: {
273
+ appUrl: { type: 'string', description: 'URL of the running application to review' },
274
+ flows: {
275
+ type: 'array',
276
+ items: { type: 'string' },
277
+ description: 'User flows to test (e.g., ["login", "search", "checkout"])',
278
+ default: ['homepage', 'main_flow']
279
+ },
280
+ screenshotDir: {
281
+ type: 'string',
282
+ description: 'Directory to save screenshots',
283
+ default: '.ruvector/ux-review'
284
+ },
285
+ criticalReview: {
286
+ type: 'boolean',
287
+ description: 'Perform deep critical review of each screenshot',
288
+ default: true
289
+ }
290
+ },
291
+ required: ['appUrl']
292
+ }
224
293
  }
225
294
  ];
226
295
 
@@ -351,6 +420,50 @@ function scoreKBDimensions(cwd) {
351
420
  improvement: attributionScore < 80 ? 'Add KB citations to code files' : 'Good attribution'
352
421
  };
353
422
 
423
+ // UX Quality: Based on presence of UX-related artifacts
424
+ let uxScore = 0;
425
+ const packagePath = join(cwd, 'package.json');
426
+ const uxReviewPath = join(cwd, '.ruvector', 'ux-review');
427
+
428
+ // Check for version in package.json
429
+ if (existsSync(packagePath)) {
430
+ try {
431
+ const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));
432
+ if (pkg.version) uxScore += 15; // Versioning exists
433
+ } catch {}
434
+ }
435
+
436
+ // Check for prior UX review
437
+ if (existsSync(uxReviewPath)) {
438
+ try {
439
+ const reviewFiles = readdirSync(uxReviewPath);
440
+ if (reviewFiles.length > 0) uxScore += 25; // UX review conducted
441
+ if (reviewFiles.some(f => f.includes('review-report'))) uxScore += 20; // Detailed review exists
442
+ } catch {}
443
+ }
444
+
445
+ // Check for accessibility considerations
446
+ if (existsSync(srcDir)) {
447
+ try {
448
+ const files = globSync('**/*.{tsx,jsx,html}', { cwd: srcDir });
449
+ let a11yScore = 0;
450
+ for (const f of files) {
451
+ try {
452
+ const content = readFileSync(join(srcDir, f), 'utf-8');
453
+ if (content.includes('aria-') || content.includes('role=')) a11yScore += 5;
454
+ if (content.includes('alt=') || content.includes('loading=')) a11yScore += 3;
455
+ } catch {}
456
+ }
457
+ uxScore += Math.min(40, a11yScore);
458
+ } catch {}
459
+ }
460
+
461
+ scores.ux_quality = {
462
+ score: Math.min(100, uxScore),
463
+ reason: uxScore >= 60 ? 'UX review conducted, accessibility present' : 'Limited UX review artifacts',
464
+ improvement: uxScore < 80 ? 'Run kb_first_ux_review for Playwright-based UX audit' : 'Good UX coverage'
465
+ };
466
+
354
467
  return scores;
355
468
  }
356
469
 
@@ -941,6 +1054,296 @@ async function handleVerify(cwd, args) {
941
1054
  return result;
942
1055
  }
943
1056
 
1057
+ /**
1058
+ * UX Review Criteria for critical evaluation
1059
+ */
1060
+ const UX_CRITERIA = {
1061
+ versioning: {
1062
+ name: 'Version Display',
1063
+ checks: ['Header shows version', 'Footer shows version', 'Format: major.minor.patch'],
1064
+ weight: 15
1065
+ },
1066
+ caching: {
1067
+ name: 'Cache Management',
1068
+ checks: ['Version change detection', 'User notification on updates', 'Force refresh capability'],
1069
+ weight: 10
1070
+ },
1071
+ visual_design: {
1072
+ name: 'Visual Design Excellence',
1073
+ checks: ['Professional typography', 'Cohesive color palette', 'Proper spacing/hierarchy', 'Not generic AI aesthetic'],
1074
+ weight: 20
1075
+ },
1076
+ emotional_appeal: {
1077
+ name: 'Emotional Appeal',
1078
+ checks: ['Creates confidence', 'Guides without confusion', 'Celebrates success states', 'Softens error states'],
1079
+ weight: 15
1080
+ },
1081
+ loading_states: {
1082
+ name: 'Loading States',
1083
+ checks: ['Skeleton loaders present', 'Progress indicators', 'No jarring transitions', 'Graceful degradation'],
1084
+ weight: 10
1085
+ },
1086
+ error_handling: {
1087
+ name: 'Error Handling UX',
1088
+ checks: ['Clear error messages', 'Actionable next steps', 'Recovery paths provided', 'No technical jargon'],
1089
+ weight: 10
1090
+ },
1091
+ user_flow: {
1092
+ name: 'User Flow',
1093
+ checks: ['Intuitive navigation', 'Clear call-to-actions', 'Logical progression', 'Minimal friction'],
1094
+ weight: 10
1095
+ },
1096
+ accessibility: {
1097
+ name: 'Accessibility',
1098
+ checks: ['Keyboard navigation', 'Screen reader compatible', 'Color contrast', 'Focus indicators'],
1099
+ weight: 10
1100
+ }
1101
+ };
1102
+
1103
+ /**
1104
+ * Detect available frontend-design skills
1105
+ */
1106
+ function detectFrontendDesignSkills() {
1107
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '';
1108
+ const skillsDir = join(homeDir, '.claude', 'skills');
1109
+ const skills = {
1110
+ preferred: null,
1111
+ available: [],
1112
+ recommendation: null
1113
+ };
1114
+
1115
+ // Check for frontend-design-Stu (preferred)
1116
+ if (existsSync(join(skillsDir, 'frontend-design-Stu.md'))) {
1117
+ skills.preferred = 'frontend-design-Stu';
1118
+ skills.available.push('frontend-design-Stu');
1119
+ }
1120
+
1121
+ // Check for frontend-design
1122
+ if (existsSync(join(skillsDir, 'frontend-design.md'))) {
1123
+ if (!skills.preferred) {
1124
+ skills.preferred = 'frontend-design';
1125
+ }
1126
+ skills.available.push('frontend-design');
1127
+ }
1128
+
1129
+ // Generate recommendation if no skills found
1130
+ if (skills.available.length === 0) {
1131
+ skills.recommendation = {
1132
+ message: 'No frontend-design skill installed. For UX excellence, install the Anthropic frontend-design skill.',
1133
+ installation: 'Visit: https://github.com/anthropics/claude-code-plugins and install frontend-design plugin',
1134
+ benefit: 'Creates distinctive, production-grade interfaces that avoid generic AI aesthetics'
1135
+ };
1136
+ }
1137
+
1138
+ return skills;
1139
+ }
1140
+
1141
+ /**
1142
+ * Handle UX Review with Playwright
1143
+ */
1144
+ async function handleUXReview(cwd, args) {
1145
+ const { appUrl, flows = ['homepage', 'main_flow'], screenshotDir = '.ruvector/ux-review', criticalReview = true } = args;
1146
+
1147
+ // Check for frontend-design skills
1148
+ const designSkills = detectFrontendDesignSkills();
1149
+
1150
+ // Check if Playwright is installed
1151
+ let playwrightAvailable = false;
1152
+ try {
1153
+ await import('playwright');
1154
+ playwrightAvailable = true;
1155
+ } catch {
1156
+ // Playwright not installed
1157
+ }
1158
+
1159
+ if (!playwrightAvailable) {
1160
+ return {
1161
+ action: 'PLAYWRIGHT_REQUIRED',
1162
+ status: 'INSTALLATION_NEEDED',
1163
+ message: 'Playwright is required for UX review but not installed.',
1164
+ installation: {
1165
+ command: 'npm install playwright && npx playwright install chromium',
1166
+ description: 'Installs Playwright and Chromium browser for screenshot capture',
1167
+ automated: 'Run this command, then re-run kb_first_ux_review'
1168
+ },
1169
+ designSkills: designSkills,
1170
+ alternative: {
1171
+ message: 'Alternatively, you can manually capture screenshots and place them in:',
1172
+ directory: join(cwd, screenshotDir),
1173
+ format: 'Name format: 01-homepage.png, 02-login.png, etc.',
1174
+ thenRun: 'Re-run kb_first_ux_review with criticalReview=true to analyze'
1175
+ }
1176
+ };
1177
+ }
1178
+
1179
+ // Create screenshot directory
1180
+ const screenshotPath = join(cwd, screenshotDir);
1181
+ if (!existsSync(screenshotPath)) {
1182
+ mkdirSync(screenshotPath, { recursive: true });
1183
+ }
1184
+
1185
+ // Capture screenshots using Playwright
1186
+ const screenshots = [];
1187
+ try {
1188
+ const { chromium } = await import('playwright');
1189
+ const browser = await chromium.launch();
1190
+ const context = await browser.newContext({
1191
+ viewport: { width: 1920, height: 1080 }
1192
+ });
1193
+ const page = await context.newPage();
1194
+
1195
+ // Navigate to app
1196
+ await page.goto(appUrl, { waitUntil: 'networkidle', timeout: 30000 });
1197
+
1198
+ // Capture initial screenshot
1199
+ const timestamp = Date.now();
1200
+ const homepagePath = join(screenshotPath, `01-homepage-${timestamp}.png`);
1201
+ await page.screenshot({ path: homepagePath, fullPage: true });
1202
+ screenshots.push({
1203
+ id: 1,
1204
+ name: 'Homepage',
1205
+ path: homepagePath,
1206
+ url: appUrl,
1207
+ viewport: 'desktop'
1208
+ });
1209
+
1210
+ // Check for version display
1211
+ const versionCheck = await page.evaluate(() => {
1212
+ const body = document.body.innerText;
1213
+ const versionPattern = /v?\d+\.\d+\.\d+/;
1214
+ const hasVersion = versionPattern.test(body);
1215
+ const header = document.querySelector('header')?.innerText || '';
1216
+ const footer = document.querySelector('footer')?.innerText || '';
1217
+ return {
1218
+ hasVersion,
1219
+ inHeader: versionPattern.test(header),
1220
+ inFooter: versionPattern.test(footer),
1221
+ foundVersion: body.match(versionPattern)?.[0] || null
1222
+ };
1223
+ });
1224
+
1225
+ // Mobile viewport screenshot
1226
+ await page.setViewportSize({ width: 375, height: 812 });
1227
+ await page.reload({ waitUntil: 'networkidle' });
1228
+ const mobilePath = join(screenshotPath, `02-homepage-mobile-${timestamp}.png`);
1229
+ await page.screenshot({ path: mobilePath, fullPage: true });
1230
+ screenshots.push({
1231
+ id: 2,
1232
+ name: 'Homepage Mobile',
1233
+ path: mobilePath,
1234
+ url: appUrl,
1235
+ viewport: 'mobile'
1236
+ });
1237
+
1238
+ await browser.close();
1239
+
1240
+ // Generate critical review for each screenshot
1241
+ const reviews = [];
1242
+ if (criticalReview) {
1243
+ for (const screenshot of screenshots) {
1244
+ reviews.push({
1245
+ screenshot: screenshot.name,
1246
+ path: screenshot.path,
1247
+ score: 0, // To be filled by Claude's analysis
1248
+ evaluation: {
1249
+ howGood: 'REQUIRES_VISUAL_ANALYSIS - Open screenshot and evaluate',
1250
+ couldBeBetter: [],
1251
+ fallingDown: [],
1252
+ excellentWouldLookLike: '',
1253
+ recommendations: []
1254
+ },
1255
+ criteria: Object.entries(UX_CRITERIA).map(([key, crit]) => ({
1256
+ name: crit.name,
1257
+ checks: crit.checks,
1258
+ score: 0,
1259
+ notes: 'Awaiting visual review'
1260
+ }))
1261
+ });
1262
+ }
1263
+ }
1264
+
1265
+ // Save review report
1266
+ const reviewReport = {
1267
+ timestamp: new Date().toISOString(),
1268
+ appUrl,
1269
+ versionCheck,
1270
+ screenshots,
1271
+ reviews,
1272
+ summary: {
1273
+ screenshotsCaptured: screenshots.length,
1274
+ versionDisplayed: versionCheck.hasVersion,
1275
+ versionInHeader: versionCheck.inHeader,
1276
+ versionInFooter: versionCheck.inFooter,
1277
+ requiresManualReview: true
1278
+ },
1279
+ criticalQuestions: [
1280
+ 'How good is this? (Score each screen 1-100)',
1281
+ 'How could we make it better?',
1282
+ 'Where is it falling down?',
1283
+ 'What would EXCELLENT look like?',
1284
+ 'What are the specific recommendations?'
1285
+ ]
1286
+ };
1287
+
1288
+ writeFileSync(join(screenshotPath, 'review-report.json'), JSON.stringify(reviewReport, null, 2));
1289
+
1290
+ return {
1291
+ action: 'UX_REVIEW_CAPTURED',
1292
+ status: 'SCREENSHOTS_READY',
1293
+ appUrl,
1294
+ versionCheck: {
1295
+ found: versionCheck.hasVersion,
1296
+ version: versionCheck.foundVersion,
1297
+ inHeader: versionCheck.inHeader,
1298
+ inFooter: versionCheck.inFooter,
1299
+ recommendation: !versionCheck.inHeader && !versionCheck.inFooter
1300
+ ? '⚠️ Version not displayed in header/footer - ADD version display immediately'
1301
+ : '✓ Version displayed'
1302
+ },
1303
+ screenshots: screenshots.map(s => ({
1304
+ name: s.name,
1305
+ path: s.path,
1306
+ viewport: s.viewport
1307
+ })),
1308
+ nextSteps: {
1309
+ step1: 'Open each screenshot file and visually inspect',
1310
+ step2: 'Score each screen 1-100 for overall UX quality',
1311
+ step3: 'Document: What works? What fails? What would excellent look like?',
1312
+ step4: 'Generate specific recommendations with priority (HIGH/MEDIUM/LOW)',
1313
+ step5: 'Update review-report.json with scores and findings',
1314
+ step6: 'Re-run kb_first_assess to update UX Quality scores'
1315
+ },
1316
+ criticalQuestions: reviewReport.criticalQuestions,
1317
+ criteria: Object.entries(UX_CRITERIA).map(([key, crit]) => ({
1318
+ name: crit.name,
1319
+ checks: crit.checks,
1320
+ weight: `${crit.weight}%`
1321
+ })),
1322
+ reportPath: join(screenshotPath, 'review-report.json'),
1323
+ designSkills: {
1324
+ available: designSkills.available,
1325
+ useSkill: designSkills.preferred || null,
1326
+ recommendation: designSkills.recommendation,
1327
+ implementationGuidance: designSkills.preferred
1328
+ ? `Use skill "${designSkills.preferred}" when implementing UX improvements. It creates distinctive, production-grade interfaces.`
1329
+ : 'Install frontend-design skill for UX improvements: https://github.com/anthropics/claude-code-plugins'
1330
+ }
1331
+ };
1332
+ } catch (error) {
1333
+ return {
1334
+ action: 'UX_REVIEW_ERROR',
1335
+ status: 'CAPTURE_FAILED',
1336
+ error: error.message,
1337
+ troubleshooting: {
1338
+ step1: 'Ensure the app is running at the specified URL',
1339
+ step2: 'Check if Playwright browsers are installed: npx playwright install chromium',
1340
+ step3: 'Try with a simpler URL first',
1341
+ step4: 'Manually capture screenshots and place in: ' + screenshotPath
1342
+ }
1343
+ };
1344
+ }
1345
+ }
1346
+
944
1347
  /**
945
1348
  * Get improvement task based on gap
946
1349
  */
@@ -983,6 +1386,8 @@ async function handleToolCall(toolName, args) {
983
1386
  return await handleExecute(cwd, args);
984
1387
  case 'kb_first_verify':
985
1388
  return await handleVerify(cwd, args);
1389
+ case 'kb_first_ux_review':
1390
+ return await handleUXReview(cwd, args);
986
1391
  default:
987
1392
  return { error: `Unknown tool: ${toolName}` };
988
1393
  }
@@ -1033,8 +1438,9 @@ async function handleMCPMessage(message) {
1033
1438
  */
1034
1439
  export async function startMCPServer(options = {}) {
1035
1440
  console.error(`RuvNet KB-First MCP Server v${SERVER_VERSION}`);
1036
- console.error('Architecture: Granular Score-Driven | Tools: 5 | Dimensions: 6 KB + 12 Phases');
1037
- console.error('Workflow: Assess → Plan → Confirm → Execute → Verify');
1441
+ console.error('Architecture: Granular Score-Driven | Tools: 6 | Dimensions: 7 KB + 13 Phases');
1442
+ console.error('Workflow: Assess → Plan → Confirm → Execute → Verify → UX Review');
1443
+ console.error('UX Review: Playwright-based visual quality audit from end-user perspective');
1038
1444
 
1039
1445
  let buffer = '';
1040
1446
  process.stdin.setEncoding('utf-8');