agentic-qe 2.1.0 → 2.1.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/agents/QXPartnerAgent.d.ts +40 -1
  3. package/dist/agents/QXPartnerAgent.d.ts.map +1 -1
  4. package/dist/agents/QXPartnerAgent.js +918 -19
  5. package/dist/agents/QXPartnerAgent.js.map +1 -1
  6. package/dist/core/memory/ReflexionMemoryAdapter.d.ts +109 -0
  7. package/dist/core/memory/ReflexionMemoryAdapter.d.ts.map +1 -0
  8. package/dist/core/memory/ReflexionMemoryAdapter.js +306 -0
  9. package/dist/core/memory/ReflexionMemoryAdapter.js.map +1 -0
  10. package/dist/core/memory/RuVectorPatternStore.d.ts +28 -0
  11. package/dist/core/memory/RuVectorPatternStore.d.ts.map +1 -1
  12. package/dist/core/memory/RuVectorPatternStore.js +70 -0
  13. package/dist/core/memory/RuVectorPatternStore.js.map +1 -1
  14. package/dist/core/memory/SparseVectorSearch.d.ts +55 -0
  15. package/dist/core/memory/SparseVectorSearch.d.ts.map +1 -0
  16. package/dist/core/memory/SparseVectorSearch.js +130 -0
  17. package/dist/core/memory/SparseVectorSearch.js.map +1 -0
  18. package/dist/core/memory/TieredCompression.d.ts +81 -0
  19. package/dist/core/memory/TieredCompression.d.ts.map +1 -0
  20. package/dist/core/memory/TieredCompression.js +270 -0
  21. package/dist/core/memory/TieredCompression.js.map +1 -0
  22. package/dist/core/memory/index.d.ts +6 -0
  23. package/dist/core/memory/index.d.ts.map +1 -1
  24. package/dist/core/memory/index.js +29 -1
  25. package/dist/core/memory/index.js.map +1 -1
  26. package/dist/mcp/handlers/chaos/chaos-inject-failure.d.ts +5 -0
  27. package/dist/mcp/handlers/chaos/chaos-inject-failure.d.ts.map +1 -1
  28. package/dist/mcp/handlers/chaos/chaos-inject-failure.js +36 -2
  29. package/dist/mcp/handlers/chaos/chaos-inject-failure.js.map +1 -1
  30. package/dist/mcp/handlers/chaos/chaos-inject-latency.d.ts +5 -0
  31. package/dist/mcp/handlers/chaos/chaos-inject-latency.d.ts.map +1 -1
  32. package/dist/mcp/handlers/chaos/chaos-inject-latency.js +36 -2
  33. package/dist/mcp/handlers/chaos/chaos-inject-latency.js.map +1 -1
  34. package/dist/types/qx.d.ts +74 -0
  35. package/dist/types/qx.d.ts.map +1 -1
  36. package/dist/types/qx.js.map +1 -1
  37. package/package.json +4 -1
@@ -16,12 +16,50 @@
16
16
  * - Integration with testability scoring
17
17
  * - Contextual recommendations generation
18
18
  */
19
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ var desc = Object.getOwnPropertyDescriptor(m, k);
22
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
23
+ desc = { enumerable: true, get: function() { return m[k]; } };
24
+ }
25
+ Object.defineProperty(o, k2, desc);
26
+ }) : (function(o, m, k, k2) {
27
+ if (k2 === undefined) k2 = k;
28
+ o[k2] = m[k];
29
+ }));
30
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
31
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
32
+ }) : function(o, v) {
33
+ o["default"] = v;
34
+ });
35
+ var __importStar = (this && this.__importStar) || (function () {
36
+ var ownKeys = function(o) {
37
+ ownKeys = Object.getOwnPropertyNames || function (o) {
38
+ var ar = [];
39
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
40
+ return ar;
41
+ };
42
+ return ownKeys(o);
43
+ };
44
+ return function (mod) {
45
+ if (mod && mod.__esModule) return mod;
46
+ var result = {};
47
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
48
+ __setModuleDefault(result, mod);
49
+ return result;
50
+ };
51
+ })();
19
52
  Object.defineProperty(exports, "__esModule", { value: true });
20
53
  exports.QXPartnerAgent = void 0;
21
54
  const BaseAgent_1 = require("./BaseAgent");
22
55
  const types_1 = require("../types");
23
56
  const playwright_1 = require("playwright");
57
+ const fs = __importStar(require("fs"));
58
+ const path = __importStar(require("path"));
59
+ const child_process_1 = require("child_process");
60
+ const util_1 = require("util");
24
61
  const qx_1 = require("../types/qx");
62
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
25
63
  class ConsoleLogger {
26
64
  info(message, ...args) {
27
65
  console.log(`[INFO] ${message}`, ...args);
@@ -264,14 +302,18 @@ class QXPartnerAgent extends BaseAgent_1.BaseAgent {
264
302
  const userNeeds = await this.analyzeUserNeeds(context, problemAnalysis);
265
303
  // 4. Analyze business needs
266
304
  const businessNeeds = await this.analyzeBusinessNeeds(context, problemAnalysis);
267
- // 5. Detect oracle problems
305
+ // 5. Analyze creativity - drawing inspiration from diverse domains
306
+ const creativityAnalysis = await this.analyzeCreativity(context, problemAnalysis);
307
+ // 6. Analyze design - exactness, intuitive, and counter-intuitive design
308
+ const designAnalysis = await this.analyzeDesign(context, problemAnalysis);
309
+ // 7. Detect oracle problems
268
310
  const oracleProblems = this.config.detectOracleProblems
269
311
  ? await this.detectOracleProblemsFromContext(context, userNeeds, businessNeeds)
270
312
  : [];
271
- // 6. Perform impact analysis
313
+ // 8. Perform impact analysis
272
314
  const impactAnalysis = await this.analyzeImpact(context, problemAnalysis);
273
- // 7. Apply heuristics
274
- const heuristics = await this.applyAllHeuristics(context, problemAnalysis, userNeeds, businessNeeds);
315
+ // 9. Apply heuristics
316
+ const heuristics = await this.applyAllHeuristics(context, problemAnalysis, userNeeds, businessNeeds, creativityAnalysis, designAnalysis);
275
317
  // 8. Integrate testability (if enabled)
276
318
  const testabilityIntegration = this.config.integrateTestability
277
319
  ? await this.integrateTestabilityScoring(params)
@@ -279,7 +321,7 @@ class QXPartnerAgent extends BaseAgent_1.BaseAgent {
279
321
  // 9. Generate recommendations
280
322
  const recommendations = await this.generateRecommendations(problemAnalysis, userNeeds, businessNeeds, oracleProblems, impactAnalysis, heuristics, testabilityIntegration);
281
323
  // 10. Calculate overall score
282
- const overallScore = this.calculateOverallQXScore(problemAnalysis, userNeeds, businessNeeds, impactAnalysis, heuristics);
324
+ const overallScore = this.calculateOverallQXScore(problemAnalysis, userNeeds, businessNeeds, creativityAnalysis, designAnalysis, impactAnalysis, heuristics);
283
325
  const grade = this.scoreToGrade(overallScore);
284
326
  const analysis = {
285
327
  overallScore,
@@ -289,6 +331,8 @@ class QXPartnerAgent extends BaseAgent_1.BaseAgent {
289
331
  problemAnalysis,
290
332
  userNeeds,
291
333
  businessNeeds,
334
+ creativityAnalysis,
335
+ designAnalysis,
292
336
  oracleProblems,
293
337
  impactAnalysis,
294
338
  heuristics,
@@ -300,8 +344,633 @@ class QXPartnerAgent extends BaseAgent_1.BaseAgent {
300
344
  await this.storeMemory(`qx-analysis:${target}`, analysis);
301
345
  const duration = Date.now() - startTime;
302
346
  this.logger.info(`QX analysis completed in ${duration}ms. Score: ${overallScore}/100 (${grade})`);
347
+ // Generate HTML report and auto-launch
348
+ try {
349
+ const reportPath = await this.generateHTMLReport(analysis);
350
+ this.logger.info(`HTML report generated: ${reportPath}`);
351
+ // Auto-launch browser
352
+ await this.launchReportInBrowser(reportPath);
353
+ this.logger.info(`Report launched in browser`);
354
+ }
355
+ catch (error) {
356
+ this.logger.warn(`Failed to generate/launch HTML report:`, error);
357
+ // Don't fail the analysis if report generation fails
358
+ }
303
359
  return analysis;
304
360
  }
361
+ /**
362
+ * Generate HTML report from QX analysis
363
+ */
364
+ async generateHTMLReport(analysis) {
365
+ const sanitizedTarget = analysis.target.replace(/[^a-zA-Z0-9]/g, '-').substring(0, 50);
366
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').substring(0, 19);
367
+ const filename = `qx-report-${sanitizedTarget}-${timestamp}.html`;
368
+ const reportsDir = path.join(process.cwd(), 'docs', 'qx-reports');
369
+ // Ensure reports directory exists
370
+ if (!fs.existsSync(reportsDir)) {
371
+ fs.mkdirSync(reportsDir, { recursive: true });
372
+ }
373
+ const reportPath = path.join(reportsDir, filename);
374
+ const html = this.generateHTMLContent(analysis);
375
+ fs.writeFileSync(reportPath, html, 'utf8');
376
+ return reportPath;
377
+ }
378
+ /**
379
+ * Generate HTML content for the report
380
+ */
381
+ generateHTMLContent(analysis) {
382
+ const date = analysis.timestamp.toLocaleDateString();
383
+ const time = analysis.timestamp.toLocaleTimeString();
384
+ return `<!DOCTYPE html>
385
+ <html lang="en">
386
+ <head>
387
+ <meta charset="UTF-8">
388
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
389
+ <title>QX Analysis: ${this.escapeHtml(analysis.target)}</title>
390
+ ${this.getReportStyles()}
391
+ </head>
392
+ <body>
393
+ <div class="container">
394
+ <div class="header">
395
+ <h1>🍵 Quality Experience (QX) Analysis</h1>
396
+ <div class="subtitle">${this.escapeHtml(analysis.target)}</div>
397
+ <div class="meta">
398
+ <strong>URL:</strong> ${this.escapeHtml(analysis.target)}<br>
399
+ <strong>Analysis Date:</strong> ${date} at ${time}<br>
400
+ <strong>Framework:</strong> QX Partner (Quality + UX Advocacy)
401
+ </div>
402
+ </div>
403
+
404
+ <div class="content">
405
+ <!-- Executive Summary -->
406
+ <div class="section">
407
+ <h2>📊 Executive Summary</h2>
408
+ <p>
409
+ This comprehensive QX analysis evaluates <strong>${this.escapeHtml(analysis.context.title || analysis.target)}</strong>
410
+ through the lens of Quality Experience, examining how quality is co-created for all stakeholders.
411
+ </p>
412
+ </div>
413
+
414
+ <!-- Overall QX Score -->
415
+ <div class="section">
416
+ <h2>🎯 Overall QX Score</h2>
417
+ <div class="score-card">
418
+ <div class="score-item">
419
+ <h4>Problem Clarity</h4>
420
+ <div class="score-value">${analysis.problemAnalysis.clarityScore}</div>
421
+ <div class="score-label">/ 100</div>
422
+ </div>
423
+ <div class="score-item">
424
+ <h4>User Needs Alignment</h4>
425
+ <div class="score-value">${analysis.userNeeds.alignmentScore}</div>
426
+ <div class="score-label">/ 100</div>
427
+ </div>
428
+ <div class="score-item">
429
+ <h4>Business Alignment</h4>
430
+ <div class="score-value">${analysis.businessNeeds.alignmentScore}</div>
431
+ <div class="score-label">/ 100</div>
432
+ </div>
433
+ <div class="score-item">
434
+ <h4>Impact Assessment</h4>
435
+ <div class="score-value">${100 - analysis.impactAnalysis.overallImpactScore}</div>
436
+ <div class="score-label">/ 100</div>
437
+ </div>
438
+ </div>
439
+ <div style="text-align: center; margin-top: 30px;">
440
+ <div class="score-value" style="font-size: 3em; color: ${this.getScoreColor(analysis.overallScore)};">${analysis.overallScore}</div>
441
+ <div class="score-label" style="font-size: 1.2em;">OVERALL QX SCORE (Grade: ${analysis.grade})</div>
442
+ </div>
443
+ </div>
444
+
445
+ <!-- Problem Analysis -->
446
+ <div class="section">
447
+ <h2>🔍 Problem Analysis</h2>
448
+ <div class="info-box">
449
+ <h3>Problem Statement</h3>
450
+ <p>${this.escapeHtml(analysis.problemAnalysis.problemStatement)}</p>
451
+ <p><strong>Complexity:</strong> ${analysis.problemAnalysis.complexity}</p>
452
+ <p><strong>Clarity Score:</strong> ${analysis.problemAnalysis.clarityScore}/100</p>
453
+ </div>
454
+ ${analysis.problemAnalysis.potentialFailures.length > 0 ? `
455
+ <div class="improvements">
456
+ <h3>⚠️ Potential Failure Modes</h3>
457
+ <ul>
458
+ ${analysis.problemAnalysis.potentialFailures.map(f => `
459
+ <li>
460
+ <strong>[${f.severity.toUpperCase()}]</strong> ${this.escapeHtml(f.description)}
461
+ <br><small>Likelihood: ${f.likelihood}</small>
462
+ </li>
463
+ `).join('')}
464
+ </ul>
465
+ </div>
466
+ ` : ''}
467
+ </div>
468
+
469
+ <!-- User Needs -->
470
+ <div class="section">
471
+ <h2>👥 User Needs Analysis</h2>
472
+ <p><strong>Suitability:</strong> ${analysis.userNeeds.suitability} | <strong>Score:</strong> ${analysis.userNeeds.alignmentScore}/100</p>
473
+ ${analysis.userNeeds.needs.length > 0 ? `
474
+ <div class="strengths">
475
+ <h3>✅ User Needs</h3>
476
+ <ul>
477
+ ${analysis.userNeeds.needs.map(n => `
478
+ <li>
479
+ <strong>[${n.priority}]</strong> ${this.escapeHtml(n.description)}
480
+ ${n.addressed ? '✓ Addressed' : '✗ Not Addressed'}
481
+ </li>
482
+ `).join('')}
483
+ </ul>
484
+ </div>
485
+ ` : ''}
486
+ ${analysis.userNeeds.challenges.length > 0 ? `
487
+ <div class="improvements">
488
+ <h3>⚠️ User Challenges</h3>
489
+ <ul>
490
+ ${analysis.userNeeds.challenges.map(c => `<li>${this.escapeHtml(c)}</li>`).join('')}
491
+ </ul>
492
+ </div>
493
+ ` : ''}
494
+ </div>
495
+
496
+ <!-- Business Needs -->
497
+ <div class="section">
498
+ <h2>💼 Business Needs Analysis</h2>
499
+ <p><strong>Primary Goal:</strong> ${analysis.businessNeeds.primaryGoal}</p>
500
+ <p><strong>Compromises UX:</strong> ${analysis.businessNeeds.compromisesUX ? 'Yes ⚠️' : 'No ✓'}</p>
501
+ ${analysis.businessNeeds.kpisAffected.length > 0 ? `
502
+ <div class="info-box">
503
+ <h3>KPIs Affected</h3>
504
+ <ul>
505
+ ${analysis.businessNeeds.kpisAffected.map(k => `<li>${this.escapeHtml(k)}</li>`).join('')}
506
+ </ul>
507
+ </div>
508
+ ` : ''}
509
+ </div>
510
+
511
+ <!-- Creativity Analysis -->
512
+ <div class="section">
513
+ <h2>🎨 Creativity & Innovation Analysis</h2>
514
+ <p><strong>Creativity Score:</strong> ${analysis.creativityAnalysis.creativityScore}/100</p>
515
+ <p><strong>Domains Explored:</strong> ${analysis.creativityAnalysis.domainsExplored.join(', ')}</p>
516
+ ${analysis.creativityAnalysis.innovativeApproaches.length > 0 ? `
517
+ <div class="strengths">
518
+ <h3>✨ Innovative Testing Approaches</h3>
519
+ <ul>
520
+ ${analysis.creativityAnalysis.innovativeApproaches.map(a => `
521
+ <li>
522
+ <strong>[${a.inspirationSource.toUpperCase()}]</strong> ${this.escapeHtml(a.description)}
523
+ <br><small>Applicability: ${a.applicability} | Novelty: ${a.novelty}</small>
524
+ </li>
525
+ `).join('')}
526
+ </ul>
527
+ </div>
528
+ ` : ''}
529
+ ${analysis.creativityAnalysis.perspectives.length > 0 ? `
530
+ <div class="info-box">
531
+ <h3>🔍 Testing Perspectives Applied</h3>
532
+ <ul>
533
+ ${analysis.creativityAnalysis.perspectives.map(p => `<li>${this.escapeHtml(p)}</li>`).join('')}
534
+ </ul>
535
+ </div>
536
+ ` : ''}
537
+ </div>
538
+
539
+ <!-- Design Quality Analysis -->
540
+ <div class="section">
541
+ <h2>🎯 Design Quality Analysis</h2>
542
+ <p><strong>Overall Design Score:</strong> ${analysis.designAnalysis.overallDesignScore}/100</p>
543
+
544
+ <!-- Exactness -->
545
+ <div class="info-box" style="margin-top: 20px;">
546
+ <h3>📏 Exactness & Clarity (${analysis.designAnalysis.exactness.score}/100)</h3>
547
+ <p><strong>Clarity Level:</strong> ${analysis.designAnalysis.exactness.clarity}</p>
548
+ ${analysis.designAnalysis.exactness.clearElements.length > 0 ? `
549
+ <div style="margin-top: 15px;">
550
+ <strong>✓ Clear Elements:</strong>
551
+ <ul>
552
+ ${analysis.designAnalysis.exactness.clearElements.map(e => `<li>${this.escapeHtml(e)}</li>`).join('')}
553
+ </ul>
554
+ </div>
555
+ ` : ''}
556
+ ${analysis.designAnalysis.exactness.unclearElements.length > 0 ? `
557
+ <div style="margin-top: 15px;">
558
+ <strong>⚠️ Unclear Elements:</strong>
559
+ <ul>
560
+ ${analysis.designAnalysis.exactness.unclearElements.map(e => `<li>${this.escapeHtml(e)}</li>`).join('')}
561
+ </ul>
562
+ </div>
563
+ ` : ''}
564
+ </div>
565
+
566
+ <!-- Intuitive Design -->
567
+ <div class="strengths" style="margin-top: 20px;">
568
+ <h3>🧭 Intuitive Design (${analysis.designAnalysis.intuitive.score}/100)</h3>
569
+ <p><strong>Follows Conventions:</strong> ${analysis.designAnalysis.intuitive.followsConventions ? 'Yes ✓' : 'No ⚠️'}</p>
570
+ ${analysis.designAnalysis.intuitive.intuitivePatterns.length > 0 ? `
571
+ <div style="margin-top: 15px;">
572
+ <strong>Intuitive Patterns Detected:</strong>
573
+ <ul>
574
+ ${analysis.designAnalysis.intuitive.intuitivePatterns.map(p => `<li>${this.escapeHtml(p)}</li>`).join('')}
575
+ </ul>
576
+ </div>
577
+ ` : ''}
578
+ ${analysis.designAnalysis.intuitive.culturalIssues.length > 0 ? `
579
+ <div style="margin-top: 15px;">
580
+ <strong>⚠️ Cultural Considerations:</strong>
581
+ <ul>
582
+ ${analysis.designAnalysis.intuitive.culturalIssues.map(i => `<li>${this.escapeHtml(i)}</li>`).join('')}
583
+ </ul>
584
+ </div>
585
+ ` : ''}
586
+ </div>
587
+
588
+ <!-- Counter-intuitive Design -->
589
+ ${analysis.designAnalysis.counterIntuitive.deviations.length > 0 ? `
590
+ <div class="improvements" style="margin-top: 20px;">
591
+ <h3>🔄 Counter-intuitive Design Patterns</h3>
592
+ <p><strong>Issues Found:</strong> ${analysis.designAnalysis.counterIntuitive.issuesCount}</p>
593
+ <p><strong>Fresh Eyes Perspective Applied:</strong> ${analysis.designAnalysis.counterIntuitive.freshEyesPerspective ? 'Yes ✓' : 'No'}</p>
594
+ <ul>
595
+ ${analysis.designAnalysis.counterIntuitive.deviations.map(d => `
596
+ <li>
597
+ <strong>${this.escapeHtml(d.element)}</strong>
598
+ <br>Expected: ${this.escapeHtml(d.expectedBehavior)}
599
+ <br>Actual: ${this.escapeHtml(d.actualBehavior)}
600
+ <br><small>Impact: ${d.impact} ${d.justification ? '| ' + this.escapeHtml(d.justification) : ''}</small>
601
+ </li>
602
+ `).join('')}
603
+ </ul>
604
+ </div>
605
+ ` : ''}
606
+ </div>
607
+
608
+ <!-- Oracle Problems -->
609
+ ${analysis.oracleProblems.length > 0 ? `
610
+ <div class="section">
611
+ <h2>🔮 Oracle Problems Detected</h2>
612
+ ${analysis.oracleProblems.map(p => `
613
+ <div class="improvements">
614
+ <h3>[${p.severity.toUpperCase()}] ${p.type}</h3>
615
+ <p>${this.escapeHtml(p.description)}</p>
616
+ ${p.stakeholders ? `<p><strong>Stakeholders:</strong> ${p.stakeholders.join(', ')}</p>` : ''}
617
+ ${p.resolutionApproach ? `
618
+ <p><strong>Resolution Approach:</strong></p>
619
+ <ul>
620
+ ${p.resolutionApproach.map(r => `<li>${this.escapeHtml(r)}</li>`).join('')}
621
+ </ul>
622
+ ` : ''}
623
+ </div>
624
+ `).join('')}
625
+ </div>
626
+ ` : ''}
627
+
628
+ <!-- Recommendations -->
629
+ <div class="section">
630
+ <h2>💡 Strategic Recommendations</h2>
631
+ ${analysis.recommendations.slice(0, 10).map((rec, idx) => `
632
+ <div class="recommendations">
633
+ <h3>🎯 Priority ${idx + 1}: ${this.escapeHtml(rec.principle)}</h3>
634
+ <p>${this.escapeHtml(rec.recommendation)}</p>
635
+ <p>
636
+ <strong>Severity:</strong> ${rec.severity} |
637
+ <strong>Impact:</strong> ${rec.impactPercentage || rec.impact}% |
638
+ <strong>Effort:</strong> ${rec.estimatedEffort || rec.effort}
639
+ </p>
640
+ </div>
641
+ `).join('')}
642
+ </div>
643
+
644
+ <!-- Heuristics Results -->
645
+ ${analysis.heuristics.length > 0 ? `
646
+ <div class="section">
647
+ <h2>📐 Heuristics Analysis</h2>
648
+ <div class="score-card">
649
+ ${analysis.heuristics.slice(0, 8).map(h => `
650
+ <div class="score-item">
651
+ <h4>${this.formatHeuristicName(h.name)}</h4>
652
+ <div class="score-value" style="font-size: 1.8em; color: ${this.getScoreColor(h.score)};">${h.score}</div>
653
+ <div class="score-label">/ 100</div>
654
+ </div>
655
+ `).join('')}
656
+ </div>
657
+ </div>
658
+ ` : ''}
659
+
660
+ <!-- Impact Analysis -->
661
+ <div class="section">
662
+ <h2>⚡ Impact Analysis</h2>
663
+ <div class="score-card">
664
+ <div class="score-item">
665
+ <h4>Visible Impact</h4>
666
+ <div class="score-value">${analysis.impactAnalysis.visible.score}</div>
667
+ <div class="score-label">/ 100</div>
668
+ </div>
669
+ <div class="score-item">
670
+ <h4>Invisible Impact</h4>
671
+ <div class="score-value">${analysis.impactAnalysis.invisible.score}</div>
672
+ <div class="score-label">/ 100</div>
673
+ </div>
674
+ </div>
675
+ ${analysis.impactAnalysis.visible.userFeelings && analysis.impactAnalysis.visible.userFeelings.length > 0 ? `
676
+ <div class="info-box">
677
+ <h3>User Feelings</h3>
678
+ <ul>
679
+ ${analysis.impactAnalysis.visible.userFeelings.map(f => {
680
+ if (typeof f === 'string') {
681
+ return `<li>${this.escapeHtml(f)}</li>`;
682
+ }
683
+ else {
684
+ return `<li><strong>${f.feeling}</strong> (${f.likelihood}): ${this.escapeHtml(f.context)}</li>`;
685
+ }
686
+ }).join('')}
687
+ </ul>
688
+ </div>
689
+ ` : ''}
690
+ </div>
691
+
692
+ <!-- Conclusion -->
693
+ <div class="section">
694
+ <h2>🎓 Conclusion</h2>
695
+ <p>
696
+ This QX analysis reveals an overall score of <strong>${analysis.overallScore}/100 (Grade: ${analysis.grade})</strong>.
697
+ ${this.getScoreInterpretation(analysis.overallScore)}
698
+ </p>
699
+ </div>
700
+
701
+ <!-- QX Methodology -->
702
+ <div class="section" style="background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%); padding: 30px; border-radius: 8px; margin-top: 40px;">
703
+ <h2>📚 QX Methodology: Key Concepts</h2>
704
+
705
+ <div style="margin-top: 20px;">
706
+ <h3 style="color: #667eea; margin-bottom: 10px;">🤝 What is Quality Experience (QX)?</h3>
707
+ <p style="text-align: justify;">
708
+ <strong>Quality Experience (QX)</strong> is the marriage between <strong>Quality Advocacy (QA)</strong> and
709
+ <strong>User Experience (UX)</strong>. Unlike traditional testing that focuses solely on defects, QX recognizes
710
+ that quality is co-created by everyone associated with the product—developers, testers, designers, users, and
711
+ business stakeholders. QX enables testers to collaborate meaningfully with UX professionals by understanding
712
+ design effectiveness beyond technical correctness.
713
+ </p>
714
+ </div>
715
+
716
+ <div style="margin-top: 25px;">
717
+ <h3 style="color: #667eea; margin-bottom: 10px;">🎨 Creativity in Testing</h3>
718
+ <p style="text-align: justify;">
719
+ QX encourages drawing inspiration from <strong>diverse domains</strong>—philosophy, social science, medicine,
720
+ e-commerce, fashion, gaming—to generate innovative test ideas when conventional approaches fall short. This
721
+ cross-disciplinary perspective helps testers uncover unconventional risks and approach problems from fresh angles
722
+ that technical testing alone might miss.
723
+ </p>
724
+ </div>
725
+
726
+ <div style="margin-top: 25px;">
727
+ <h3 style="color: #667eea; margin-bottom: 10px;">📏 Exactness & Clarity</h3>
728
+ <p style="text-align: justify;">
729
+ <strong>Exactness</strong> evaluates how clearly a product communicates its intent to users. Testers should assess
730
+ whether menu items, buttons, labels, and terminology are self-evident. Are component interactions obvious? Do users
731
+ understand what will happen when they click? Exactness testing identifies ambiguities that create confusion, focusing
732
+ on <em>clarity of communication</em> rather than just functional correctness.
733
+ </p>
734
+ </div>
735
+
736
+ <div style="margin-top: 25px;">
737
+ <h3 style="color: #667eea; margin-bottom: 10px;">🧭 Intuitive Design</h3>
738
+ <p style="text-align: justify;">
739
+ <strong>Intuitive design</strong> follows common conventions and user expectations. QX testing evaluates whether
740
+ component interactions follow familiar patterns, respect cultural sensitivities, and align with mental models users
741
+ bring from other products. Intuitive design reduces cognitive load and makes products immediately usable without
742
+ extensive training.
743
+ </p>
744
+ </div>
745
+
746
+ <div style="margin-top: 25px;">
747
+ <h3 style="color: #667eea; margin-bottom: 10px;">🔄 Counter-intuitive Design Detection</h3>
748
+ <p style="text-align: justify;">
749
+ QX testing deliberately <strong>looks at products like an unexperienced user</strong> to spot design elements that
750
+ deviate from expectations. Counter-intuitive patterns aren't always bad—they might represent innovation—but they
751
+ require justification. The key is distinguishing between deliberate, valuable innovations and accidental friction
752
+ that experienced users have normalized but newcomers will struggle with.
753
+ </p>
754
+ </div>
755
+
756
+ <div style="margin-top: 25px; padding: 20px; background: white; border-left: 4px solid #667eea; border-radius: 4px;">
757
+ <p style="text-align: justify; font-style: italic;">
758
+ <strong>The QX Advantage:</strong> By combining quality advocacy with UX design thinking, QX enables testers to
759
+ contribute informed insights about user-facing quality, bridge the gap between QA and UX teams, and ensure that
760
+ testing serves the genuine experience quality that all stakeholders care about—not just technical correctness.
761
+ </p>
762
+ </div>
763
+
764
+ <div style="margin-top: 20px; text-align: center;">
765
+ <p style="font-size: 0.9em;">
766
+ <strong>Learn more:</strong>
767
+ <a href="https://talesoftesting.com/quality-experienceqx-co-creating-quality-experience-for-everyone-associated-with-the-product/"
768
+ target="_blank" rel="noopener noreferrer" style="color: #667eea; text-decoration: none;">
769
+ Quality Experience (QX) - Tales of Testing
770
+ </a>
771
+ </p>
772
+ </div>
773
+ </div>
774
+ </div>
775
+
776
+ <div class="footer">
777
+ <p><strong>QX Analysis Report</strong></p>
778
+ <p>Generated by: Agentic QE Fleet v2.1.0 - QX Partner Agent</p>
779
+ <p>Framework: Quality Experience (QX) Analysis</p>
780
+ <p>Analysis Date: ${date} at ${time}</p>
781
+ <hr style="margin: 20px 0; border: none; border-top: 1px solid #dee2e6;">
782
+ <p style="font-size: 0.9em; line-height: 1.6;">
783
+ This report applies the QX framework developed to bridge Quality Advocacy (QA) and User Experience (UX).<br>
784
+ <em>"Quality is value to someone who matters"</em> - when multiple stakeholders matter simultaneously,<br>
785
+ QX helps find balance and solve oracle problems. It is one of the key concepts originally covered in
786
+ <a href="https://talesoftesting.com/qcsd/" target="_blank" rel="noopener noreferrer" style="color: #007bff; text-decoration: none;">
787
+ QCSD - Quality Conscious Software Delivery Framework</a> created by Lalitkumar Bhamare.
788
+ </p>
789
+ </div>
790
+ </div>
791
+ </body>
792
+ </html>`;
793
+ }
794
+ /**
795
+ * Get CSS styles for the report
796
+ */
797
+ getReportStyles() {
798
+ return `
799
+ <style>
800
+ * { margin: 0; padding: 0; box-sizing: border-box; }
801
+ body {
802
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
803
+ line-height: 1.6;
804
+ color: #333;
805
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
806
+ padding: 20px;
807
+ }
808
+ .container {
809
+ max-width: 1200px;
810
+ margin: 0 auto;
811
+ background: white;
812
+ border-radius: 12px;
813
+ box-shadow: 0 20px 60px rgba(0,0,0,0.3);
814
+ overflow: hidden;
815
+ }
816
+ .header {
817
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
818
+ color: white;
819
+ padding: 40px;
820
+ text-align: center;
821
+ }
822
+ .header h1 { font-size: 2.5em; margin-bottom: 10px; font-weight: 700; }
823
+ .header .subtitle { font-size: 1.2em; opacity: 0.9; }
824
+ .header .meta { margin-top: 20px; font-size: 0.9em; opacity: 0.8; }
825
+ .content { padding: 40px; }
826
+ .section { margin-bottom: 40px; }
827
+ .section h2 {
828
+ color: #667eea;
829
+ font-size: 1.8em;
830
+ margin-bottom: 20px;
831
+ padding-bottom: 10px;
832
+ border-bottom: 3px solid #667eea;
833
+ }
834
+ .section h3 { color: #764ba2; font-size: 1.4em; margin: 25px 0 15px 0; }
835
+ .section p { margin-bottom: 15px; text-align: justify; }
836
+ .score-card {
837
+ display: grid;
838
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
839
+ gap: 20px;
840
+ margin: 30px 0;
841
+ }
842
+ .score-item {
843
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
844
+ padding: 20px;
845
+ border-radius: 8px;
846
+ text-align: center;
847
+ transition: transform 0.3s ease;
848
+ }
849
+ .score-item:hover { transform: translateY(-5px); box-shadow: 0 5px 20px rgba(0,0,0,0.1); }
850
+ .score-item h4 { color: #667eea; font-size: 1.1em; margin-bottom: 10px; }
851
+ .score-value {
852
+ font-size: 2.5em;
853
+ font-weight: bold;
854
+ color: #764ba2;
855
+ margin: 10px 0;
856
+ }
857
+ .score-label {
858
+ font-size: 0.9em;
859
+ color: #666;
860
+ text-transform: uppercase;
861
+ letter-spacing: 1px;
862
+ }
863
+ .strengths, .improvements, .recommendations, .info-box {
864
+ background: #f8f9fa;
865
+ padding: 25px;
866
+ border-radius: 8px;
867
+ margin: 20px 0;
868
+ }
869
+ .strengths { border-left: 5px solid #28a745; }
870
+ .improvements { border-left: 5px solid #ffc107; }
871
+ .recommendations { border-left: 5px solid #17a2b8; }
872
+ .info-box { border-left: 5px solid #6c757d; }
873
+ .strengths h3 { color: #28a745; }
874
+ .improvements h3 { color: #ffc107; }
875
+ .recommendations h3 { color: #17a2b8; }
876
+ .info-box h3 { color: #6c757d; }
877
+ ul { margin-left: 20px; margin-top: 10px; }
878
+ li { margin-bottom: 10px; line-height: 1.8; }
879
+ .footer {
880
+ background: #f8f9fa;
881
+ padding: 30px;
882
+ text-align: center;
883
+ color: #666;
884
+ border-top: 1px solid #e0e0e0;
885
+ }
886
+ .footer p { margin-bottom: 10px; }
887
+ @media print {
888
+ body { background: white; padding: 0; }
889
+ .container { box-shadow: none; }
890
+ }
891
+ </style>`;
892
+ }
893
+ /**
894
+ * Escape HTML special characters
895
+ */
896
+ escapeHtml(text) {
897
+ const map = {
898
+ '&': '&amp;',
899
+ '<': '&lt;',
900
+ '>': '&gt;',
901
+ '"': '&quot;',
902
+ "'": '&#039;'
903
+ };
904
+ return text.replace(/[&<>"']/g, m => map[m]);
905
+ }
906
+ /**
907
+ * Format heuristic name for display
908
+ */
909
+ formatHeuristicName(name) {
910
+ return name
911
+ .split('-')
912
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
913
+ .join(' ');
914
+ }
915
+ /**
916
+ * Get color based on score
917
+ */
918
+ getScoreColor(score) {
919
+ if (score >= 90)
920
+ return '#28a745'; // Green
921
+ if (score >= 80)
922
+ return '#17a2b8'; // Blue
923
+ if (score >= 70)
924
+ return '#ffc107'; // Yellow
925
+ if (score >= 60)
926
+ return '#fd7e14'; // Orange
927
+ return '#dc3545'; // Red
928
+ }
929
+ /**
930
+ * Get score interpretation
931
+ */
932
+ getScoreInterpretation(score) {
933
+ if (score >= 90) {
934
+ return 'Excellent quality experience with strong alignment across all dimensions.';
935
+ }
936
+ else if (score >= 80) {
937
+ return 'Good quality experience with minor areas for improvement.';
938
+ }
939
+ else if (score >= 70) {
940
+ return 'Adequate quality experience but significant improvements recommended.';
941
+ }
942
+ else if (score >= 60) {
943
+ return 'Below target quality experience. Priority improvements required.';
944
+ }
945
+ else {
946
+ return 'Poor quality experience. Immediate action needed across multiple areas.';
947
+ }
948
+ }
949
+ /**
950
+ * Launch report in default browser
951
+ */
952
+ async launchReportInBrowser(reportPath) {
953
+ try {
954
+ const platform = process.platform;
955
+ let command;
956
+ if (platform === 'darwin') {
957
+ command = `open "${reportPath}"`;
958
+ }
959
+ else if (platform === 'win32') {
960
+ command = `start "" "${reportPath}"`;
961
+ }
962
+ else {
963
+ // Linux and others
964
+ command = `xdg-open "${reportPath}"`;
965
+ }
966
+ await execAsync(command);
967
+ this.logger.info(`Launched report in browser: ${reportPath}`);
968
+ }
969
+ catch (error) {
970
+ this.logger.warn(`Failed to auto-launch browser:`, error);
971
+ this.logger.info(`Report available at: ${reportPath}`);
972
+ }
973
+ }
305
974
  /**
306
975
  * Collect QX context from target using Playwright
307
976
  */
@@ -875,6 +1544,186 @@ class QXPartnerAgent extends BaseAgent_1.BaseAgent {
875
1544
  alignmentScore
876
1545
  };
877
1546
  }
1547
+ /**
1548
+ * Analyze Creativity - Drawing inspiration from diverse domains
1549
+ */
1550
+ async analyzeCreativity(context, problemAnalysis) {
1551
+ this.logger.debug('Analyzing creativity and innovation');
1552
+ const innovativeApproaches = [];
1553
+ // Analyze based on problem complexity
1554
+ if (problemAnalysis.complexity === 'complex' || problemAnalysis.complexity === 'moderate') {
1555
+ // Philosophy-inspired: Question fundamental assumptions
1556
+ innovativeApproaches.push({
1557
+ description: 'Question fundamental assumptions about user mental models and expected workflows',
1558
+ inspirationSource: 'philosophy',
1559
+ applicability: 'high',
1560
+ novelty: 'moderately-novel'
1561
+ });
1562
+ // Medicine-inspired: Diagnostic approach
1563
+ if (context.errorIndicators?.hasErrorMessages) {
1564
+ innovativeApproaches.push({
1565
+ description: 'Apply diagnostic testing - systematically isolate error sources through controlled scenarios',
1566
+ inspirationSource: 'medicine',
1567
+ applicability: 'high',
1568
+ novelty: 'moderately-novel'
1569
+ });
1570
+ }
1571
+ }
1572
+ // E-commerce/Fashion-inspired: User journey and aesthetics
1573
+ if (context.domMetrics?.forms && context.domMetrics.forms > 0) {
1574
+ innovativeApproaches.push({
1575
+ description: 'Test checkout/form flows like fashion retail - focus on friction points, abandonment triggers',
1576
+ inspirationSource: 'e-commerce',
1577
+ applicability: 'high',
1578
+ novelty: 'incremental'
1579
+ });
1580
+ }
1581
+ // Social Science-inspired: Cultural sensitivity and demographics
1582
+ innovativeApproaches.push({
1583
+ description: 'Analyze through diverse demographic lenses (age, gender, culture, ability) for inclusive testing',
1584
+ inspirationSource: 'social science',
1585
+ applicability: 'high',
1586
+ novelty: 'moderately-novel'
1587
+ });
1588
+ // Gaming-inspired: Edge cases and exploits
1589
+ if (context.domMetrics?.interactiveElements && context.domMetrics.interactiveElements > 20) {
1590
+ innovativeApproaches.push({
1591
+ description: 'Test for "game-breaking" exploits - unexpected interaction sequences, boundary conditions',
1592
+ inspirationSource: 'gaming',
1593
+ applicability: 'medium',
1594
+ novelty: 'highly-novel'
1595
+ });
1596
+ }
1597
+ const domainsExplored = [...new Set(innovativeApproaches.map(a => a.inspirationSource))];
1598
+ const perspectives = [
1599
+ 'Unexperienced user perspective (fresh eyes)',
1600
+ 'Power user perspective (efficiency focus)',
1601
+ 'Accessibility perspective (assistive tech users)',
1602
+ 'International perspective (cultural differences)'
1603
+ ];
1604
+ // Calculate creativity score
1605
+ let creativityScore = 50; // Base score
1606
+ creativityScore += innovativeApproaches.length * 8; // +8 per approach
1607
+ creativityScore += domainsExplored.length * 5; // +5 per domain
1608
+ creativityScore = Math.min(100, creativityScore);
1609
+ return {
1610
+ innovativeApproaches,
1611
+ domainsExplored,
1612
+ perspectives,
1613
+ creativityScore,
1614
+ notes: [
1615
+ 'Creativity draws from diverse domains to uncover unconventional testing approaches',
1616
+ 'Higher complexity problems benefit from cross-disciplinary inspiration',
1617
+ `Applied ${innovativeApproaches.length} creative approaches from ${domainsExplored.length} domains`
1618
+ ]
1619
+ };
1620
+ }
1621
+ /**
1622
+ * Analyze Design - Exactness, Intuitive, and Counter-intuitive Design
1623
+ */
1624
+ async analyzeDesign(context, _problemAnalysis) {
1625
+ this.logger.debug('Analyzing design quality');
1626
+ // 1. Exactness Analysis - How clearly the product communicates its intent
1627
+ const clearElements = [];
1628
+ const unclearElements = [];
1629
+ // Check semantic structure for clarity
1630
+ if (context.domMetrics?.semanticStructure?.hasNav) {
1631
+ clearElements.push('Navigation structure clearly defined with semantic <nav> element');
1632
+ }
1633
+ if (context.domMetrics?.semanticStructure?.hasMain) {
1634
+ clearElements.push('Main content area clearly identified');
1635
+ }
1636
+ if (context.domMetrics?.semanticStructure?.hasHeader && context.domMetrics?.semanticStructure?.hasFooter) {
1637
+ clearElements.push('Header and footer provide clear page structure');
1638
+ }
1639
+ // Check for unclear elements
1640
+ const ariaLabels = context.semanticQuality?.ariaLabels || 0;
1641
+ const interactiveElements = context.domMetrics?.interactiveElements || 0;
1642
+ if (interactiveElements > 0 && ariaLabels < interactiveElements * 0.5) {
1643
+ unclearElements.push('Many interactive elements lack ARIA labels for clarity');
1644
+ }
1645
+ if (context.errorIndicators?.hasErrorMessages) {
1646
+ unclearElements.push('Error messages present - may indicate unclear user guidance');
1647
+ }
1648
+ const exactnessClarity = unclearElements.length === 0 ? 'excellent' :
1649
+ unclearElements.length <= 2 ? 'good' :
1650
+ unclearElements.length <= 4 ? 'adequate' : 'poor';
1651
+ let exactnessScore = 50;
1652
+ exactnessScore += clearElements.length * 10;
1653
+ exactnessScore -= unclearElements.length * 8;
1654
+ exactnessScore = Math.max(0, Math.min(100, exactnessScore));
1655
+ // 2. Intuitive Design Analysis
1656
+ const intuitivePatterns = [];
1657
+ const culturalIssues = [];
1658
+ if (context.domMetrics?.semanticStructure?.hasNav) {
1659
+ intuitivePatterns.push('Standard navigation patterns (semantic nav element)');
1660
+ }
1661
+ if (context.domMetrics?.forms && context.domMetrics.forms > 0) {
1662
+ intuitivePatterns.push('Standard form patterns detected');
1663
+ }
1664
+ if (context.metadata?.viewport) {
1665
+ intuitivePatterns.push('Responsive design viewport configured');
1666
+ }
1667
+ // Cultural sensitivity check (basic)
1668
+ if (context.title && /[^\x00-\x7F]/.test(context.title || '')) {
1669
+ // Non-ASCII characters detected - could be good (internationalization) or need review
1670
+ culturalIssues.push('International characters detected - ensure cultural appropriateness');
1671
+ }
1672
+ const followsConventions = intuitivePatterns.length >= 2;
1673
+ let intuitiveScore = followsConventions ? 70 : 50;
1674
+ intuitiveScore += intuitivePatterns.length * 8;
1675
+ intuitiveScore -= culturalIssues.length * 10;
1676
+ intuitiveScore = Math.max(0, Math.min(100, intuitiveScore));
1677
+ // 3. Counter-intuitive Design Detection
1678
+ const deviations = [];
1679
+ // Check for potential counter-intuitive patterns
1680
+ const buttons = context.domMetrics?.buttons || 0;
1681
+ const forms = context.domMetrics?.forms || 0;
1682
+ if (buttons > 20 && forms === 0) {
1683
+ deviations.push({
1684
+ element: 'Multiple buttons without forms',
1685
+ expectedBehavior: 'Forms typically accompany many buttons',
1686
+ actualBehavior: 'Many buttons present without traditional forms',
1687
+ impact: 'neutral',
1688
+ justification: 'May be single-page app or API-driven interface'
1689
+ });
1690
+ }
1691
+ if (!context.domMetrics?.semanticStructure?.hasMain && (context.domMetrics?.totalElements || 0) > 50) {
1692
+ deviations.push({
1693
+ element: 'Complex page without main landmark',
1694
+ expectedBehavior: 'Complex pages typically have <main> landmark',
1695
+ actualBehavior: 'No main content landmark defined',
1696
+ impact: 'negative',
1697
+ justification: 'Reduces accessibility and clarity'
1698
+ });
1699
+ }
1700
+ const innovativeJustification = deviations.some(d => d.impact === 'positive' || d.justification?.includes('innovation'));
1701
+ const freshEyesPerspective = deviations.length > 0; // We're looking from unexperienced user view
1702
+ const issuesCount = deviations.filter(d => d.impact === 'negative').length;
1703
+ // 4. Overall Design Score
1704
+ const overallDesignScore = Math.round((exactnessScore + intuitiveScore) / 2);
1705
+ return {
1706
+ exactness: {
1707
+ clarity: exactnessClarity,
1708
+ clearElements,
1709
+ unclearElements,
1710
+ score: exactnessScore
1711
+ },
1712
+ intuitive: {
1713
+ followsConventions,
1714
+ intuitivePatterns,
1715
+ culturalIssues,
1716
+ score: intuitiveScore
1717
+ },
1718
+ counterIntuitive: {
1719
+ deviations,
1720
+ innovativeJustification,
1721
+ freshEyesPerspective,
1722
+ issuesCount
1723
+ },
1724
+ overallDesignScore
1725
+ };
1726
+ }
878
1727
  /**
879
1728
  * Detect oracle problems from analysis context
880
1729
  */
@@ -896,11 +1745,63 @@ class QXPartnerAgent extends BaseAgent_1.BaseAgent {
896
1745
  /**
897
1746
  * Apply all enabled heuristics
898
1747
  */
899
- async applyAllHeuristics(context, problemAnalysis, userNeeds, businessNeeds) {
1748
+ async applyAllHeuristics(context, problemAnalysis, userNeeds, businessNeeds, creativityAnalysis, designAnalysis) {
900
1749
  if (!this.heuristicsEngine) {
901
1750
  throw new Error('Heuristics engine not initialized');
902
1751
  }
903
- return this.heuristicsEngine.applyAll(context, problemAnalysis, userNeeds, businessNeeds);
1752
+ // Get standard heuristics
1753
+ const standardHeuristics = await this.heuristicsEngine.applyAll(context, problemAnalysis, userNeeds, businessNeeds);
1754
+ // Add creativity and design heuristics
1755
+ const creativityHeuristic = {
1756
+ name: 'creativity-innovation',
1757
+ category: 'creativity',
1758
+ applied: true,
1759
+ score: creativityAnalysis.creativityScore,
1760
+ findings: [
1761
+ `Applied ${creativityAnalysis.innovativeApproaches.length} creative approaches`,
1762
+ `Explored ${creativityAnalysis.domainsExplored.length} diverse domains: ${creativityAnalysis.domainsExplored.join(', ')}`,
1763
+ ...creativityAnalysis.notes
1764
+ ],
1765
+ issues: creativityAnalysis.innovativeApproaches
1766
+ .filter(a => a.applicability === 'low')
1767
+ .map(a => ({
1768
+ description: `Low applicability approach: ${a.description}`,
1769
+ severity: 'low'
1770
+ })),
1771
+ recommendations: creativityAnalysis.innovativeApproaches
1772
+ .filter(a => a.applicability === 'high')
1773
+ .map(a => `Consider: ${a.description} (${a.inspirationSource})`)
1774
+ };
1775
+ const designHeuristic = {
1776
+ name: 'design-quality',
1777
+ category: 'design',
1778
+ applied: true,
1779
+ score: designAnalysis.overallDesignScore,
1780
+ findings: [
1781
+ `Exactness: ${designAnalysis.exactness.clarity} (${designAnalysis.exactness.score}/100)`,
1782
+ `Intuitive Design: ${designAnalysis.intuitive.followsConventions ? 'Follows' : 'Deviates from'} conventions (${designAnalysis.intuitive.score}/100)`,
1783
+ `Counter-intuitive issues: ${designAnalysis.counterIntuitive.issuesCount}`,
1784
+ ...designAnalysis.exactness.clearElements.map(e => `✓ ${e}`),
1785
+ ...designAnalysis.intuitive.intuitivePatterns.map(p => `✓ ${p}`)
1786
+ ],
1787
+ issues: [
1788
+ ...designAnalysis.exactness.unclearElements.map(e => ({
1789
+ description: e,
1790
+ severity: 'medium'
1791
+ })),
1792
+ ...designAnalysis.counterIntuitive.deviations
1793
+ .filter(d => d.impact === 'negative')
1794
+ .map(d => ({
1795
+ description: `${d.element}: ${d.expectedBehavior} vs ${d.actualBehavior}`,
1796
+ severity: 'medium'
1797
+ }))
1798
+ ],
1799
+ recommendations: [
1800
+ ...designAnalysis.exactness.unclearElements.map(e => `Improve clarity: ${e}`),
1801
+ ...designAnalysis.intuitive.culturalIssues.map(i => `Address: ${i}`)
1802
+ ]
1803
+ };
1804
+ return [...standardHeuristics, creativityHeuristic, designHeuristic];
904
1805
  }
905
1806
  /**
906
1807
  * Generate QX recommendations
@@ -1044,23 +1945,19 @@ class QXPartnerAgent extends BaseAgent_1.BaseAgent {
1044
1945
  });
1045
1946
  return sorted;
1046
1947
  }
1047
- formatHeuristicName(heuristic) {
1048
- return heuristic
1049
- .split('-')
1050
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
1051
- .join(' ');
1052
- }
1053
1948
  /**
1054
1949
  * Calculate overall QX score
1055
1950
  */
1056
- calculateOverallQXScore(problemAnalysis, userNeeds, businessNeeds, impactAnalysis, heuristics) {
1951
+ calculateOverallQXScore(problemAnalysis, userNeeds, businessNeeds, creativityAnalysis, designAnalysis, impactAnalysis, heuristics) {
1057
1952
  // Weighted average of all components
1058
1953
  const weights = {
1059
- problem: 0.20,
1060
- userNeeds: 0.25,
1061
- businessNeeds: 0.20,
1062
- impact: 0.15,
1063
- heuristics: 0.20
1954
+ problem: 0.15, // Reduced from 0.20
1955
+ userNeeds: 0.20, // Reduced from 0.25
1956
+ businessNeeds: 0.15, // Reduced from 0.20
1957
+ creativity: 0.15, // NEW
1958
+ design: 0.15, // NEW
1959
+ impact: 0.10, // Reduced from 0.15
1960
+ heuristics: 0.10 // Reduced from 0.20
1064
1961
  };
1065
1962
  const heuristicsAvg = heuristics.length > 0
1066
1963
  ? heuristics.reduce((sum, h) => sum + h.score, 0) / heuristics.length
@@ -1069,6 +1966,8 @@ class QXPartnerAgent extends BaseAgent_1.BaseAgent {
1069
1966
  const score = problemAnalysis.clarityScore * weights.problem +
1070
1967
  userNeeds.alignmentScore * weights.userNeeds +
1071
1968
  businessNeeds.alignmentScore * weights.businessNeeds +
1969
+ creativityAnalysis.creativityScore * weights.creativity +
1970
+ designAnalysis.overallDesignScore * weights.design +
1072
1971
  impactScore * weights.impact +
1073
1972
  heuristicsAvg * weights.heuristics;
1074
1973
  return Math.round(score);