@kevinrabun/judges 3.115.4 → 3.117.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/accessibility.judge.md +7 -0
- package/agents/agent-instructions.judge.md +7 -0
- package/agents/ai-code-safety.judge.md +7 -0
- package/agents/api-contract.judge.md +7 -0
- package/agents/api-design.judge.md +7 -0
- package/agents/authentication.judge.md +7 -0
- package/agents/backwards-compatibility.judge.md +7 -0
- package/agents/caching.judge.md +7 -0
- package/agents/ci-cd.judge.md +7 -0
- package/agents/cloud-readiness.judge.md +7 -0
- package/agents/concurrency.judge.md +7 -0
- package/agents/configuration-management.judge.md +7 -0
- package/agents/cybersecurity.judge.md +7 -0
- package/agents/data-security.judge.md +7 -0
- package/agents/dependency-health.judge.md +7 -0
- package/agents/documentation.judge.md +7 -0
- package/agents/error-handling.judge.md +7 -0
- package/agents/ethics-bias.judge.md +7 -0
- package/agents/false-positive-review.judge.md +12 -0
- package/agents/framework-safety.judge.md +7 -0
- package/agents/hallucination-detection.judge.md +13 -0
- package/agents/iac-security.judge.md +7 -0
- package/agents/intent-alignment.judge.md +13 -0
- package/agents/logging-privacy.judge.md +7 -0
- package/agents/maintainability.judge.md +7 -0
- package/agents/multi-turn-coherence.judge.md +7 -0
- package/agents/observability.judge.md +7 -0
- package/agents/portability.judge.md +7 -0
- package/agents/rate-limiting.judge.md +7 -0
- package/agents/reliability.judge.md +7 -0
- package/agents/security.judge.md +13 -0
- package/agents/testing.judge.md +7 -0
- package/agents/ux.judge.md +7 -0
- package/dist/a2a-protocol.d.ts +136 -0
- package/dist/a2a-protocol.js +218 -0
- package/dist/api.d.ts +21 -3
- package/dist/api.js +21 -1
- package/dist/audit-trail.d.ts +245 -0
- package/dist/audit-trail.js +257 -0
- package/dist/commands/benchmark-advanced.js +51 -51
- package/dist/commands/benchmark-ai-agents.js +16 -16
- package/dist/commands/benchmark-compliance-ethics.js +12 -12
- package/dist/commands/benchmark-expanded-2.js +2 -2
- package/dist/commands/benchmark-expanded.js +2 -2
- package/dist/commands/benchmark-infrastructure.js +12 -12
- package/dist/commands/benchmark-languages.js +11 -11
- package/dist/commands/benchmark-quality-ops.js +7 -7
- package/dist/commands/benchmark-security-deep.js +9 -9
- package/dist/commands/benchmark.js +1 -1
- package/dist/commands/llm-benchmark-optimizer.d.ts +78 -0
- package/dist/commands/llm-benchmark-optimizer.js +241 -0
- package/dist/commands/llm-benchmark.d.ts +4 -2
- package/dist/commands/llm-benchmark.js +40 -12
- package/dist/escalation.d.ts +100 -0
- package/dist/escalation.js +292 -0
- package/dist/evaluation-session.d.ts +74 -0
- package/dist/evaluation-session.js +152 -0
- package/dist/evaluators/index.d.ts +23 -1
- package/dist/evaluators/index.js +192 -3
- package/dist/evaluators/judge-selector.d.ts +19 -0
- package/dist/evaluators/judge-selector.js +141 -0
- package/dist/evaluators/recall-boost.d.ts +27 -0
- package/dist/evaluators/recall-boost.js +409 -0
- package/dist/feedback-loop.d.ts +62 -0
- package/dist/feedback-loop.js +179 -0
- package/dist/index.js +2 -0
- package/dist/judges/accessibility.js +7 -0
- package/dist/judges/agent-instructions.js +7 -0
- package/dist/judges/ai-code-safety.js +7 -0
- package/dist/judges/api-contract.js +7 -0
- package/dist/judges/api-design.js +7 -0
- package/dist/judges/authentication.js +7 -0
- package/dist/judges/backwards-compatibility.js +7 -0
- package/dist/judges/caching.js +7 -0
- package/dist/judges/ci-cd.js +7 -0
- package/dist/judges/cloud-readiness.js +7 -0
- package/dist/judges/concurrency.js +7 -0
- package/dist/judges/configuration-management.js +7 -0
- package/dist/judges/cybersecurity.js +7 -0
- package/dist/judges/data-security.js +7 -0
- package/dist/judges/dependency-health.js +7 -0
- package/dist/judges/documentation.js +7 -0
- package/dist/judges/error-handling.js +7 -0
- package/dist/judges/ethics-bias.js +7 -0
- package/dist/judges/false-positive-review.js +13 -1
- package/dist/judges/framework-safety.js +7 -0
- package/dist/judges/hallucination-detection.js +14 -1
- package/dist/judges/iac-security.js +7 -0
- package/dist/judges/intent-alignment.js +14 -1
- package/dist/judges/logging-privacy.js +7 -0
- package/dist/judges/maintainability.js +7 -0
- package/dist/judges/multi-turn-coherence.js +7 -0
- package/dist/judges/observability.js +7 -0
- package/dist/judges/portability.js +7 -0
- package/dist/judges/rate-limiting.js +7 -0
- package/dist/judges/reliability.js +7 -0
- package/dist/judges/security.js +14 -1
- package/dist/judges/testing.js +7 -0
- package/dist/judges/ux.js +7 -0
- package/dist/review-conversation.d.ts +87 -0
- package/dist/review-conversation.js +307 -0
- package/dist/sast-integration.d.ts +112 -0
- package/dist/sast-integration.js +215 -0
- package/dist/tools/register-evaluation.js +208 -8
- package/dist/tools/register-fix.js +24 -1
- package/dist/tools/register-resources.d.ts +6 -0
- package/dist/tools/register-resources.js +177 -0
- package/dist/tools/register-review.js +26 -1
- package/dist/tools/register-workflow.js +384 -11
- package/dist/tools/validation.d.ts +13 -0
- package/dist/tools/validation.js +77 -0
- package/dist/types.d.ts +122 -0
- package/package.json +25 -12
- package/server.json +2 -2
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recall Booster — Additional detection patterns for weak-recall categories
|
|
3
|
+
*
|
|
4
|
+
* This module provides supplementary pattern detection for judge categories
|
|
5
|
+
* where the deterministic evaluators have recall below 85%. It acts as
|
|
6
|
+
* a second-pass augmentation applied after the primary evaluator.
|
|
7
|
+
*
|
|
8
|
+
* Categories strengthened (by recall gap analysis):
|
|
9
|
+
* - hallucination-detection (46.2% → improved)
|
|
10
|
+
* - ci-cd (41.7% → improved)
|
|
11
|
+
* - internationalization (42.9% → improved)
|
|
12
|
+
* - cost-effectiveness (57.1% → improved)
|
|
13
|
+
* - documentation (63.6% → improved)
|
|
14
|
+
* - iac-security (66.7% → improved)
|
|
15
|
+
* - cloud/cloud-readiness (50-73% → improved)
|
|
16
|
+
*/
|
|
17
|
+
import { getLangFamily } from "./shared.js";
|
|
18
|
+
// ─── Hallucination Detection Extras ──────────────────────────────────────────
|
|
19
|
+
const EXTRA_HALLUCINATION_PATTERNS = [
|
|
20
|
+
// Python: common hallucinated built-in functions
|
|
21
|
+
{
|
|
22
|
+
pattern: /\bstr\.isinteger\s*\(/,
|
|
23
|
+
title: "Hallucinated Python str.isinteger()",
|
|
24
|
+
description: "Python str has no isinteger() method. LLMs confuse this with float.is_integer() or str.isdigit().",
|
|
25
|
+
fix: "Use str.isdigit() for digit check, or float(s).is_integer() for integer check.",
|
|
26
|
+
languages: ["python"],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
pattern: /\blist\.contains\s*\(/,
|
|
30
|
+
title: "Hallucinated Python list.contains()",
|
|
31
|
+
description: "Python lists have no contains() method. Use the `in` operator instead.",
|
|
32
|
+
fix: "Replace `list.contains(x)` with `x in list`.",
|
|
33
|
+
languages: ["python"],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
pattern: /\bdict\.has_key\s*\(/,
|
|
37
|
+
title: "Deprecated/hallucinated dict.has_key()",
|
|
38
|
+
description: "dict.has_key() was removed in Python 3. LLMs trained on mixed Python 2/3 code still generate it.",
|
|
39
|
+
fix: "Use `key in dict` instead of `dict.has_key(key)`.",
|
|
40
|
+
languages: ["python"],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
pattern: /\bimport\s+asyncio\b[\s\S]{0,200}\basyncio\.sleep_ms\s*\(/,
|
|
44
|
+
title: "Hallucinated asyncio.sleep_ms()",
|
|
45
|
+
description: "asyncio has no sleep_ms(). LLMs confuse this with asyncio.sleep() which takes seconds.",
|
|
46
|
+
fix: "Use `await asyncio.sleep(ms / 1000)` for millisecond sleep.",
|
|
47
|
+
languages: ["python"],
|
|
48
|
+
},
|
|
49
|
+
// Node.js: fabricated API patterns
|
|
50
|
+
{
|
|
51
|
+
pattern: /\bprocess\.env\.getAll\s*\(/,
|
|
52
|
+
title: "Hallucinated process.env.getAll()",
|
|
53
|
+
description: "Node.js process.env has no getAll() method. It's a plain object.",
|
|
54
|
+
fix: "Use Object.entries(process.env) to get all environment variables.",
|
|
55
|
+
languages: ["javascript", "typescript"],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
pattern: /\bJSON\.tryParse\s*\(/,
|
|
59
|
+
title: "Hallucinated JSON.tryParse()",
|
|
60
|
+
description: "JavaScript has no JSON.tryParse(). This is a common .NET/C# pattern hallucinated into JS.",
|
|
61
|
+
fix: "Wrap JSON.parse() in a try/catch block for safe parsing.",
|
|
62
|
+
languages: ["javascript", "typescript"],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
pattern: /\bArray\.flatten\s*\(/,
|
|
66
|
+
title: "Hallucinated Array.flatten()",
|
|
67
|
+
description: "JavaScript Array has no static flatten() method. The instance method is .flat().",
|
|
68
|
+
fix: "Use `array.flat()` or `array.flat(Infinity)` for deep flattening.",
|
|
69
|
+
languages: ["javascript", "typescript"],
|
|
70
|
+
},
|
|
71
|
+
// Go: common hallucinations
|
|
72
|
+
{
|
|
73
|
+
pattern: /\bstrings\.Reverse\s*\(/,
|
|
74
|
+
title: "Hallucinated strings.Reverse()",
|
|
75
|
+
description: "Go strings package has no Reverse function. LLMs frequently hallucinate this.",
|
|
76
|
+
fix: "Implement string reversal manually using rune conversion: []rune(s).",
|
|
77
|
+
languages: ["go"],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
pattern: /\berrors\.Wrapf?\s*\(/,
|
|
81
|
+
title: "Hallucinated errors.Wrap()",
|
|
82
|
+
description: "Go standard errors package has no Wrap function. This was from pkg/errors (deprecated).",
|
|
83
|
+
fix: 'Use fmt.Errorf("%w", err) for error wrapping (Go 1.13+).',
|
|
84
|
+
languages: ["go"],
|
|
85
|
+
},
|
|
86
|
+
// Rust: hallucinated trait methods
|
|
87
|
+
{
|
|
88
|
+
pattern: /\.to_str\(\)\s*\.unwrap\(\)/,
|
|
89
|
+
title: "Potentially hallucinated .to_str().unwrap() chain",
|
|
90
|
+
description: "LLMs frequently chain .to_str().unwrap() on types that don't implement to_str(). Verify the type has this method.",
|
|
91
|
+
fix: "Consider using .to_string() or .as_str() depending on the actual type.",
|
|
92
|
+
languages: ["rust"],
|
|
93
|
+
},
|
|
94
|
+
// Java: hallucinated APIs
|
|
95
|
+
{
|
|
96
|
+
pattern: /\bString\.isEmpty\s*\(\s*\w+\s*\)/,
|
|
97
|
+
title: "Hallucinated static String.isEmpty()",
|
|
98
|
+
description: "Java String.isEmpty() is an instance method, not static. LLMs sometimes generate static calls.",
|
|
99
|
+
fix: "Use `str.isEmpty()` as an instance method call.",
|
|
100
|
+
languages: ["java"],
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
// ─── CI/CD Detection Extras ──────────────────────────────────────────────────
|
|
104
|
+
const EXTRA_CICD_PATTERNS = [
|
|
105
|
+
{
|
|
106
|
+
pattern: /\bpipeline\b[\s\S]{0,100}checkout:\s*none/i,
|
|
107
|
+
title: "Pipeline skips source checkout",
|
|
108
|
+
description: "CI pipeline configured to skip source checkout. This may indicate a misconfiguration.",
|
|
109
|
+
languages: ["yaml"],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
pattern: /\bcurl\b[\s\S]{0,50}\|\s*(?:bash|sh)\b/,
|
|
113
|
+
title: "Piping curl to shell in CI",
|
|
114
|
+
description: "Downloading and directly executing scripts via curl|bash is a supply-chain risk in CI/CD pipelines.",
|
|
115
|
+
languages: ["yaml", "bash", "dockerfile"],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
pattern: /\b(?:npm|pip|cargo)\s+install\b[\s\S]{0,30}--no-verify/i,
|
|
119
|
+
title: "Package install with verification disabled",
|
|
120
|
+
description: "Installing packages with verification disabled weakens supply-chain integrity in CI.",
|
|
121
|
+
languages: ["yaml", "bash", "dockerfile"],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
pattern: /\bsudo\s+.*\b(?:chmod\s+777|chmod\s+a\+rwx)\b/,
|
|
125
|
+
title: "Overly permissive chmod in CI script",
|
|
126
|
+
description: "Setting 777 permissions in CI/CD scripts creates security risks on shared runners.",
|
|
127
|
+
languages: ["yaml", "bash"],
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
// ─── Internationalization Detection Extras ────────────────────────────────────
|
|
131
|
+
const EXTRA_I18N_PATTERNS = [
|
|
132
|
+
{
|
|
133
|
+
pattern: /\.toLocaleDateString\s*\(\s*\)/,
|
|
134
|
+
title: "toLocaleDateString() without explicit locale",
|
|
135
|
+
description: "Calling toLocaleDateString() without a locale parameter uses the system default, producing inconsistent date formats across environments.",
|
|
136
|
+
languages: ["javascript", "typescript"],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
pattern: /new\s+Intl\.NumberFormat\s*\(\s*\)/,
|
|
140
|
+
title: "Intl.NumberFormat without explicit locale",
|
|
141
|
+
description: "Creating NumberFormat without a locale uses system default, inconsistent across deployments.",
|
|
142
|
+
languages: ["javascript", "typescript"],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
pattern: /\bcurrency\s*[:=]\s*["'](?:USD|EUR|GBP)["'][\s\S]{0,100}(?:format|display|render)/i,
|
|
146
|
+
title: "Hardcoded currency code",
|
|
147
|
+
description: "Currency code is hardcoded rather than derived from user locale or configuration.",
|
|
148
|
+
languages: ["javascript", "typescript", "python", "java"],
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
pattern: /\.(?:trim|split|substring)\([\s\S]{0,30}(?:first|last)\s*name/i,
|
|
152
|
+
title: "Culturally-biased name parsing",
|
|
153
|
+
description: "Splitting names into first/last assumes Western naming conventions. Many cultures use single names, family-name-first order, or multiple name components.",
|
|
154
|
+
languages: ["javascript", "typescript", "python", "java", "csharp"],
|
|
155
|
+
},
|
|
156
|
+
];
|
|
157
|
+
// ─── Cost-Effectiveness Detection Extras ─────────────────────────────────────
|
|
158
|
+
const EXTRA_COST_PATTERNS = [
|
|
159
|
+
{
|
|
160
|
+
pattern: /\bnew\s+Date\(\)[\s\S]{0,30}while\s*\(/,
|
|
161
|
+
title: "Busy-wait loop with Date() polling",
|
|
162
|
+
description: "Busy-wait loops waste CPU cycles and increase compute costs. Use async timers instead.",
|
|
163
|
+
languages: ["javascript", "typescript"],
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
pattern: /\bsetInterval\s*\([^,]+,\s*(?:100|50|10|1)\s*\)/,
|
|
167
|
+
title: "Very frequent interval (≤100ms)",
|
|
168
|
+
description: "Very frequent setInterval polling wastes CPU/battery. Consider event-driven approaches or longer intervals.",
|
|
169
|
+
languages: ["javascript", "typescript"],
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
pattern: /SELECT\s+\*\s+FROM[\s\S]{0,50}(?:JOIN|,\s*\w+)/i,
|
|
173
|
+
title: "SELECT * with JOINs",
|
|
174
|
+
description: "Using SELECT * with JOINs retrieves all columns from all joined tables, significantly increasing data transfer and memory costs.",
|
|
175
|
+
languages: ["sql", "python", "javascript", "typescript", "java", "csharp"],
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
pattern: /\.(?:map|forEach|filter)\s*\([\s\S]{0,100}\.(?:map|forEach|filter)\s*\(/,
|
|
179
|
+
title: "Nested array iterations",
|
|
180
|
+
description: "Chained .map/.filter/.forEach calls iterate the array multiple times. Consider combining into a single pass with .reduce().",
|
|
181
|
+
languages: ["javascript", "typescript"],
|
|
182
|
+
},
|
|
183
|
+
];
|
|
184
|
+
// ─── IaC Security Extras ─────────────────────────────────────────────────────
|
|
185
|
+
const EXTRA_IAC_PATTERNS = [
|
|
186
|
+
{
|
|
187
|
+
pattern: /\bpublic_network_access_enabled\s*=\s*true/i,
|
|
188
|
+
title: "Public network access enabled on Azure resource",
|
|
189
|
+
description: "Enabling public network access exposes the resource to the internet. Use private endpoints instead.",
|
|
190
|
+
languages: ["terraform", "bicep"],
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
pattern: /\bingress\b[\s\S]{0,100}\bcidr_blocks\s*=\s*\[\s*["']0\.0\.0\.0\/0["']\s*\]/,
|
|
194
|
+
title: "Security group allows all inbound traffic (0.0.0.0/0)",
|
|
195
|
+
description: "Ingress rule allows traffic from any IP. Restrict to specific CIDR ranges.",
|
|
196
|
+
languages: ["terraform"],
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
pattern: /\bsku\b[\s\S]{0,30}(?:Basic|Free)\b/i,
|
|
200
|
+
title: "Using Basic/Free SKU in production IaC",
|
|
201
|
+
description: "Basic/Free tier SKUs often lack security features like encryption, private endpoints, and SLA guarantees.",
|
|
202
|
+
languages: ["terraform", "bicep", "arm"],
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
pattern: /\bretention_in_days\s*[:=]\s*(?:0|1|7)\b/,
|
|
206
|
+
title: "Short log retention period",
|
|
207
|
+
description: "Log retention of 7 days or less may be insufficient for security investigation and compliance requirements.",
|
|
208
|
+
languages: ["terraform", "bicep"],
|
|
209
|
+
},
|
|
210
|
+
];
|
|
211
|
+
// ─── Documentation Detection Extras ──────────────────────────────────────────
|
|
212
|
+
const EXTRA_DOC_PATTERNS = [
|
|
213
|
+
{
|
|
214
|
+
pattern: /(?:TODO|FIXME|HACK|XXX|TEMP)\s*[:!]/i,
|
|
215
|
+
title: "Unresolved TODO/FIXME/HACK comment",
|
|
216
|
+
description: "Code contains unresolved TODO/FIXME/HACK markers indicating incomplete implementation or known issues.",
|
|
217
|
+
languages: ["javascript", "typescript", "python", "java", "csharp", "go", "rust", "ruby", "php"],
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
pattern: /export\s+(?:default\s+)?(?:function|class|const)\s+\w+[\s\S]{0,50}\{[\s\S]{50,}(?:throw|return|if)\b/,
|
|
221
|
+
title: "Complex exported function without JSDoc/docstring",
|
|
222
|
+
description: "Public API function with complex logic lacks documentation. This makes the API hard to use correctly.",
|
|
223
|
+
languages: ["javascript", "typescript"],
|
|
224
|
+
},
|
|
225
|
+
];
|
|
226
|
+
// ─── Cloud Readiness Extras ──────────────────────────────────────────────────
|
|
227
|
+
const EXTRA_CLOUD_PATTERNS = [
|
|
228
|
+
{
|
|
229
|
+
pattern: /\bfs\.(?:writeFileSync|appendFileSync)\s*\(\s*["']\/(?:tmp|var|data)\//,
|
|
230
|
+
title: "Writing to local filesystem path",
|
|
231
|
+
description: "Writing to local filesystem paths (/tmp, /var, /data) is not reliable in containerized or serverless environments. Use object storage or managed databases.",
|
|
232
|
+
languages: ["javascript", "typescript"],
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
pattern: /\bopen\s*\(\s*["']\/(?:tmp|var|data)\//,
|
|
236
|
+
title: "Writing to local filesystem path",
|
|
237
|
+
description: "Writing to local filesystem paths is not reliable in cloud/container environments.",
|
|
238
|
+
languages: ["python"],
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
pattern: /\b(?:127\.0\.0\.1|localhost)\b[\s\S]{0,30}(?:connect|host|url|endpoint)/i,
|
|
242
|
+
title: "Hardcoded localhost reference",
|
|
243
|
+
description: "Hardcoded localhost/127.0.0.1 references will fail in containerized deployments where services run on separate hosts.",
|
|
244
|
+
languages: ["javascript", "typescript", "python", "java", "go", "csharp"],
|
|
245
|
+
},
|
|
246
|
+
];
|
|
247
|
+
/**
|
|
248
|
+
* Apply recall-boosting patterns to detect issues that primary evaluators miss.
|
|
249
|
+
* Returns additional findings (does not modify existing ones).
|
|
250
|
+
*/
|
|
251
|
+
export function applyRecallBoost(code, language) {
|
|
252
|
+
const lang = getLangFamily(language);
|
|
253
|
+
const findings = [];
|
|
254
|
+
const boostedCategories = [];
|
|
255
|
+
const lines = code.split("\n");
|
|
256
|
+
function getMatchLines(pattern) {
|
|
257
|
+
const matched = [];
|
|
258
|
+
for (let i = 0; i < lines.length; i++) {
|
|
259
|
+
if (pattern.test(lines[i]))
|
|
260
|
+
matched.push(i + 1);
|
|
261
|
+
pattern.lastIndex = 0;
|
|
262
|
+
}
|
|
263
|
+
return matched;
|
|
264
|
+
}
|
|
265
|
+
// Hallucination boost
|
|
266
|
+
let halluNum = 900;
|
|
267
|
+
for (const p of EXTRA_HALLUCINATION_PATTERNS) {
|
|
268
|
+
if (!p.languages.includes(lang))
|
|
269
|
+
continue;
|
|
270
|
+
const matchLines = getMatchLines(p.pattern);
|
|
271
|
+
if (matchLines.length > 0) {
|
|
272
|
+
if (!boostedCategories.includes("hallucination-detection"))
|
|
273
|
+
boostedCategories.push("hallucination-detection");
|
|
274
|
+
findings.push({
|
|
275
|
+
ruleId: `HALLU-${String(halluNum++).padStart(3, "0")}`,
|
|
276
|
+
severity: "high",
|
|
277
|
+
title: p.title,
|
|
278
|
+
description: p.description,
|
|
279
|
+
lineNumbers: matchLines,
|
|
280
|
+
recommendation: p.fix,
|
|
281
|
+
reference: "AI Code Generation: Hallucinated API Detection",
|
|
282
|
+
confidence: 0.85,
|
|
283
|
+
provenance: "regex-pattern-match",
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// CI/CD boost
|
|
288
|
+
let cicdNum = 900;
|
|
289
|
+
for (const p of EXTRA_CICD_PATTERNS) {
|
|
290
|
+
if (!p.languages.includes(lang))
|
|
291
|
+
continue;
|
|
292
|
+
if (p.pattern.test(code)) {
|
|
293
|
+
if (!boostedCategories.includes("ci-cd"))
|
|
294
|
+
boostedCategories.push("ci-cd");
|
|
295
|
+
findings.push({
|
|
296
|
+
ruleId: `CICD-${String(cicdNum++).padStart(3, "0")}`,
|
|
297
|
+
severity: "medium",
|
|
298
|
+
title: p.title,
|
|
299
|
+
description: p.description,
|
|
300
|
+
lineNumbers: getMatchLines(p.pattern),
|
|
301
|
+
recommendation: "Review and remediate this CI/CD configuration issue.",
|
|
302
|
+
confidence: 0.75,
|
|
303
|
+
provenance: "regex-pattern-match",
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// I18N boost
|
|
308
|
+
let i18nNum = 900;
|
|
309
|
+
for (const p of EXTRA_I18N_PATTERNS) {
|
|
310
|
+
if (!p.languages.includes(lang))
|
|
311
|
+
continue;
|
|
312
|
+
const matchLines = getMatchLines(p.pattern);
|
|
313
|
+
if (matchLines.length > 0) {
|
|
314
|
+
if (!boostedCategories.includes("internationalization"))
|
|
315
|
+
boostedCategories.push("internationalization");
|
|
316
|
+
findings.push({
|
|
317
|
+
ruleId: `I18N-${String(i18nNum++).padStart(3, "0")}`,
|
|
318
|
+
severity: "medium",
|
|
319
|
+
title: p.title,
|
|
320
|
+
description: p.description,
|
|
321
|
+
lineNumbers: matchLines,
|
|
322
|
+
recommendation: "Ensure locale-awareness for international users.",
|
|
323
|
+
confidence: 0.7,
|
|
324
|
+
provenance: "regex-pattern-match",
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// Cost-effectiveness boost
|
|
329
|
+
let costNum = 900;
|
|
330
|
+
for (const p of EXTRA_COST_PATTERNS) {
|
|
331
|
+
if (!p.languages.includes(lang))
|
|
332
|
+
continue;
|
|
333
|
+
if (p.pattern.test(code)) {
|
|
334
|
+
if (!boostedCategories.includes("cost-effectiveness"))
|
|
335
|
+
boostedCategories.push("cost-effectiveness");
|
|
336
|
+
findings.push({
|
|
337
|
+
ruleId: `COST-${String(costNum++).padStart(3, "0")}`,
|
|
338
|
+
severity: "medium",
|
|
339
|
+
title: p.title,
|
|
340
|
+
description: p.description,
|
|
341
|
+
lineNumbers: getMatchLines(p.pattern),
|
|
342
|
+
recommendation: "Consider more cost-efficient alternatives.",
|
|
343
|
+
confidence: 0.75,
|
|
344
|
+
provenance: "regex-pattern-match",
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// IaC security boost
|
|
349
|
+
let iacNum = 900;
|
|
350
|
+
for (const p of EXTRA_IAC_PATTERNS) {
|
|
351
|
+
if (!p.languages.includes(lang))
|
|
352
|
+
continue;
|
|
353
|
+
if (p.pattern.test(code)) {
|
|
354
|
+
if (!boostedCategories.includes("iac-security"))
|
|
355
|
+
boostedCategories.push("iac-security");
|
|
356
|
+
findings.push({
|
|
357
|
+
ruleId: `IAC-${String(iacNum++).padStart(3, "0")}`,
|
|
358
|
+
severity: "high",
|
|
359
|
+
title: p.title,
|
|
360
|
+
description: p.description,
|
|
361
|
+
lineNumbers: getMatchLines(p.pattern),
|
|
362
|
+
recommendation: "Apply infrastructure security best practices.",
|
|
363
|
+
confidence: 0.8,
|
|
364
|
+
provenance: "regex-pattern-match",
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
// Documentation boost
|
|
369
|
+
let docNum = 900;
|
|
370
|
+
for (const p of EXTRA_DOC_PATTERNS) {
|
|
371
|
+
if (!p.languages.includes(lang))
|
|
372
|
+
continue;
|
|
373
|
+
if (p.pattern.test(code)) {
|
|
374
|
+
if (!boostedCategories.includes("documentation"))
|
|
375
|
+
boostedCategories.push("documentation");
|
|
376
|
+
findings.push({
|
|
377
|
+
ruleId: `DOC-${String(docNum++).padStart(3, "0")}`,
|
|
378
|
+
severity: "low",
|
|
379
|
+
title: p.title,
|
|
380
|
+
description: p.description,
|
|
381
|
+
lineNumbers: getMatchLines(p.pattern),
|
|
382
|
+
recommendation: "Improve documentation for maintainability.",
|
|
383
|
+
confidence: 0.7,
|
|
384
|
+
provenance: "regex-pattern-match",
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// Cloud readiness boost
|
|
389
|
+
let cloudNum = 900;
|
|
390
|
+
for (const p of EXTRA_CLOUD_PATTERNS) {
|
|
391
|
+
if (!p.languages.includes(lang))
|
|
392
|
+
continue;
|
|
393
|
+
if (p.pattern.test(code)) {
|
|
394
|
+
if (!boostedCategories.includes("cloud-readiness"))
|
|
395
|
+
boostedCategories.push("cloud-readiness");
|
|
396
|
+
findings.push({
|
|
397
|
+
ruleId: `CLOUD-${String(cloudNum++).padStart(3, "0")}`,
|
|
398
|
+
severity: "medium",
|
|
399
|
+
title: p.title,
|
|
400
|
+
description: p.description,
|
|
401
|
+
lineNumbers: getMatchLines(p.pattern),
|
|
402
|
+
recommendation: "Design for cloud-native deployment.",
|
|
403
|
+
confidence: 0.75,
|
|
404
|
+
provenance: "regex-pattern-match",
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return { findings, boostedCategories };
|
|
409
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fix-Outcome Feedback Loop
|
|
3
|
+
*
|
|
4
|
+
* Closes the feedback loop between fix acceptance/rejection data and
|
|
5
|
+
* the calibration system. When developers accept or reject suggested
|
|
6
|
+
* fixes, that signal feeds back into confidence calibration:
|
|
7
|
+
*
|
|
8
|
+
* - Accepted fixes → "true positive" signal → boost confidence for that rule
|
|
9
|
+
* - Rejected fixes → possible FP signal → reduce confidence for that rule
|
|
10
|
+
* - Reverted fixes → strong FP signal → significantly reduce confidence
|
|
11
|
+
*
|
|
12
|
+
* This module runs periodically (or on-demand) to:
|
|
13
|
+
* 1. Read fix history outcomes
|
|
14
|
+
* 2. Convert them into calibration-compatible feedback entries
|
|
15
|
+
* 3. Update the feedback store so calibration picks them up
|
|
16
|
+
* 4. Compute per-rule confidence adjustments
|
|
17
|
+
* 5. Generate a summary report of the feedback loop's impact
|
|
18
|
+
*/
|
|
19
|
+
import { type CalibrationProfile, type CalibrationOptions } from "./calibration.js";
|
|
20
|
+
export interface FeedbackLoopResult {
|
|
21
|
+
/** Number of fix outcomes processed */
|
|
22
|
+
outcomesProcessed: number;
|
|
23
|
+
/** Number of new feedback entries created */
|
|
24
|
+
feedbackEntriesCreated: number;
|
|
25
|
+
/** Per-rule confidence adjustments recommended */
|
|
26
|
+
adjustments: ConfidenceAdjustment[];
|
|
27
|
+
/** Summary statistics */
|
|
28
|
+
stats: FeedbackLoopStats;
|
|
29
|
+
/** Calibration profile after updates */
|
|
30
|
+
calibrationProfile: CalibrationProfile;
|
|
31
|
+
}
|
|
32
|
+
export interface ConfidenceAdjustment {
|
|
33
|
+
ruleId: string;
|
|
34
|
+
currentConfidence: number;
|
|
35
|
+
recommendedConfidence: number;
|
|
36
|
+
direction: "boost" | "reduce" | "stable";
|
|
37
|
+
reason: string;
|
|
38
|
+
sampleCount: number;
|
|
39
|
+
}
|
|
40
|
+
export interface FeedbackLoopStats {
|
|
41
|
+
totalOutcomes: number;
|
|
42
|
+
accepted: number;
|
|
43
|
+
rejected: number;
|
|
44
|
+
reverted: number;
|
|
45
|
+
rulesWithPositiveSignal: number;
|
|
46
|
+
rulesWithNegativeSignal: number;
|
|
47
|
+
netCalibrationImpact: "positive" | "negative" | "neutral";
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Process fix history and generate calibration feedback.
|
|
51
|
+
* This is the main entry point for the feedback loop.
|
|
52
|
+
*/
|
|
53
|
+
export declare function runFeedbackLoop(options?: {
|
|
54
|
+
fixHistoryDir?: string;
|
|
55
|
+
feedbackDir?: string;
|
|
56
|
+
calibrationOptions?: CalibrationOptions;
|
|
57
|
+
dryRun?: boolean;
|
|
58
|
+
}): FeedbackLoopResult;
|
|
59
|
+
/**
|
|
60
|
+
* Generate a markdown report of the feedback loop results.
|
|
61
|
+
*/
|
|
62
|
+
export declare function formatFeedbackLoopReport(result: FeedbackLoopResult): string;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fix-Outcome Feedback Loop
|
|
3
|
+
*
|
|
4
|
+
* Closes the feedback loop between fix acceptance/rejection data and
|
|
5
|
+
* the calibration system. When developers accept or reject suggested
|
|
6
|
+
* fixes, that signal feeds back into confidence calibration:
|
|
7
|
+
*
|
|
8
|
+
* - Accepted fixes → "true positive" signal → boost confidence for that rule
|
|
9
|
+
* - Rejected fixes → possible FP signal → reduce confidence for that rule
|
|
10
|
+
* - Reverted fixes → strong FP signal → significantly reduce confidence
|
|
11
|
+
*
|
|
12
|
+
* This module runs periodically (or on-demand) to:
|
|
13
|
+
* 1. Read fix history outcomes
|
|
14
|
+
* 2. Convert them into calibration-compatible feedback entries
|
|
15
|
+
* 3. Update the feedback store so calibration picks them up
|
|
16
|
+
* 4. Compute per-rule confidence adjustments
|
|
17
|
+
* 5. Generate a summary report of the feedback loop's impact
|
|
18
|
+
*/
|
|
19
|
+
import { loadFixHistory, computeFixStats } from "./fix-history.js";
|
|
20
|
+
import { loadFeedbackStore, saveFeedbackStore } from "./commands/feedback.js";
|
|
21
|
+
import { loadCalibrationProfile } from "./calibration.js";
|
|
22
|
+
// ─── Feedback Loop Engine ────────────────────────────────────────────────────
|
|
23
|
+
/**
|
|
24
|
+
* Process fix history and generate calibration feedback.
|
|
25
|
+
* This is the main entry point for the feedback loop.
|
|
26
|
+
*/
|
|
27
|
+
export function runFeedbackLoop(options) {
|
|
28
|
+
const fixHistory = loadFixHistory(options?.fixHistoryDir || ".");
|
|
29
|
+
const feedbackStore = loadFeedbackStore(options?.feedbackDir);
|
|
30
|
+
const fixStats = computeFixStats(fixHistory);
|
|
31
|
+
// Track which outcomes have already been converted to feedback
|
|
32
|
+
const existingFeedbackKeys = new Set(feedbackStore.entries
|
|
33
|
+
.filter((e) => e.comment?.startsWith("[fix-outcome]"))
|
|
34
|
+
.map((e) => `${e.ruleId}::${e.timestamp}`));
|
|
35
|
+
// Convert new fix outcomes to feedback entries
|
|
36
|
+
const newEntries = [];
|
|
37
|
+
for (const outcome of fixHistory.outcomes) {
|
|
38
|
+
const key = `${outcome.ruleId}::${outcome.timestamp}`;
|
|
39
|
+
if (existingFeedbackKeys.has(key))
|
|
40
|
+
continue;
|
|
41
|
+
const verdict = outcomeToVerdict(outcome.accepted, outcome.reverted);
|
|
42
|
+
newEntries.push({
|
|
43
|
+
ruleId: outcome.ruleId,
|
|
44
|
+
verdict,
|
|
45
|
+
timestamp: outcome.timestamp,
|
|
46
|
+
source: "manual",
|
|
47
|
+
comment: `[fix-outcome] ${outcome.reason || (outcome.reverted ? "Fix was reverted" : outcome.accepted ? "Fix accepted" : "Fix rejected")}`,
|
|
48
|
+
filePath: outcome.filePath,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// Add new entries to feedback store
|
|
52
|
+
if (newEntries.length > 0 && !options?.dryRun) {
|
|
53
|
+
feedbackStore.entries.push(...newEntries);
|
|
54
|
+
saveFeedbackStore(feedbackStore, options?.feedbackDir);
|
|
55
|
+
}
|
|
56
|
+
// Compute confidence adjustments from fix stats
|
|
57
|
+
const adjustments = computeAdjustments(fixStats);
|
|
58
|
+
// Load updated calibration profile
|
|
59
|
+
const calibrationProfile = loadCalibrationProfile(options?.calibrationOptions);
|
|
60
|
+
// Compute summary stats
|
|
61
|
+
const stats = computeLoopStats(fixStats, adjustments);
|
|
62
|
+
return {
|
|
63
|
+
outcomesProcessed: fixHistory.outcomes.length,
|
|
64
|
+
feedbackEntriesCreated: newEntries.length,
|
|
65
|
+
adjustments,
|
|
66
|
+
stats,
|
|
67
|
+
calibrationProfile,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Generate a markdown report of the feedback loop results.
|
|
72
|
+
*/
|
|
73
|
+
export function formatFeedbackLoopReport(result) {
|
|
74
|
+
const lines = [
|
|
75
|
+
"# Fix-Outcome Feedback Loop Report",
|
|
76
|
+
"",
|
|
77
|
+
`**Outcomes Processed**: ${result.outcomesProcessed}`,
|
|
78
|
+
`**New Feedback Entries**: ${result.feedbackEntriesCreated}`,
|
|
79
|
+
`**Net Impact**: ${result.stats.netCalibrationImpact}`,
|
|
80
|
+
"",
|
|
81
|
+
"## Statistics",
|
|
82
|
+
"",
|
|
83
|
+
`| Metric | Count |`,
|
|
84
|
+
`|--------|-------|`,
|
|
85
|
+
`| Total outcomes | ${result.stats.totalOutcomes} |`,
|
|
86
|
+
`| Accepted fixes | ${result.stats.accepted} |`,
|
|
87
|
+
`| Rejected fixes | ${result.stats.rejected} |`,
|
|
88
|
+
`| Reverted fixes | ${result.stats.reverted} |`,
|
|
89
|
+
`| Rules with positive signal | ${result.stats.rulesWithPositiveSignal} |`,
|
|
90
|
+
`| Rules with negative signal | ${result.stats.rulesWithNegativeSignal} |`,
|
|
91
|
+
"",
|
|
92
|
+
];
|
|
93
|
+
if (result.adjustments.length > 0) {
|
|
94
|
+
lines.push("## Confidence Adjustments");
|
|
95
|
+
lines.push("");
|
|
96
|
+
lines.push("| Rule | Direction | Current | Recommended | Reason | Samples |");
|
|
97
|
+
lines.push("|------|-----------|---------|-------------|--------|---------|");
|
|
98
|
+
for (const adj of result.adjustments) {
|
|
99
|
+
lines.push(`| ${adj.ruleId} | ${adj.direction} | ${(adj.currentConfidence * 100).toFixed(0)}% | ${(adj.recommendedConfidence * 100).toFixed(0)}% | ${adj.reason} | ${adj.sampleCount} |`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (result.calibrationProfile.isActive) {
|
|
103
|
+
lines.push("");
|
|
104
|
+
lines.push(`## Calibration Status`);
|
|
105
|
+
lines.push("");
|
|
106
|
+
lines.push(`Calibration is **active** with ${result.calibrationProfile.feedbackCount} feedback entries.`);
|
|
107
|
+
}
|
|
108
|
+
return lines.join("\n");
|
|
109
|
+
}
|
|
110
|
+
// ─── Internal Helpers ────────────────────────────────────────────────────────
|
|
111
|
+
function outcomeToVerdict(accepted, reverted) {
|
|
112
|
+
if (reverted)
|
|
113
|
+
return "fp";
|
|
114
|
+
return accepted ? "tp" : "fp";
|
|
115
|
+
}
|
|
116
|
+
function computeAdjustments(stats) {
|
|
117
|
+
const adjustments = [];
|
|
118
|
+
const MIN_SAMPLES = 3;
|
|
119
|
+
for (const [ruleId, ruleStats] of Object.entries(stats.byRule)) {
|
|
120
|
+
if (ruleStats.total < MIN_SAMPLES)
|
|
121
|
+
continue;
|
|
122
|
+
const acceptanceRate = ruleStats.rate;
|
|
123
|
+
const currentConfidence = 0.7; // Default assumption
|
|
124
|
+
if (acceptanceRate >= 0.8) {
|
|
125
|
+
// High acceptance → boost confidence
|
|
126
|
+
const boost = Math.min(0.15, (acceptanceRate - 0.7) * 0.5);
|
|
127
|
+
adjustments.push({
|
|
128
|
+
ruleId,
|
|
129
|
+
currentConfidence,
|
|
130
|
+
recommendedConfidence: Math.min(0.95, currentConfidence + boost),
|
|
131
|
+
direction: "boost",
|
|
132
|
+
reason: `${(acceptanceRate * 100).toFixed(0)}% fix acceptance rate`,
|
|
133
|
+
sampleCount: ruleStats.total,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
else if (acceptanceRate < 0.4) {
|
|
137
|
+
// Low acceptance → reduce confidence
|
|
138
|
+
const reduction = Math.min(0.3, (0.5 - acceptanceRate) * 0.6);
|
|
139
|
+
adjustments.push({
|
|
140
|
+
ruleId,
|
|
141
|
+
currentConfidence,
|
|
142
|
+
recommendedConfidence: Math.max(0.1, currentConfidence - reduction),
|
|
143
|
+
direction: "reduce",
|
|
144
|
+
reason: `${(acceptanceRate * 100).toFixed(0)}% fix acceptance rate (likely FP-prone)`,
|
|
145
|
+
sampleCount: ruleStats.total,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Sort by impact (largest reduction first)
|
|
150
|
+
adjustments.sort((a, b) => {
|
|
151
|
+
const aImpact = Math.abs(a.currentConfidence - a.recommendedConfidence);
|
|
152
|
+
const bImpact = Math.abs(b.currentConfidence - b.recommendedConfidence);
|
|
153
|
+
return bImpact - aImpact;
|
|
154
|
+
});
|
|
155
|
+
return adjustments;
|
|
156
|
+
}
|
|
157
|
+
function computeLoopStats(fixStats, adjustments) {
|
|
158
|
+
const rulesWithPositiveSignal = adjustments.filter((a) => a.direction === "boost").length;
|
|
159
|
+
const rulesWithNegativeSignal = adjustments.filter((a) => a.direction === "reduce").length;
|
|
160
|
+
let netCalibrationImpact;
|
|
161
|
+
if (rulesWithPositiveSignal > rulesWithNegativeSignal) {
|
|
162
|
+
netCalibrationImpact = "positive";
|
|
163
|
+
}
|
|
164
|
+
else if (rulesWithNegativeSignal > rulesWithPositiveSignal) {
|
|
165
|
+
netCalibrationImpact = "negative";
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
netCalibrationImpact = "neutral";
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
totalOutcomes: fixStats.totalFixes,
|
|
172
|
+
accepted: fixStats.accepted,
|
|
173
|
+
rejected: fixStats.rejected,
|
|
174
|
+
reverted: fixStats.reverted,
|
|
175
|
+
rulesWithPositiveSignal,
|
|
176
|
+
rulesWithNegativeSignal,
|
|
177
|
+
netCalibrationImpact,
|
|
178
|
+
};
|
|
179
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import("@modelcontextprotocol/sdk/server/mcp.js")
|
|
|
6
6
|
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
7
7
|
const { registerTools } = await import("./tools/register.js");
|
|
8
8
|
const { registerPrompts } = await import("./tools/prompts.js");
|
|
9
|
+
const { registerResources } = await import("./tools/register-resources.js");
|
|
9
10
|
const { readFileSync } = await import("fs");
|
|
10
11
|
const { resolve, dirname } = await import("path");
|
|
11
12
|
const { fileURLToPath } = await import("url");
|
|
@@ -25,6 +26,7 @@ import("@modelcontextprotocol/sdk/server/mcp.js")
|
|
|
25
26
|
});
|
|
26
27
|
registerTools(server);
|
|
27
28
|
registerPrompts(server);
|
|
29
|
+
registerResources(server);
|
|
28
30
|
const transport = new StdioServerTransport();
|
|
29
31
|
await server.connect(transport);
|
|
30
32
|
console.error("Judges Panel MCP server running on stdio");
|
|
@@ -29,6 +29,13 @@ RULES FOR YOUR EVALUATION:
|
|
|
29
29
|
- Recommend fixes with code examples using proper ARIA patterns.
|
|
30
30
|
- Score from 0-100 where 100 means fully WCAG 2.2 AA compliant.
|
|
31
31
|
|
|
32
|
+
FALSE POSITIVE AVOIDANCE:
|
|
33
|
+
- Only flag accessibility issues in UI/frontend code (HTML, JSX, React components, CSS, templates).
|
|
34
|
+
- Do NOT flag backend APIs, CLI tools, build scripts, or infrastructure code for accessibility issues.
|
|
35
|
+
- Missing ARIA attributes are only an issue when there is actual UI markup to evaluate.
|
|
36
|
+
- Do NOT flag non-UI code for missing alt text, keyboard navigation, or screen reader support.
|
|
37
|
+
- Server-side rendering code should be evaluated for the HTML it produces, not its internal logic.
|
|
38
|
+
|
|
32
39
|
ADVERSARIAL MANDATE:
|
|
33
40
|
- Your role is adversarial: assume the code has accessibility defects and actively hunt for them. Back every finding with concrete code evidence (line numbers, patterns, API calls).
|
|
34
41
|
- Never praise or compliment the code. Report only problems, risks, and deficiencies.
|