@bryan-thompson/inspector-assessment 1.35.2 → 1.36.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 (82) hide show
  1. package/cli/build/__tests__/assess-full-e2e.test.js +35 -9
  2. package/cli/build/__tests__/assess-full.test.js +4 -1
  3. package/cli/build/__tests__/assessment-runner/assessment-executor.test.js +15 -2
  4. package/cli/build/__tests__/assessment-runner/config-builder.test.js +6 -0
  5. package/cli/build/__tests__/assessment-runner/index.test.js +9 -4
  6. package/cli/build/__tests__/assessment-runner/path-resolver.test.js +112 -0
  7. package/cli/build/__tests__/assessment-runner/server-config.test.js +3 -0
  8. package/cli/build/__tests__/assessment-runner/server-connection.test.js +9 -1
  9. package/cli/build/__tests__/assessment-runner/source-loader.test.js +121 -16
  10. package/cli/build/__tests__/assessment-runner/tool-wrapper.test.js +3 -0
  11. package/cli/build/__tests__/assessment-runner-facade.test.js +7 -2
  12. package/cli/build/__tests__/cli-build-fixes.test.js +4 -1
  13. package/cli/build/__tests__/flag-parsing.test.js +3 -2
  14. package/cli/build/__tests__/http-transport-integration.test.js +19 -5
  15. package/cli/build/__tests__/jsonl-events.test.js +1 -1
  16. package/cli/build/__tests__/lib/server-configSchemas.test.js +4 -1
  17. package/cli/build/__tests__/lib/zodErrorFormatter.test.js +4 -1
  18. package/cli/build/__tests__/profiles.test.js +19 -8
  19. package/cli/build/__tests__/security/security-pattern-count.test.js +6 -3
  20. package/cli/build/__tests__/stage3-fix-validation.test.js +4 -1
  21. package/cli/build/__tests__/testbed-integration.test.js +19 -5
  22. package/cli/build/__tests__/transport.test.js +4 -1
  23. package/cli/build/lib/__tests__/cli-parserSchemas.test.js +4 -1
  24. package/cli/build/lib/assessment-runner/__tests__/server-configSchemas.test.js +4 -1
  25. package/cli/build/lib/assessment-runner/assessment-executor.js +23 -4
  26. package/cli/build/lib/assessment-runner/index.js +2 -0
  27. package/cli/build/lib/assessment-runner/path-resolver.js +48 -0
  28. package/cli/build/lib/assessment-runner/source-loader.js +47 -5
  29. package/cli/build/lib/cli-parser.js +10 -0
  30. package/cli/package.json +1 -1
  31. package/client/dist/assets/{OAuthCallback-jfmizOMH.js → OAuthCallback-Cfp3Vzdz.js} +1 -1
  32. package/client/dist/assets/{OAuthDebugCallback-bU5kKvnt.js → OAuthDebugCallback-7BLaxlcq.js} +1 -1
  33. package/client/dist/assets/{index-Ce63ds7G.js → index-B21S7_ML.js} +4 -4
  34. package/client/dist/index.html +1 -1
  35. package/client/lib/lib/assessment/coreTypes.d.ts +23 -0
  36. package/client/lib/lib/assessment/coreTypes.d.ts.map +1 -1
  37. package/client/lib/lib/assessment/extendedTypes.d.ts +49 -2
  38. package/client/lib/lib/assessment/extendedTypes.d.ts.map +1 -1
  39. package/client/lib/lib/assessment/jsonlEventSchemas.d.ts +4 -4
  40. package/client/lib/lib/assessment/resultTypes.d.ts +32 -1
  41. package/client/lib/lib/assessment/resultTypes.d.ts.map +1 -1
  42. package/client/lib/lib/aupPatterns.d.ts +50 -0
  43. package/client/lib/lib/aupPatterns.d.ts.map +1 -1
  44. package/client/lib/lib/aupPatterns.js +140 -0
  45. package/client/lib/lib/moduleScoring.d.ts.map +1 -1
  46. package/client/lib/lib/moduleScoring.js +39 -2
  47. package/client/lib/lib/securityPatterns.d.ts.map +1 -1
  48. package/client/lib/lib/securityPatterns.js +92 -0
  49. package/client/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts +26 -1
  50. package/client/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts.map +1 -1
  51. package/client/lib/services/assessment/modules/DeveloperExperienceAssessor.js +160 -1
  52. package/client/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts.map +1 -1
  53. package/client/lib/services/assessment/modules/ErrorHandlingAssessor.js +15 -0
  54. package/client/lib/services/assessment/modules/ManifestValidationAssessor.d.ts +32 -0
  55. package/client/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -1
  56. package/client/lib/services/assessment/modules/ManifestValidationAssessor.js +218 -20
  57. package/client/lib/services/assessment/modules/ProhibitedLibrariesAssessor.d.ts +5 -0
  58. package/client/lib/services/assessment/modules/ProhibitedLibrariesAssessor.d.ts.map +1 -1
  59. package/client/lib/services/assessment/modules/ProhibitedLibrariesAssessor.js +29 -0
  60. package/client/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
  61. package/client/lib/services/assessment/modules/SecurityAssessor.js +13 -0
  62. package/client/lib/services/assessment/modules/annotations/AlignmentChecker.d.ts +7 -2
  63. package/client/lib/services/assessment/modules/annotations/AlignmentChecker.d.ts.map +1 -1
  64. package/client/lib/services/assessment/modules/annotations/AlignmentChecker.js +116 -18
  65. package/client/lib/services/assessment/modules/annotations/index.d.ts +1 -1
  66. package/client/lib/services/assessment/modules/annotations/index.d.ts.map +1 -1
  67. package/client/lib/services/assessment/modules/annotations/index.js +2 -1
  68. package/client/lib/services/assessment/modules/securityTests/ConfidenceScorer.d.ts.map +1 -1
  69. package/client/lib/services/assessment/modules/securityTests/ConfidenceScorer.js +28 -0
  70. package/client/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.d.ts +95 -0
  71. package/client/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.d.ts.map +1 -1
  72. package/client/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.js +174 -0
  73. package/client/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts.map +1 -1
  74. package/client/lib/services/assessment/modules/securityTests/SecurityPayloadTester.js +15 -0
  75. package/client/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +40 -0
  76. package/client/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -1
  77. package/client/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +143 -131
  78. package/client/package.json +1 -1
  79. package/package.json +1 -1
  80. package/server/build/__tests__/helpers.test.js +3 -0
  81. package/server/build/__tests__/security.test.js +3 -0
  82. package/server/package.json +1 -1
@@ -24,9 +24,27 @@ export function calculateModuleScore(result) {
24
24
  if (!result || typeof result !== "object")
25
25
  return null;
26
26
  const r = result;
27
- // ErrorHandling module - uses metrics.mcpComplianceScore
27
+ // ErrorHandling module - validate test execution before scoring (Issue #153)
28
28
  const metrics = r.metrics;
29
29
  if (metrics?.mcpComplianceScore !== undefined) {
30
+ const metadata = r.testExecutionMetadata;
31
+ // If we have metadata, validate test execution
32
+ if (metadata) {
33
+ const { validTestsCompleted = 0, connectionErrorCount = 0, testCoveragePercent = 0, } = metadata;
34
+ // Case 1: All tests failed due to connection errors
35
+ // Return 0 score - can't verify error handling without successful test execution
36
+ // Note: validTestsCompleted=0 with connectionErrorCount=0 is allowed
37
+ // (e.g., no tools selected for testing - uses normal scoring)
38
+ if (validTestsCompleted === 0 && connectionErrorCount > 0) {
39
+ return 0;
40
+ }
41
+ // Case 2: Significant connection errors (>50% failure)
42
+ // Cap score at 50 - partial coverage means partial confidence
43
+ if (testCoveragePercent < 50 && connectionErrorCount > 0) {
44
+ const baseScore = Math.round(metrics.mcpComplianceScore);
45
+ return Math.min(50, baseScore);
46
+ }
47
+ }
30
48
  return Math.round(metrics.mcpComplianceScore);
31
49
  }
32
50
  // MCPSpecCompliance module - uses complianceScore
@@ -37,9 +55,28 @@ export function calculateModuleScore(result) {
37
55
  if (r.coveragePercentage !== undefined) {
38
56
  return Math.round(r.coveragePercentage);
39
57
  }
40
- // Security module - 100% if no vulns, lower based on vuln count
58
+ // Security module - validate test execution before scoring (Issue #152)
41
59
  if (Array.isArray(r.vulnerabilities)) {
42
60
  const vulnCount = r.vulnerabilities.length;
61
+ const metadata = r.testExecutionMetadata;
62
+ // If we have metadata, validate test execution
63
+ if (metadata) {
64
+ const { validTestsCompleted = 0, connectionErrorCount = 0, testCoveragePercent = 0, } = metadata;
65
+ // Case 1: All tests failed due to connection errors
66
+ // Return 0 score - can't verify security without successful test execution
67
+ // Note: validTestsCompleted=0 with connectionErrorCount=0 is allowed
68
+ // (e.g., server has no security-relevant tools - uses normal scoring)
69
+ if (validTestsCompleted === 0 && connectionErrorCount > 0) {
70
+ return 0;
71
+ }
72
+ // Case 2: Significant connection errors (>50% failure)
73
+ // Cap score at 50 - partial coverage means partial confidence
74
+ if (testCoveragePercent < 50 && connectionErrorCount > 0) {
75
+ const baseScore = vulnCount === 0 ? 100 : Math.max(0, 100 - vulnCount * 10);
76
+ return Math.min(50, baseScore);
77
+ }
78
+ }
79
+ // Normal case: good test coverage, calculate based on vulnerabilities
43
80
  return vulnCount === 0 ? 100 : Math.max(0, 100 - vulnCount * 10);
44
81
  }
45
82
  // AUP module - 100% if no violations, lower based on violation count
@@ -1 +1 @@
1
- {"version":3,"file":"securityPatterns.d.ts","sourceRoot":"","sources":["../../src/lib/securityPatterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,aAAa,EAo7DnD,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,MAAM,GACb,eAAe,EAAE,CAQnB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,aAAa,EAAE,CAEtD;AAED;;GAEG;AACH,wBAAgB,oBAAoB;;;;;;;;EA8BnC"}
1
+ {"version":3,"file":"securityPatterns.d.ts","sourceRoot":"","sources":["../../src/lib/securityPatterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,aAAa,EAoiEnD,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,MAAM,GACb,eAAe,EAAE,CAQnB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,aAAa,EAAE,CAEtD;AAED;;GAEG;AACH,wBAAgB,oBAAoB;;;;;;;;EA8BnC"}
@@ -1809,6 +1809,98 @@ export const SECURITY_ATTACK_PATTERNS = [
1809
1809
  },
1810
1810
  ],
1811
1811
  },
1812
+ // ==========================================
1813
+ // EXCESSIVE PERMISSIONS SCOPE TESTS (Issue #144, Challenge #22)
1814
+ // ==========================================
1815
+ // 32. EXCESSIVE PERMISSIONS SCOPE
1816
+ {
1817
+ attackName: "Excessive Permissions Scope",
1818
+ description: "Test if tools with restrictive annotations (readOnlyHint=True) allow privileged operations via specific inputs (CWE-250, CWE-269)",
1819
+ payloads: [
1820
+ // Privileged action payloads for tools that claim readOnlyHint=True
1821
+ {
1822
+ payload: "write_file",
1823
+ evidence: /"scope_violation"\s*:\s*true|"actual_scope"\s*:\s*"write"/i,
1824
+ riskLevel: "HIGH",
1825
+ description: "Write operation bypassing readOnlyHint=True annotation (CWE-250)",
1826
+ payloadType: "scope_violation",
1827
+ parameterTypes: ["action", "operation", "command", "cmd"],
1828
+ },
1829
+ {
1830
+ payload: "delete_data",
1831
+ evidence: /"scope_violation"\s*:\s*true|"actual_scope"\s*:\s*"delete"/i,
1832
+ riskLevel: "HIGH",
1833
+ description: "Delete operation bypassing destructiveHint=False annotation (CWE-250)",
1834
+ payloadType: "scope_violation",
1835
+ parameterTypes: ["action", "operation", "command", "cmd"],
1836
+ },
1837
+ {
1838
+ payload: "execute_command",
1839
+ evidence: /"scope_violation"\s*:\s*true|"actual_scope"\s*:\s*"execute"/i,
1840
+ riskLevel: "HIGH",
1841
+ description: "Execute operation bypassing readOnlyHint=True annotation (CWE-250)",
1842
+ payloadType: "scope_violation",
1843
+ parameterTypes: ["action", "operation", "command", "cmd"],
1844
+ },
1845
+ {
1846
+ payload: "network_request",
1847
+ evidence: /"scope_violation"\s*:\s*true|"actual_scope"\s*:\s*"network"/i,
1848
+ riskLevel: "HIGH",
1849
+ description: "Network operation bypassing openWorldHint=False annotation (CWE-250)",
1850
+ payloadType: "scope_violation",
1851
+ parameterTypes: ["action", "operation", "command", "cmd"],
1852
+ },
1853
+ {
1854
+ payload: "modify_config",
1855
+ evidence: /"scope_violation"\s*:\s*true|"actual_scope"\s*:\s*"modify"/i,
1856
+ riskLevel: "HIGH",
1857
+ description: "Config modification bypassing readOnlyHint=True annotation (CWE-250)",
1858
+ payloadType: "scope_violation",
1859
+ parameterTypes: ["action", "operation", "command", "cmd"],
1860
+ },
1861
+ {
1862
+ payload: "environment_access",
1863
+ evidence: /"scope_violation"\s*:\s*true|"actual_scope"\s*:\s*"environment"/i,
1864
+ riskLevel: "HIGH",
1865
+ description: "Environment access bypassing annotation restrictions (CWE-250)",
1866
+ payloadType: "scope_violation",
1867
+ parameterTypes: ["action", "operation", "command", "cmd"],
1868
+ },
1869
+ // Escalation keyword payloads for tools that claim readOnlyHint=True
1870
+ {
1871
+ payload: "show admin users",
1872
+ evidence: /"scope_escalation"\s*:\s*true|"privileged_data"\s*:|admin[_-]?mode[_-]?activated/i,
1873
+ riskLevel: "HIGH",
1874
+ description: "Keyword-triggered privilege escalation via 'admin' (CWE-269)",
1875
+ payloadType: "scope_escalation",
1876
+ parameterTypes: ["request", "query", "input", "text", "message"],
1877
+ },
1878
+ {
1879
+ payload: "sudo access logs",
1880
+ evidence: /"scope_escalation"\s*:\s*true|"system_secrets"\s*:|"trigger_keyword"\s*:\s*"sudo"/i,
1881
+ riskLevel: "HIGH",
1882
+ description: "Keyword-triggered privilege escalation via 'sudo' (CWE-269)",
1883
+ payloadType: "scope_escalation",
1884
+ parameterTypes: ["request", "query", "input", "text", "message"],
1885
+ },
1886
+ {
1887
+ payload: "elevate to root",
1888
+ evidence: /"scope_escalation"\s*:\s*true|"trigger_keyword"\s*:\s*"(elevate|root)"/i,
1889
+ riskLevel: "HIGH",
1890
+ description: "Keyword-triggered privilege escalation via 'elevate' or 'root' (CWE-269)",
1891
+ payloadType: "scope_escalation",
1892
+ parameterTypes: ["request", "query", "input", "text", "message"],
1893
+ },
1894
+ {
1895
+ payload: "get superuser privileges",
1896
+ evidence: /"scope_escalation"\s*:\s*true|"trigger_keyword"\s*:\s*"(superuser|privilege)"/i,
1897
+ riskLevel: "HIGH",
1898
+ description: "Keyword-triggered privilege escalation via 'superuser' or 'privilege' (CWE-269)",
1899
+ payloadType: "scope_escalation",
1900
+ parameterTypes: ["request", "query", "input", "text", "message"],
1901
+ },
1902
+ ],
1903
+ },
1812
1904
  ];
1813
1905
  /**
1814
1906
  * Get all payloads for an attack type
@@ -12,7 +12,7 @@
12
12
  *
13
13
  * @module assessment/modules/DeveloperExperienceAssessor
14
14
  */
15
- import { DocumentationMetrics, UsabilityMetrics, AssessmentStatus } from "../../../lib/assessmentTypes.js";
15
+ import { DocumentationMetrics, UsabilityMetrics, AssessmentStatus, NamespaceDetectionResult } from "../../../lib/assessmentTypes.js";
16
16
  import { BaseAssessor } from "./BaseAssessor.js";
17
17
  import { AssessmentContext } from "../AssessmentOrchestrator.js";
18
18
  /**
@@ -35,6 +35,8 @@ export interface DeveloperExperienceAssessment {
35
35
  usability: number;
36
36
  overall: number;
37
37
  };
38
+ /** Namespace detection results (Issue #142) */
39
+ namespaceDetection?: NamespaceDetectionResult;
38
40
  }
39
41
  export declare class DeveloperExperienceAssessor extends BaseAssessor<DeveloperExperienceAssessment> {
40
42
  assess(context: AssessmentContext): Promise<DeveloperExperienceAssessment>;
@@ -97,6 +99,29 @@ export declare class DeveloperExperienceAssessor extends BaseAssessor<DeveloperE
97
99
  private isDescriptiveName;
98
100
  private getToolSchema;
99
101
  private calculateUsabilityScore;
102
+ /**
103
+ * Detect namespace/prefix patterns in tool names.
104
+ * This helps identify intentional naming conventions like:
105
+ * - calc_add, calc_subtract -> namespace "calc"
106
+ * - fileRead, fileWrite -> namespace "file"
107
+ * - myserver_tool1, myserver_tool2 -> matches server name
108
+ */
109
+ private detectNamespace;
110
+ /**
111
+ * Find common prefix among tool names.
112
+ * Handles both snake_case (calc_add) and camelCase (calcAdd) conventions.
113
+ */
114
+ private findCommonPrefix;
115
+ /**
116
+ * Check if tool names use the server name as a prefix.
117
+ * Normalizes server name to match common patterns.
118
+ */
119
+ private checkServerNamePrefix;
120
+ /**
121
+ * Normalize server name for prefix matching.
122
+ * Converts "My-Server" -> "myserver", "my_server" -> "myserver"
123
+ */
124
+ private normalizeServerName;
100
125
  private determineOverallStatus;
101
126
  private generateExplanation;
102
127
  private generateRecommendations;
@@ -1 +1 @@
1
- {"version":3,"file":"DeveloperExperienceAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/DeveloperExperienceAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAEhB,gBAAgB,EAKjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG9D;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,yCAAyC;IACzC,aAAa,EAAE,oBAAoB,CAAC;IACpC,qCAAqC;IACrC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,gDAAgD;IAChD,MAAM,EAAE,gBAAgB,CAAC;IACzB,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iDAAiD;IACjD,MAAM,EAAE;QACN,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,qBAAa,2BAA4B,SAAQ,YAAY,CAAC,6BAA6B,CAAC;IACpF,MAAM,CACV,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,6BAA6B,CAAC;IAsEzC,OAAO,CAAC,oBAAoB;IAmH5B,OAAO,CAAC,yBAAyB;IA4CjC,OAAO,CAAC,wBAAwB;IAiBhC,OAAO,CAAC,sBAAsB;IA8B9B,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,mBAAmB;IAwC3B,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,mBAAmB;IA6B3B;;;OAGG;IACH,OAAO,CAAC,0BAA0B;IAkBlC;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAW9B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,qBAAqB;IAgC7B;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAgBjC;;;OAGG;IACH,OAAO,CAAC,aAAa;IAoBrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAsEzB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,uBAAuB;IAsC/B,OAAO,CAAC,uBAAuB;IAwC/B,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,kBAAkB;IAsC1B,OAAO,CAAC,iBAAiB;IAiCzB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,uBAAuB;IAgB/B,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,mBAAmB;IAyC3B,OAAO,CAAC,uBAAuB;CAmDhC"}
1
+ {"version":3,"file":"DeveloperExperienceAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/DeveloperExperienceAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAEhB,gBAAgB,EAKhB,wBAAwB,EACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG9D;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,yCAAyC;IACzC,aAAa,EAAE,oBAAoB,CAAC;IACpC,qCAAqC;IACrC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,gDAAgD;IAChD,MAAM,EAAE,gBAAgB,CAAC;IACzB,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iDAAiD;IACjD,MAAM,EAAE;QACN,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;CAC/C;AAED,qBAAa,2BAA4B,SAAQ,YAAY,CAAC,6BAA6B,CAAC;IACpF,MAAM,CACV,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,6BAA6B,CAAC;IA6EzC,OAAO,CAAC,oBAAoB;IAmH5B,OAAO,CAAC,yBAAyB;IA4CjC,OAAO,CAAC,wBAAwB;IAiBhC,OAAO,CAAC,sBAAsB;IA8B9B,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,mBAAmB;IAwC3B,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,mBAAmB;IA6B3B;;;OAGG;IACH,OAAO,CAAC,0BAA0B;IAkBlC;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAW9B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,qBAAqB;IAgC7B;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAgBjC;;;OAGG;IACH,OAAO,CAAC,aAAa;IAoBrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAsEzB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,uBAAuB;IAsC/B,OAAO,CAAC,uBAAuB;IAwC/B,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,kBAAkB;IAsC1B,OAAO,CAAC,iBAAiB;IAiCzB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,uBAAuB;IAgB/B;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;IAsEvB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA0DxB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAsC7B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,mBAAmB;IAyC3B,OAAO,CAAC,uBAAuB;CAmDhC"}
@@ -30,6 +30,8 @@ export class DeveloperExperienceAssessor extends BaseAssessor {
30
30
  // Assess usability
31
31
  const usabilityMetrics = this.analyzeUsability(context.tools);
32
32
  const usabilityScore = this.calculateUsabilityScore(usabilityMetrics);
33
+ // Issue #142: Detect namespace/prefix patterns in tool names
34
+ const namespaceDetection = this.detectNamespace(context.tools, context.serverInfo?.name);
33
35
  // Calculate overall score (weighted average: 60% docs, 40% usability)
34
36
  const overallScore = Math.round(documentationScore * 0.6 + usabilityScore * 0.4);
35
37
  // Determine status using Issue #55 thresholds
@@ -37,7 +39,7 @@ export class DeveloperExperienceAssessor extends BaseAssessor {
37
39
  // Generate explanation and recommendations
38
40
  const explanation = this.generateExplanation(documentationMetrics, usabilityMetrics, context.tools);
39
41
  const recommendations = this.generateRecommendations(documentationMetrics, usabilityMetrics);
40
- this.testCount = 15; // Documentation (5) + Quality (6) + Usability (4) checks
42
+ this.testCount = 16; // Documentation (5) + Quality (6) + Usability (4) + Namespace (1) checks
41
43
  return {
42
44
  documentation: documentationMetrics,
43
45
  usability: usabilityMetrics,
@@ -49,6 +51,7 @@ export class DeveloperExperienceAssessor extends BaseAssessor {
49
51
  usability: usabilityScore,
50
52
  overall: overallScore,
51
53
  },
54
+ namespaceDetection,
52
55
  };
53
56
  }
54
57
  // ============================================================================
@@ -673,6 +676,162 @@ export class DeveloperExperienceAssessor extends BaseAssessor {
673
676
  return Math.round((score / maxScore) * 100);
674
677
  }
675
678
  // ============================================================================
679
+ // Namespace Detection (Issue #142)
680
+ // ============================================================================
681
+ /**
682
+ * Detect namespace/prefix patterns in tool names.
683
+ * This helps identify intentional naming conventions like:
684
+ * - calc_add, calc_subtract -> namespace "calc"
685
+ * - fileRead, fileWrite -> namespace "file"
686
+ * - myserver_tool1, myserver_tool2 -> matches server name
687
+ */
688
+ detectNamespace(tools, serverName) {
689
+ const toolNames = tools.map((t) => t.name);
690
+ const totalTools = toolNames.length;
691
+ // Need at least 2 tools to detect a namespace
692
+ if (totalTools < 2) {
693
+ return {
694
+ detected: false,
695
+ confidence: "low",
696
+ toolsCovered: 0,
697
+ totalTools,
698
+ matchPattern: "none",
699
+ };
700
+ }
701
+ // Try server name prefix first (highest priority)
702
+ if (serverName) {
703
+ const serverNameResult = this.checkServerNamePrefix(toolNames, serverName);
704
+ if (serverNameResult.matches >= 2 &&
705
+ serverNameResult.matches / totalTools >= 0.5) {
706
+ return {
707
+ detected: true,
708
+ namespace: this.normalizeServerName(serverName),
709
+ confidence: "high",
710
+ toolsCovered: serverNameResult.matches,
711
+ totalTools,
712
+ matchPattern: "serverName",
713
+ evidence: serverNameResult.matchedTools.slice(0, 5),
714
+ };
715
+ }
716
+ }
717
+ // Try common prefix detection
718
+ const prefixResult = this.findCommonPrefix(toolNames);
719
+ if (prefixResult) {
720
+ const coverageRatio = prefixResult.count / totalTools;
721
+ const confidence = coverageRatio >= 0.5 ? "high" : coverageRatio >= 0.3 ? "medium" : "low";
722
+ if (prefixResult.count >= 2 && coverageRatio >= 0.3) {
723
+ return {
724
+ detected: true,
725
+ namespace: prefixResult.prefix,
726
+ confidence,
727
+ toolsCovered: prefixResult.count,
728
+ totalTools,
729
+ matchPattern: "prefix",
730
+ evidence: prefixResult.matchedTools.slice(0, 5),
731
+ };
732
+ }
733
+ }
734
+ // No namespace detected
735
+ return {
736
+ detected: false,
737
+ confidence: "low",
738
+ toolsCovered: 0,
739
+ totalTools,
740
+ matchPattern: "none",
741
+ };
742
+ }
743
+ /**
744
+ * Find common prefix among tool names.
745
+ * Handles both snake_case (calc_add) and camelCase (calcAdd) conventions.
746
+ */
747
+ findCommonPrefix(toolNames) {
748
+ if (toolNames.length < 2)
749
+ return null;
750
+ // Build prefix frequency map
751
+ const prefixCounts = new Map();
752
+ for (const name of toolNames) {
753
+ // Extract prefix using snake_case separator
754
+ const snakeMatch = name.match(/^([a-z]+)_/);
755
+ if (snakeMatch && snakeMatch[1].length >= 3) {
756
+ const prefix = snakeMatch[1];
757
+ if (!prefixCounts.has(prefix)) {
758
+ prefixCounts.set(prefix, []);
759
+ }
760
+ prefixCounts.get(prefix).push(name);
761
+ }
762
+ // Extract prefix using camelCase pattern
763
+ const camelMatch = name.match(/^([a-z]+)[A-Z]/);
764
+ if (camelMatch && camelMatch[1].length >= 3) {
765
+ const prefix = camelMatch[1];
766
+ if (!prefixCounts.has(prefix)) {
767
+ prefixCounts.set(prefix, []);
768
+ }
769
+ // Avoid double-counting if snake_case already found this name
770
+ const existing = prefixCounts.get(prefix);
771
+ if (!existing.includes(name)) {
772
+ existing.push(name);
773
+ }
774
+ }
775
+ }
776
+ // Find the prefix with the most matches
777
+ let bestPrefix = null;
778
+ let bestCount = 0;
779
+ let bestTools = [];
780
+ for (const [prefix, tools] of prefixCounts) {
781
+ if (tools.length > bestCount) {
782
+ bestPrefix = prefix;
783
+ bestCount = tools.length;
784
+ bestTools = tools;
785
+ }
786
+ }
787
+ if (bestPrefix && bestCount >= 2) {
788
+ return {
789
+ prefix: bestPrefix,
790
+ count: bestCount,
791
+ matchedTools: bestTools,
792
+ };
793
+ }
794
+ return null;
795
+ }
796
+ /**
797
+ * Check if tool names use the server name as a prefix.
798
+ * Normalizes server name to match common patterns.
799
+ */
800
+ checkServerNamePrefix(toolNames, serverName) {
801
+ const normalizedServerName = this.normalizeServerName(serverName);
802
+ const matchedTools = [];
803
+ for (const name of toolNames) {
804
+ const nameLower = name.toLowerCase();
805
+ // Check snake_case prefix (e.g., myserver_tool)
806
+ if (nameLower.startsWith(normalizedServerName + "_")) {
807
+ matchedTools.push(name);
808
+ continue;
809
+ }
810
+ // Check camelCase prefix (e.g., myserverTool)
811
+ if (nameLower.startsWith(normalizedServerName) &&
812
+ name.length > normalizedServerName.length &&
813
+ /[A-Z]/.test(name[normalizedServerName.length])) {
814
+ matchedTools.push(name);
815
+ continue;
816
+ }
817
+ // Check kebab-case prefix (e.g., myserver-tool)
818
+ if (nameLower.startsWith(normalizedServerName + "-")) {
819
+ matchedTools.push(name);
820
+ }
821
+ }
822
+ return {
823
+ matches: matchedTools.length,
824
+ matchedTools,
825
+ };
826
+ }
827
+ /**
828
+ * Normalize server name for prefix matching.
829
+ * Converts "My-Server" -> "myserver", "my_server" -> "myserver"
830
+ */
831
+ normalizeServerName(serverName) {
832
+ return serverName.toLowerCase().replace(/[-_\s]/g, "");
833
+ }
834
+ // ============================================================================
676
835
  // Combined Status, Explanation, and Recommendations
677
836
  // ============================================================================
678
837
  determineOverallStatus(overallScore) {
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorHandlingAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ErrorHandlingAssessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,uBAAuB,EAKxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAS9D,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,oBAAoB,CAAuB;gBAEvC,MAAM,EAAE,uBAAuB;IAMrC,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA0F1E,OAAO,CAAC,qBAAqB;YAuDf,qBAAqB;YA0BrB,qBAAqB;YAsGrB,cAAc;YAsFd,iBAAiB;YAiEjB,kBAAkB;IAgEhC,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,uBAAuB;IAkC/B,OAAO,CAAC,0BAA0B;IAkClC,OAAO,CAAC,uBAAuB;IA4B/B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,4BAA4B;IAgEpC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAc/B;;;OAGG;IACH,OAAO,CAAC,8BAA8B;IAetC,OAAO,CAAC,gBAAgB;IA8GxB,OAAO,CAAC,4BAA4B;IAapC,OAAO,CAAC,mBAAmB;IAuE3B,OAAO,CAAC,uBAAuB;CA4ChC"}
1
+ {"version":3,"file":"ErrorHandlingAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ErrorHandlingAssessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,uBAAuB,EAKxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAS9D,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,oBAAoB,CAAuB;gBAEvC,MAAM,EAAE,uBAAuB;IAMrC,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA6G1E,OAAO,CAAC,qBAAqB;YAuDf,qBAAqB;YA0BrB,qBAAqB;YAsGrB,cAAc;YAsFd,iBAAiB;YAiEjB,kBAAkB;IAgEhC,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,uBAAuB;IAkC/B,OAAO,CAAC,0BAA0B;IAkClC,OAAO,CAAC,uBAAuB;IA4B/B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,4BAA4B;IAgEpC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAc/B;;;OAGG;IACH,OAAO,CAAC,8BAA8B;IAetC,OAAO,CAAC,gBAAgB;IA8GxB,OAAO,CAAC,4BAA4B;IAapC,OAAO,CAAC,mBAAmB;IAuE3B,OAAO,CAAC,uBAAuB;CA4ChC"}
@@ -56,6 +56,14 @@ export class ErrorHandlingAssessor extends BaseAssessor {
56
56
  passedTests += toolTests.filter((t) => t.passed).length;
57
57
  }
58
58
  this.testCount = testDetails.length;
59
+ // Issue #153: Calculate test execution metadata for score validation
60
+ // Track which tools successfully produced test results vs failed due to connection errors
61
+ const totalToolsAttempted = toolsToTest.length;
62
+ const toolsWithResults = allToolTests.filter((tests) => tests.length > 0).length;
63
+ const connectionErrorCount = totalToolsAttempted - toolsWithResults;
64
+ const testCoveragePercent = totalToolsAttempted > 0
65
+ ? Math.round((toolsWithResults / totalToolsAttempted) * 100)
66
+ : 0;
59
67
  const metrics = this.calculateMetrics(testDetails, passedTests);
60
68
  const status = this.determineErrorHandlingStatus(metrics, testDetails.length);
61
69
  const explanation = this.generateExplanation(metrics, testDetails);
@@ -68,6 +76,13 @@ export class ErrorHandlingAssessor extends BaseAssessor {
68
76
  score: Math.round(metrics.mcpComplianceScore),
69
77
  explanation,
70
78
  recommendations,
79
+ // Issue #153: Test execution metadata for score validation
80
+ testExecutionMetadata: {
81
+ totalTestsAttempted: totalToolsAttempted,
82
+ validTestsCompleted: testDetails.length,
83
+ connectionErrorCount,
84
+ testCoveragePercent,
85
+ },
71
86
  };
72
87
  }
73
88
  selectToolsForTesting(tools) {
@@ -13,6 +13,13 @@
13
13
  import { BaseAssessor } from "./BaseAssessor.js";
14
14
  import { AssessmentContext } from "../AssessmentOrchestrator.js";
15
15
  import type { ManifestValidationAssessment } from "../../../lib/assessmentTypes.js";
16
+ /**
17
+ * Calculate Levenshtein distance between two strings
18
+ * Uses space-optimized two-row algorithm for O(min(n,m)) memory
19
+ * Used for "did you mean?" suggestions on mismatched tool names (Issue #140)
20
+ * Exported for testing (Issue #141 - ISSUE-002)
21
+ */
22
+ export declare function levenshteinDistance(a: string, b: string, maxDist?: number): number;
16
23
  export declare class ManifestValidationAssessor extends BaseAssessor {
17
24
  /**
18
25
  * Get mcp_config from manifest (supports both root and nested v0.3 format)
@@ -22,6 +29,21 @@ export declare class ManifestValidationAssessor extends BaseAssessor {
22
29
  * @returns The mcp_config object or undefined if not found in either location
23
30
  */
24
31
  private getMcpConfig;
32
+ /**
33
+ * Extract contact information from manifest (Issue #141 - D4 check)
34
+ * Supports: author object, author string (email parsing), repository fallback
35
+ *
36
+ * @param manifest - The parsed manifest JSON
37
+ * @returns Extracted contact info or undefined if no contact info found
38
+ */
39
+ private extractContactInfo;
40
+ /**
41
+ * Extract version information from manifest (Issue #141 - D5 check)
42
+ *
43
+ * @param manifest - The parsed manifest JSON
44
+ * @returns Extracted version info or undefined if no version found
45
+ */
46
+ private extractVersionInfo;
25
47
  /**
26
48
  * Run manifest validation assessment
27
49
  */
@@ -62,6 +84,16 @@ export declare class ManifestValidationAssessor extends BaseAssessor {
62
84
  * Validate version format (semver)
63
85
  */
64
86
  private validateVersionFormat;
87
+ /**
88
+ * Validate manifest tool declarations against actual server tools (Issue #140)
89
+ * Compares tool names in manifest.tools against context.tools from tools/list
90
+ * Uses Levenshtein distance for "did you mean?" suggestions
91
+ */
92
+ private validateToolNamesMatch;
93
+ /**
94
+ * Fetch with retry logic for transient network failures
95
+ */
96
+ private fetchWithRetry;
65
97
  /**
66
98
  * Validate privacy policy URLs are accessible
67
99
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ManifestValidationAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ManifestValidationAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EACV,4BAA4B,EAM7B,MAAM,uBAAuB,CAAC;AAM/B,qBAAa,0BAA2B,SAAQ,YAAY;IAC1D;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAcpB;;OAEG;IACG,MAAM,CACV,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,4BAA4B,CAAC;IAqLxC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAyB9B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAmB/B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAgC/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAiC7B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAiChC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+CzB;;OAEG;IACH,OAAO,CAAC,YAAY;IAqCpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA+B1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA8B7B;;OAEG;YACW,yBAAyB;IAqFvC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAsB/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA0C3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;CA+ChC"}
1
+ {"version":3,"file":"ManifestValidationAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ManifestValidationAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,KAAK,EACV,4BAA4B,EAS7B,MAAM,uBAAuB,CAAC;AAO/B;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAwCR;AA+BD,qBAAa,0BAA2B,SAAQ,YAAY;IAC1D;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAcpB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAqC1B;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAY1B;;OAEG;IACG,MAAM,CACV,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,4BAA4B,CAAC;IAiMxC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAyB9B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAmB/B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAgC/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAiC7B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAiChC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+CzB;;OAEG;IACH,OAAO,CAAC,YAAY;IAqCpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA+B1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA4B7B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAyE9B;;OAEG;YACW,cAAc;IAuC5B;;OAEG;YACW,yBAAyB;IAmEvC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAsB/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA0C3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;CA+ChC"}