@botlearn/code-review 0.1.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/LICENSE +21 -0
- package/README.md +35 -0
- package/knowledge/anti-patterns.md +74 -0
- package/knowledge/best-practices.md +90 -0
- package/knowledge/domain.md +129 -0
- package/manifest.json +26 -0
- package/package.json +35 -0
- package/skill.md +46 -0
- package/strategies/main.md +72 -0
- package/tests/benchmark.json +476 -0
- package/tests/smoke.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 BotLearn
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# @botlearn/code-review
|
|
2
|
+
|
|
3
|
+
> Systematic code review identifying security vulnerabilities, performance issues, and code smells with human-level coverage for OpenClaw Agent
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# via npm
|
|
9
|
+
npm install @botlearn/code-review
|
|
10
|
+
|
|
11
|
+
# via clawhub
|
|
12
|
+
clawhub install @botlearn/code-review
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Category
|
|
16
|
+
|
|
17
|
+
programming-assistance
|
|
18
|
+
|
|
19
|
+
## Dependencies
|
|
20
|
+
|
|
21
|
+
None
|
|
22
|
+
|
|
23
|
+
## Files
|
|
24
|
+
|
|
25
|
+
| File | Description |
|
|
26
|
+
|------|-------------|
|
|
27
|
+
| `manifest.json` | Skill metadata and configuration |
|
|
28
|
+
| `skill.md` | Role definition and activation rules |
|
|
29
|
+
| `knowledge/` | Domain knowledge documents |
|
|
30
|
+
| `strategies/` | Behavioral strategy definitions |
|
|
31
|
+
| `tests/` | Smoke and benchmark tests |
|
|
32
|
+
|
|
33
|
+
## License
|
|
34
|
+
|
|
35
|
+
MIT
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
domain: code-review
|
|
3
|
+
topic: anti-patterns
|
|
4
|
+
priority: medium
|
|
5
|
+
ttl: 30d
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Code Review — Anti-Patterns
|
|
9
|
+
|
|
10
|
+
## Reviewer Anti-Patterns
|
|
11
|
+
|
|
12
|
+
### 1. Nitpicking Over Substance
|
|
13
|
+
**Problem**: Spending review time on formatting, whitespace, and semicolons while missing a SQL injection vulnerability two lines below.
|
|
14
|
+
**Fix**: Follow the priority order — Security → Correctness → Performance → Maintainability → Style. Only comment on style after all substantive issues are addressed.
|
|
15
|
+
|
|
16
|
+
### 2. Vague Feedback
|
|
17
|
+
**Problem**: Comments like "this is wrong" or "needs improvement" without specifying what, why, or how to fix.
|
|
18
|
+
**Fix**: Every finding must include: location, issue, impact, severity, and a concrete fix suggestion.
|
|
19
|
+
|
|
20
|
+
### 3. Missing Security Issues
|
|
21
|
+
**Problem**: Reviewing for code quality but overlooking injection, authentication bypass, or data exposure vulnerabilities.
|
|
22
|
+
**Fix**: Systematically scan against the OWASP Top 10 checklist before reviewing anything else. Use the domain knowledge security section as a reference.
|
|
23
|
+
|
|
24
|
+
### 4. Context-Free Review
|
|
25
|
+
**Problem**: Flagging issues that are acceptable in the given context (e.g., flagging `eval()` in a REPL tool, or missing CSRF protection on a CLI endpoint).
|
|
26
|
+
**Fix**: Identify the language, framework, and deployment context first. Adjust severity ratings accordingly.
|
|
27
|
+
|
|
28
|
+
### 5. Overwhelming with Low-Priority Issues
|
|
29
|
+
**Problem**: Reporting 50 Low/Info findings that bury the 2 Critical findings. The developer can't see what matters.
|
|
30
|
+
**Fix**: Limit Low/Info findings to the top 5-10 most impactful. Always present Critical/High findings first and separately.
|
|
31
|
+
|
|
32
|
+
### 6. Style-as-Severity Inflation
|
|
33
|
+
**Problem**: Marking naming conventions or formatting as "High" severity to get attention.
|
|
34
|
+
**Fix**: Use the severity classification strictly. Style issues are always Low or Info unless they cause actual confusion or bugs.
|
|
35
|
+
|
|
36
|
+
### 7. Missing Positive Feedback
|
|
37
|
+
**Problem**: Only reporting problems, never acknowledging good patterns. This makes reviews feel adversarial.
|
|
38
|
+
**Fix**: Include at least 1-2 positive observations (good error handling, clean abstraction, thorough tests).
|
|
39
|
+
|
|
40
|
+
## Analysis Anti-Patterns
|
|
41
|
+
|
|
42
|
+
### 8. Surface-Level Scanning
|
|
43
|
+
**Problem**: Only checking for obvious issues (typos, missing semicolons) without tracing data flow or control flow for deeper bugs.
|
|
44
|
+
**Fix**: For security issues, trace user input from entry point through all transformations to output. For logic errors, mentally execute edge cases.
|
|
45
|
+
|
|
46
|
+
### 9. Single-File Blindness
|
|
47
|
+
**Problem**: Reviewing a file in isolation without considering how it interacts with the rest of the codebase.
|
|
48
|
+
**Fix**: Consider the call chain — who calls this function? What data flows into it? What happens with its output?
|
|
49
|
+
|
|
50
|
+
### 10. Assuming Framework Safety
|
|
51
|
+
**Problem**: Trusting that the framework prevents all security issues (e.g., "React prevents XSS" — but `dangerouslySetInnerHTML` bypasses this).
|
|
52
|
+
**Fix**: Know the escape hatches in common frameworks and check for their misuse.
|
|
53
|
+
|
|
54
|
+
### 11. Ignoring Error Paths
|
|
55
|
+
**Problem**: Only reviewing the happy path. Errors, timeouts, and partial failures are where most bugs live.
|
|
56
|
+
**Fix**: For each function, ask: "What happens when this fails? What happens with null/undefined input? What happens on timeout?"
|
|
57
|
+
|
|
58
|
+
### 12. False Positive Flooding
|
|
59
|
+
**Problem**: Reporting issues that aren't actually problems, eroding trust in the review process.
|
|
60
|
+
**Fix**: Verify each finding before reporting. If unsure, mark as "Potential issue — verify in context" with Info severity.
|
|
61
|
+
|
|
62
|
+
## Output Anti-Patterns
|
|
63
|
+
|
|
64
|
+
### 13. No Prioritization
|
|
65
|
+
**Problem**: Presenting all findings in a flat list with no ordering. The developer doesn't know where to start.
|
|
66
|
+
**Fix**: Always group by severity (Critical → High → Medium → Low → Info) and provide a "Top 3 action items" summary.
|
|
67
|
+
|
|
68
|
+
### 14. Fix Without Explanation
|
|
69
|
+
**Problem**: Saying "change X to Y" without explaining why. The developer makes the change but doesn't understand the vulnerability, leading to recurrence.
|
|
70
|
+
**Fix**: Every fix suggestion should include a one-sentence explanation of WHY the original code is problematic.
|
|
71
|
+
|
|
72
|
+
### 15. Missing Overall Assessment
|
|
73
|
+
**Problem**: Only listing individual findings without a holistic quality assessment. The developer doesn't know if the code is "mostly good with minor issues" or "fundamentally problematic."
|
|
74
|
+
**Fix**: Always include an overall health summary scoring security, performance, maintainability, and reliability.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
domain: code-review
|
|
3
|
+
topic: best-practices
|
|
4
|
+
priority: high
|
|
5
|
+
ttl: 30d
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Code Review — Best Practices
|
|
9
|
+
|
|
10
|
+
## Structured Review Methodology
|
|
11
|
+
|
|
12
|
+
### Review Order (Priority-First)
|
|
13
|
+
1. **Security** — Scan for OWASP Top 10 vulnerabilities first; these are Critical/High
|
|
14
|
+
2. **Correctness** — Logic errors, off-by-one, null/undefined handling, edge cases
|
|
15
|
+
3. **Performance** — N+1 queries, memory leaks, algorithmic complexity
|
|
16
|
+
4. **Concurrency** — Race conditions, deadlocks, thread safety
|
|
17
|
+
5. **Maintainability** — Code smells, naming, structure, test coverage
|
|
18
|
+
6. **Style** — Only after all substantive issues are addressed
|
|
19
|
+
|
|
20
|
+
### Review Scope Awareness
|
|
21
|
+
- Before reviewing, identify: language, framework, runtime environment, deployment context
|
|
22
|
+
- Adjust severity based on context (e.g., SQL injection in a CLI tool vs. a public API)
|
|
23
|
+
- Consider the blast radius of each issue (affects one user vs. all users vs. data integrity)
|
|
24
|
+
|
|
25
|
+
## Severity Classification
|
|
26
|
+
|
|
27
|
+
| Severity | Criteria | Action | Examples |
|
|
28
|
+
|----------|----------|--------|----------|
|
|
29
|
+
| **Critical** | Exploitable security vulnerability or data loss risk | Must fix before merge | SQL injection, authentication bypass, data exposure |
|
|
30
|
+
| **High** | Significant bug, security weakness, or performance degradation | Should fix before merge | Missing authorization check, N+1 in hot path, race condition |
|
|
31
|
+
| **Medium** | Code smell, moderate performance issue, or minor security hardening | Fix in next iteration | Long method, missing input validation on internal API, unnecessary allocation |
|
|
32
|
+
| **Low** | Improvement opportunity, minor smell, or style preference | Nice to have | Naming improvement, dead code removal, minor refactoring |
|
|
33
|
+
| **Info** | Observation, suggestion, or praise | Optional | Alternative approach suggestion, positive reinforcement |
|
|
34
|
+
|
|
35
|
+
## Constructive Feedback Patterns
|
|
36
|
+
|
|
37
|
+
### Finding Format
|
|
38
|
+
Each finding should include:
|
|
39
|
+
1. **Location**: File, line number, function name
|
|
40
|
+
2. **Issue**: What is wrong (specific, factual)
|
|
41
|
+
3. **Impact**: Why it matters (security risk, performance cost, maintenance burden)
|
|
42
|
+
4. **Severity**: Critical / High / Medium / Low / Info
|
|
43
|
+
5. **Fix**: Concrete suggestion with code example when possible
|
|
44
|
+
|
|
45
|
+
### Good vs. Bad Feedback
|
|
46
|
+
|
|
47
|
+
**Bad**: "This code is messy and has issues."
|
|
48
|
+
**Good**: "The `processOrder()` function (line 42-98) has 4 levels of nesting and handles validation, business logic, and persistence. Extract validation into `validateOrder()` and persistence into `saveOrder()` to improve testability. [Medium]"
|
|
49
|
+
|
|
50
|
+
**Bad**: "Security issue here."
|
|
51
|
+
**Good**: "SQL injection vulnerability at line 23: `db.query('SELECT * FROM users WHERE id = ' + req.params.id)`. An attacker can manipulate the `id` parameter to execute arbitrary SQL. Fix: Use parameterized queries: `db.query('SELECT * FROM users WHERE id = $1', [req.params.id])`. [Critical]"
|
|
52
|
+
|
|
53
|
+
### Positive Reinforcement
|
|
54
|
+
- Acknowledge good patterns when found (proper error handling, good test coverage, clean abstractions)
|
|
55
|
+
- This builds trust and helps the developer know what to keep doing
|
|
56
|
+
|
|
57
|
+
## Overall Health Assessment
|
|
58
|
+
|
|
59
|
+
### Quality Dimensions
|
|
60
|
+
Score each dimension on a 1-5 scale:
|
|
61
|
+
|
|
62
|
+
| Dimension | What to assess |
|
|
63
|
+
|-----------|---------------|
|
|
64
|
+
| **Security** | Authentication, authorization, input validation, data protection |
|
|
65
|
+
| **Performance** | Query patterns, algorithm efficiency, memory usage, caching |
|
|
66
|
+
| **Maintainability** | Code organization, naming, complexity, coupling |
|
|
67
|
+
| **Reliability** | Error handling, edge cases, logging, recovery |
|
|
68
|
+
| **Test Coverage** | Presence of tests, coverage of critical paths, edge case tests |
|
|
69
|
+
|
|
70
|
+
### Prioritized Action Items
|
|
71
|
+
Always end the review with a prioritized list:
|
|
72
|
+
1. **Must fix** — Critical and High severity issues
|
|
73
|
+
2. **Should fix** — Medium severity issues with clear ROI
|
|
74
|
+
3. **Consider** — Low severity improvements for future cleanup
|
|
75
|
+
|
|
76
|
+
## Fix Suggestion Quality
|
|
77
|
+
|
|
78
|
+
### Always Provide Copy-Pasteable Code
|
|
79
|
+
When suggesting a fix, provide code that can be directly used:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
// Before (vulnerable)
|
|
83
|
+
const user = await db.query(`SELECT * FROM users WHERE id = ${id}`);
|
|
84
|
+
|
|
85
|
+
// After (safe)
|
|
86
|
+
const user = await db.query('SELECT * FROM users WHERE id = $1', [id]);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Explain the Fix
|
|
90
|
+
Brief explanation of WHY the fix works, not just WHAT to change. This teaches the developer and prevents recurrence.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
domain: code-review
|
|
3
|
+
topic: security-performance-smells
|
|
4
|
+
priority: high
|
|
5
|
+
ttl: 30d
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Code Review — Domain Knowledge
|
|
9
|
+
|
|
10
|
+
## OWASP Top 10 (2021)
|
|
11
|
+
|
|
12
|
+
### A01: Broken Access Control
|
|
13
|
+
- Missing authorization checks on API endpoints
|
|
14
|
+
- IDOR (Insecure Direct Object References): `GET /api/users/123` without verifying the caller owns the resource
|
|
15
|
+
- Path traversal: `../../../etc/passwd` in file operations
|
|
16
|
+
- Missing function-level access control (admin routes accessible to regular users)
|
|
17
|
+
|
|
18
|
+
### A02: Cryptographic Failures
|
|
19
|
+
- Hardcoded secrets, API keys, or passwords in source code
|
|
20
|
+
- Weak hashing (MD5, SHA1 for passwords instead of bcrypt/argon2)
|
|
21
|
+
- Missing encryption for sensitive data at rest or in transit
|
|
22
|
+
- Predictable session tokens or insufficiently random values
|
|
23
|
+
|
|
24
|
+
### A03: Injection
|
|
25
|
+
- **SQL Injection**: String concatenation in queries: `"SELECT * FROM users WHERE id = " + userId`
|
|
26
|
+
- **NoSQL Injection**: Unsanitized MongoDB queries: `{ $where: userInput }`
|
|
27
|
+
- **Command Injection**: `exec("ping " + hostname)` without sanitization
|
|
28
|
+
- **XSS**: Rendering user input without escaping in HTML/templates
|
|
29
|
+
- **Template Injection**: User input in template strings evaluated server-side
|
|
30
|
+
|
|
31
|
+
### A04: Insecure Design
|
|
32
|
+
- Missing rate limiting on authentication endpoints
|
|
33
|
+
- No account lockout after failed login attempts
|
|
34
|
+
- Missing CSRF tokens on state-changing requests
|
|
35
|
+
- Business logic flaws (e.g., negative quantity in shopping cart)
|
|
36
|
+
|
|
37
|
+
### A05: Security Misconfiguration
|
|
38
|
+
- Debug mode enabled in production
|
|
39
|
+
- Default credentials unchanged
|
|
40
|
+
- Overly permissive CORS (`Access-Control-Allow-Origin: *` with credentials)
|
|
41
|
+
- Verbose error messages exposing stack traces to users
|
|
42
|
+
|
|
43
|
+
### A06: Vulnerable and Outdated Components
|
|
44
|
+
- Known CVEs in dependencies
|
|
45
|
+
- Unmaintained packages with no security patches
|
|
46
|
+
- Outdated framework versions with known vulnerabilities
|
|
47
|
+
|
|
48
|
+
### A07: Identification and Authentication Failures
|
|
49
|
+
- Weak password policies
|
|
50
|
+
- Missing MFA on sensitive operations
|
|
51
|
+
- Session fixation or session ID exposure in URLs
|
|
52
|
+
- JWT issues: no expiration, `alg: none`, weak signing key
|
|
53
|
+
|
|
54
|
+
### A08: Software and Data Integrity Failures
|
|
55
|
+
- Deserialization of untrusted data (pickle, Java serialization)
|
|
56
|
+
- Missing integrity verification on software updates or CI/CD pipelines
|
|
57
|
+
- Prototype pollution in JavaScript
|
|
58
|
+
|
|
59
|
+
### A09: Security Logging and Monitoring Failures
|
|
60
|
+
- No logging of authentication events
|
|
61
|
+
- Sensitive data in logs (passwords, tokens, PII)
|
|
62
|
+
- Missing audit trail for admin operations
|
|
63
|
+
|
|
64
|
+
### A10: Server-Side Request Forgery (SSRF)
|
|
65
|
+
- Fetching user-provided URLs without validation
|
|
66
|
+
- Internal service access via URL manipulation
|
|
67
|
+
|
|
68
|
+
## Performance Anti-Patterns
|
|
69
|
+
|
|
70
|
+
### N+1 Query Problem
|
|
71
|
+
Fetching a list then querying for each item's related data individually:
|
|
72
|
+
```
|
|
73
|
+
users = db.query("SELECT * FROM users")
|
|
74
|
+
for user in users:
|
|
75
|
+
orders = db.query(f"SELECT * FROM orders WHERE user_id = {user.id}")
|
|
76
|
+
```
|
|
77
|
+
**Fix**: Use JOINs, eager loading, or batch queries.
|
|
78
|
+
|
|
79
|
+
### Memory Leaks
|
|
80
|
+
- Event listeners not removed (Node.js `emitter.on()` without `off()`)
|
|
81
|
+
- Growing caches without eviction policies
|
|
82
|
+
- Closures capturing large objects unnecessarily
|
|
83
|
+
- Timers (`setInterval`) not cleared on cleanup
|
|
84
|
+
|
|
85
|
+
### Blocking I/O in Async Context
|
|
86
|
+
- Synchronous file reads in an async handler
|
|
87
|
+
- CPU-intensive computation on the event loop
|
|
88
|
+
- Missing `await` on promises (fire-and-forget without error handling)
|
|
89
|
+
|
|
90
|
+
### Inefficient Algorithms
|
|
91
|
+
- O(n²) loops where O(n) or O(n log n) solutions exist
|
|
92
|
+
- Repeated string concatenation in loops (vs. StringBuilder/join)
|
|
93
|
+
- Unnecessary full-array scans where a hash lookup would work
|
|
94
|
+
|
|
95
|
+
### Unnecessary Re-renders (Frontend)
|
|
96
|
+
- Missing `React.memo`, `useMemo`, or `useCallback` for expensive components
|
|
97
|
+
- Unstable references in dependency arrays
|
|
98
|
+
- State stored too high in the component tree
|
|
99
|
+
|
|
100
|
+
## Code Smell Catalog (Fowler)
|
|
101
|
+
|
|
102
|
+
| Smell | Description | Severity |
|
|
103
|
+
|-------|-------------|----------|
|
|
104
|
+
| **Long Method** | Function > 30 lines or > 4 levels of nesting | Medium |
|
|
105
|
+
| **Large Class** | Class with > 10 public methods or > 300 lines | Medium |
|
|
106
|
+
| **Feature Envy** | Method uses more data from another class than its own | Low |
|
|
107
|
+
| **Data Clump** | Same group of parameters passed to multiple functions | Low |
|
|
108
|
+
| **Primitive Obsession** | Using primitives instead of small domain objects | Low |
|
|
109
|
+
| **Divergent Change** | One class changed for multiple unrelated reasons | Medium |
|
|
110
|
+
| **Shotgun Surgery** | One change requires modifying many classes | High |
|
|
111
|
+
| **Dead Code** | Unreachable or unused code paths | Low |
|
|
112
|
+
| **Speculative Generality** | Unused abstractions or parameters "for the future" | Low |
|
|
113
|
+
| **God Object** | Single class/module that knows or does too much | High |
|
|
114
|
+
|
|
115
|
+
## Concurrency Issues
|
|
116
|
+
|
|
117
|
+
### Race Conditions
|
|
118
|
+
- Shared mutable state accessed from multiple goroutines/threads without synchronization
|
|
119
|
+
- Check-then-act patterns without atomicity (`if file.exists() then file.read()`)
|
|
120
|
+
- Non-atomic read-modify-write operations on shared counters
|
|
121
|
+
|
|
122
|
+
### Deadlocks
|
|
123
|
+
- Two locks acquired in different orders across code paths
|
|
124
|
+
- Lock held during I/O operations (holding DB lock while calling external API)
|
|
125
|
+
|
|
126
|
+
### Thread Safety
|
|
127
|
+
- Non-thread-safe data structures used in concurrent contexts (HashMap vs ConcurrentHashMap)
|
|
128
|
+
- Missing `volatile` / atomics for shared flags
|
|
129
|
+
- Shared mutable state in singleton services
|
package/manifest.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@botlearn/code-review",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Systematic code review identifying security vulnerabilities, performance issues, and code smells with human-level coverage for OpenClaw Agent",
|
|
5
|
+
"category": "programming-assistance",
|
|
6
|
+
"author": "BotLearn",
|
|
7
|
+
"benchmarkDimension": "code-generation",
|
|
8
|
+
"expectedImprovement": 35,
|
|
9
|
+
"dependencies": {},
|
|
10
|
+
"compatibility": {
|
|
11
|
+
"openclaw": ">=0.5.0"
|
|
12
|
+
},
|
|
13
|
+
"files": {
|
|
14
|
+
"skill": "skill.md",
|
|
15
|
+
"knowledge": [
|
|
16
|
+
"knowledge/domain.md",
|
|
17
|
+
"knowledge/best-practices.md",
|
|
18
|
+
"knowledge/anti-patterns.md"
|
|
19
|
+
],
|
|
20
|
+
"strategies": [
|
|
21
|
+
"strategies/main.md"
|
|
22
|
+
],
|
|
23
|
+
"smokeTest": "tests/smoke.json",
|
|
24
|
+
"benchmark": "tests/benchmark.json"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@botlearn/code-review",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Systematic code review identifying security vulnerabilities, performance issues, and code smells with human-level coverage for OpenClaw Agent",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "manifest.json",
|
|
7
|
+
"files": [
|
|
8
|
+
"manifest.json",
|
|
9
|
+
"skill.md",
|
|
10
|
+
"knowledge/",
|
|
11
|
+
"strategies/",
|
|
12
|
+
"tests/",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"botlearn",
|
|
17
|
+
"openclaw",
|
|
18
|
+
"skill",
|
|
19
|
+
"programming-assistance"
|
|
20
|
+
],
|
|
21
|
+
"author": "BotLearn",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/readai-team/botlearn-awesome-skills.git",
|
|
26
|
+
"directory": "packages/skills/code-review"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/readai-team/botlearn-awesome-skills/tree/main/packages/skills/code-review",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/readai-team/botlearn-awesome-skills/issues"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/skill.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-review
|
|
3
|
+
role: Code Review Specialist
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
triggers:
|
|
6
|
+
- "review code"
|
|
7
|
+
- "code review"
|
|
8
|
+
- "check this code"
|
|
9
|
+
- "find bugs"
|
|
10
|
+
- "security audit"
|
|
11
|
+
- "review my code"
|
|
12
|
+
- "check for vulnerabilities"
|
|
13
|
+
- "code quality"
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Role
|
|
17
|
+
|
|
18
|
+
You are a Code Review Specialist. When activated, you perform systematic, multi-dimensional code reviews that identify security vulnerabilities, performance bottlenecks, code smells, and maintainability issues with human-level coverage. You provide actionable, severity-classified findings with concrete fix suggestions.
|
|
19
|
+
|
|
20
|
+
# Capabilities
|
|
21
|
+
|
|
22
|
+
1. Perform static analysis to detect code smells including long methods, deep nesting, duplicated logic, god classes, and inappropriate coupling
|
|
23
|
+
2. Identify security vulnerabilities mapped to the OWASP Top 10, including injection flaws, broken authentication, sensitive data exposure, and insecure deserialization
|
|
24
|
+
3. Detect performance anti-patterns such as N+1 queries, memory leaks, unnecessary allocations, blocking I/O in async contexts, and inefficient algorithms
|
|
25
|
+
4. Recognize concurrency issues including race conditions, deadlocks, improper lock usage, and thread-unsafe shared state
|
|
26
|
+
5. Classify each finding by severity (Critical / High / Medium / Low / Info) with confidence level and provide concrete, copy-pasteable fix suggestions
|
|
27
|
+
6. Assess overall code health across security, performance, maintainability, and reliability dimensions
|
|
28
|
+
|
|
29
|
+
# Constraints
|
|
30
|
+
|
|
31
|
+
1. Never approve code with known Critical or High severity security vulnerabilities without explicit acknowledgment
|
|
32
|
+
2. Never focus on cosmetic style issues at the expense of substantive security or correctness findings
|
|
33
|
+
3. Never provide vague feedback — every finding must include the specific location, what is wrong, why it matters, and how to fix it
|
|
34
|
+
4. Always prioritize findings by severity and business impact, presenting Critical issues first
|
|
35
|
+
5. Always consider the broader context — the language, framework, and deployment environment — before flagging an issue
|
|
36
|
+
6. Never assume benign intent for unsanitized inputs in security-sensitive contexts
|
|
37
|
+
|
|
38
|
+
# Activation
|
|
39
|
+
|
|
40
|
+
WHEN the user requests a code review, security audit, or bug-finding session:
|
|
41
|
+
1. Identify the programming language, framework, and context of the code under review
|
|
42
|
+
2. Execute the systematic review pipeline following strategies/main.md
|
|
43
|
+
3. Apply security knowledge from knowledge/domain.md to detect vulnerabilities
|
|
44
|
+
4. Evaluate findings against knowledge/best-practices.md for severity classification and constructive feedback
|
|
45
|
+
5. Verify the review avoids pitfalls described in knowledge/anti-patterns.md
|
|
46
|
+
6. Output a structured review report with severity-classified findings, fix suggestions, and an overall health assessment
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
strategy: code-review
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
steps: 6
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Code Review Strategy
|
|
8
|
+
|
|
9
|
+
## Step 1: Context Identification
|
|
10
|
+
- Identify the **programming language**, **framework**, and **runtime environment**
|
|
11
|
+
- Determine the **deployment context** (public API, internal service, CLI tool, library)
|
|
12
|
+
- Note any **security-sensitive operations** (authentication, payment, PII handling)
|
|
13
|
+
- IF the code interacts with a database THEN prioritize SQL injection and N+1 query checks
|
|
14
|
+
- IF the code handles user input THEN prioritize injection and XSS checks
|
|
15
|
+
- IF the code is async THEN prioritize race condition and error handling checks
|
|
16
|
+
|
|
17
|
+
## Step 2: Security Scan (OWASP Top 10)
|
|
18
|
+
- Trace all **user input entry points** through the code to their usage
|
|
19
|
+
- Check for **injection vulnerabilities**: SQL, NoSQL, command, XSS, template injection
|
|
20
|
+
- Look for string concatenation in queries, `eval()`, `exec()`, unescaped HTML rendering
|
|
21
|
+
- Check for **authentication/authorization**: missing auth checks, IDOR, privilege escalation
|
|
22
|
+
- Check for **cryptographic issues**: hardcoded secrets, weak hashing, missing encryption
|
|
23
|
+
- Check for **SSRF**: fetching user-provided URLs without validation
|
|
24
|
+
- Check for **deserialization**: untrusted data deserialized without validation
|
|
25
|
+
- Flag every security issue as **Critical** or **High** severity
|
|
26
|
+
|
|
27
|
+
## Step 3: Performance Analysis
|
|
28
|
+
- Scan for **N+1 query patterns**: loops containing database queries
|
|
29
|
+
- Check for **memory leaks**: unclosed resources, growing caches, orphaned listeners
|
|
30
|
+
- Identify **blocking operations** in async contexts: sync I/O, CPU-intensive loops on event loop
|
|
31
|
+
- Evaluate **algorithmic complexity**: look for O(n²) where O(n) or O(n log n) is feasible
|
|
32
|
+
- Check for **unnecessary allocations**: objects created in loops, redundant copies
|
|
33
|
+
- IF performance issues are in a hot path THEN classify as **High**, else **Medium**
|
|
34
|
+
|
|
35
|
+
## Step 4: Code Smell & Pattern Check
|
|
36
|
+
- Apply the code smell catalog from knowledge/domain.md:
|
|
37
|
+
- **Long Method**: > 30 lines or > 4 nesting levels
|
|
38
|
+
- **Large Class**: > 10 public methods or > 300 lines
|
|
39
|
+
- **God Object**: single module handling unrelated responsibilities
|
|
40
|
+
- **Feature Envy**: method using more data from another class
|
|
41
|
+
- **Dead Code**: unreachable or unused code paths
|
|
42
|
+
- Check for **logic errors**: off-by-one, null handling, edge cases, boundary conditions
|
|
43
|
+
- Check for **naming**: misleading names, inconsistent conventions, abbreviations
|
|
44
|
+
- Check for **error handling**: swallowed exceptions, missing `catch`, no error recovery
|
|
45
|
+
- Apply knowledge/anti-patterns.md to verify review thoroughness
|
|
46
|
+
|
|
47
|
+
## Step 5: Issue Classification
|
|
48
|
+
- Assign **severity** to each finding using the classification from knowledge/best-practices.md:
|
|
49
|
+
- **Critical**: Exploitable vulnerability, data loss risk → Must fix
|
|
50
|
+
- **High**: Significant bug, security weakness, perf degradation → Should fix
|
|
51
|
+
- **Medium**: Code smell, moderate perf issue → Fix in next iteration
|
|
52
|
+
- **Low**: Improvement opportunity → Nice to have
|
|
53
|
+
- **Info**: Observation, suggestion, praise → Optional
|
|
54
|
+
- Assign **confidence** level: Certain / Likely / Possible
|
|
55
|
+
- For each finding, prepare: location, issue description, impact, severity, fix suggestion
|
|
56
|
+
|
|
57
|
+
## Step 6: Report & Fix Suggestions
|
|
58
|
+
- Structure the output report:
|
|
59
|
+
1. **Summary**: One-paragraph overall assessment
|
|
60
|
+
2. **Health Scores**: Security (1-5), Performance (1-5), Maintainability (1-5), Reliability (1-5)
|
|
61
|
+
3. **Critical/High Findings**: Listed first with full details and code fix examples
|
|
62
|
+
4. **Medium Findings**: Listed with fix suggestions
|
|
63
|
+
5. **Low/Info Findings**: Brief list (top 5-10 most impactful only)
|
|
64
|
+
6. **Positive Observations**: 1-2 things done well
|
|
65
|
+
7. **Action Items**: Top 3 prioritized next steps
|
|
66
|
+
- Every fix suggestion must include a **code example** showing before/after
|
|
67
|
+
- Every fix must include a **one-sentence explanation** of why the original is problematic
|
|
68
|
+
- SELF-CHECK:
|
|
69
|
+
- Did I check all OWASP Top 10 categories?
|
|
70
|
+
- Did I trace all user input paths?
|
|
71
|
+
- Did I check error paths, not just happy paths?
|
|
72
|
+
- Did I avoid the anti-patterns from knowledge/anti-patterns.md?
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.0.1",
|
|
3
|
+
"dimension": "code-generation",
|
|
4
|
+
"tasks": [
|
|
5
|
+
{
|
|
6
|
+
"id": "bench-easy-01",
|
|
7
|
+
"difficulty": "easy",
|
|
8
|
+
"description": "Detect XSS vulnerability in React component",
|
|
9
|
+
"input": "Review this React component for security issues:\n\n```jsx\nfunction UserProfile({ user }) {\n return (\n <div>\n <h1>{user.name}</h1>\n <div dangerouslySetInnerHTML={{ __html: user.bio }} />\n <a href={user.website}>{user.website}</a>\n </div>\n );\n}\n```",
|
|
10
|
+
"rubric": [
|
|
11
|
+
{
|
|
12
|
+
"criterion": "XSS Detection",
|
|
13
|
+
"weight": 0.5,
|
|
14
|
+
"scoring": {
|
|
15
|
+
"5": "Identifies dangerouslySetInnerHTML as XSS vector; identifies javascript: protocol risk in href; explains attack scenario",
|
|
16
|
+
"3": "Identifies dangerouslySetInnerHTML but misses href issue",
|
|
17
|
+
"1": "Only vague mention of XSS",
|
|
18
|
+
"0": "Misses XSS entirely"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"criterion": "Fix Suggestion",
|
|
23
|
+
"weight": 0.3,
|
|
24
|
+
"scoring": {
|
|
25
|
+
"5": "Suggests DOMPurify for HTML sanitization and URL validation/allowlisting for href",
|
|
26
|
+
"3": "Suggests removing dangerouslySetInnerHTML but no sanitization alternative",
|
|
27
|
+
"1": "Vague fix",
|
|
28
|
+
"0": "No fix"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"criterion": "Severity",
|
|
33
|
+
"weight": 0.2,
|
|
34
|
+
"scoring": {
|
|
35
|
+
"5": "Correctly classifies as High/Critical severity",
|
|
36
|
+
"3": "Classifies as Medium",
|
|
37
|
+
"1": "Classifies as Low",
|
|
38
|
+
"0": "No severity"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"expectedScoreWithout": 35,
|
|
43
|
+
"expectedScoreWith": 80
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "bench-easy-02",
|
|
47
|
+
"difficulty": "easy",
|
|
48
|
+
"description": "Detect missing error handling in async code",
|
|
49
|
+
"input": "Review this Node.js function for issues:\n\n```javascript\nasync function fetchUserData(userId) {\n const response = await fetch(`https://api.example.com/users/${userId}`);\n const data = await response.json();\n const posts = await fetch(`https://api.example.com/users/${userId}/posts`);\n const postsData = await posts.json();\n return { user: data, posts: postsData };\n}\n```",
|
|
50
|
+
"rubric": [
|
|
51
|
+
{
|
|
52
|
+
"criterion": "Issue Detection",
|
|
53
|
+
"weight": 0.5,
|
|
54
|
+
"scoring": {
|
|
55
|
+
"5": "Identifies: no error handling for failed requests, no status code check, no try-catch, sequential requests that could be parallel, no timeout, no input validation",
|
|
56
|
+
"3": "Identifies 3-4 of the above",
|
|
57
|
+
"1": "Only identifies missing try-catch",
|
|
58
|
+
"0": "No issues found"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"criterion": "Fix Quality",
|
|
63
|
+
"weight": 0.3,
|
|
64
|
+
"scoring": {
|
|
65
|
+
"5": "Provides complete fix with try-catch, response.ok check, Promise.all for parallel requests, timeout, input validation",
|
|
66
|
+
"3": "Provides partial fix covering error handling",
|
|
67
|
+
"1": "Minimal fix",
|
|
68
|
+
"0": "No fix"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"criterion": "Report Structure",
|
|
73
|
+
"weight": 0.2,
|
|
74
|
+
"scoring": {
|
|
75
|
+
"5": "Findings organized by severity with clear action items",
|
|
76
|
+
"3": "Some organization",
|
|
77
|
+
"1": "Flat list",
|
|
78
|
+
"0": "No structure"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"expectedScoreWithout": 30,
|
|
83
|
+
"expectedScoreWith": 75
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "bench-easy-03",
|
|
87
|
+
"difficulty": "easy",
|
|
88
|
+
"description": "Detect basic code smells and naming issues",
|
|
89
|
+
"input": "Review this Python function:\n\n```python\ndef p(d, t, x=None):\n r = []\n for i in d:\n if i['t'] == t:\n if x is not None:\n if i['v'] > x:\n r.append(i)\n else:\n r.append(i)\n if len(r) == 0:\n return None\n r2 = sorted(r, key=lambda i: i['v'], reverse=True)\n return r2\n```",
|
|
90
|
+
"rubric": [
|
|
91
|
+
{
|
|
92
|
+
"criterion": "Smell Detection",
|
|
93
|
+
"weight": 0.4,
|
|
94
|
+
"scoring": {
|
|
95
|
+
"5": "Identifies: cryptic naming (p, d, t, x, r, r2, i), deep nesting, use of dict instead of dataclass/namedtuple, returning None vs empty list inconsistency",
|
|
96
|
+
"3": "Identifies naming and nesting issues",
|
|
97
|
+
"1": "Only mentions naming",
|
|
98
|
+
"0": "No issues found"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"criterion": "Refactoring Suggestion",
|
|
103
|
+
"weight": 0.4,
|
|
104
|
+
"scoring": {
|
|
105
|
+
"5": "Provides complete refactored version with descriptive names, flat structure (early return/list comprehension), type hints, and consistent return type",
|
|
106
|
+
"3": "Provides renamed version but structure unchanged",
|
|
107
|
+
"1": "Only suggests renaming",
|
|
108
|
+
"0": "No refactoring"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"criterion": "Severity Assessment",
|
|
113
|
+
"weight": 0.2,
|
|
114
|
+
"scoring": {
|
|
115
|
+
"5": "Correctly rates naming/readability as Medium severity and notes no security issues",
|
|
116
|
+
"3": "Reasonable severity assessment",
|
|
117
|
+
"1": "Inflated or missing severity",
|
|
118
|
+
"0": "No severity"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
"expectedScoreWithout": 35,
|
|
123
|
+
"expectedScoreWith": 75
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"id": "bench-med-01",
|
|
127
|
+
"difficulty": "medium",
|
|
128
|
+
"description": "Detect SQL injection with ORM bypass",
|
|
129
|
+
"input": "Review this Django view for security issues:\n\n```python\nfrom django.http import JsonResponse\nfrom django.db import connection\nfrom .models import Product\n\ndef search_products(request):\n query = request.GET.get('q', '')\n category = request.GET.get('category', '')\n min_price = request.GET.get('min_price', 0)\n sort = request.GET.get('sort', 'name')\n \n products = Product.objects.filter(\n name__icontains=query,\n category__name=category\n )\n \n with connection.cursor() as cursor:\n cursor.execute(\n f\"SELECT * FROM products_product WHERE price >= {min_price} ORDER BY {sort}\"\n )\n filtered = cursor.fetchall()\n \n return JsonResponse({'products': list(products.values()), 'filtered': filtered})\n```",
|
|
130
|
+
"rubric": [
|
|
131
|
+
{
|
|
132
|
+
"criterion": "SQL Injection Detection",
|
|
133
|
+
"weight": 0.35,
|
|
134
|
+
"scoring": {
|
|
135
|
+
"5": "Identifies both injection points: min_price (value injection) AND sort (column injection/ORDER BY injection); explains that the ORM usage above is safe but the raw query below bypasses it",
|
|
136
|
+
"3": "Identifies the f-string SQL issue but misses ORDER BY injection specifics",
|
|
137
|
+
"1": "Only vague SQL injection mention",
|
|
138
|
+
"0": "Misses SQL injection"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"criterion": "Additional Issues",
|
|
143
|
+
"weight": 0.25,
|
|
144
|
+
"scoring": {
|
|
145
|
+
"5": "Identifies: redundant query (ORM + raw doing similar things), no pagination, no input validation for min_price type, missing authentication",
|
|
146
|
+
"3": "Identifies 2 additional issues",
|
|
147
|
+
"1": "Only SQL injection found",
|
|
148
|
+
"0": "No additional issues"
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"criterion": "Fix Quality",
|
|
153
|
+
"weight": 0.25,
|
|
154
|
+
"scoring": {
|
|
155
|
+
"5": "Provides parameterized query fix, allowlist for sort column, consolidated to single ORM query, input validation",
|
|
156
|
+
"3": "Provides parameterized fix but misses sort allowlist",
|
|
157
|
+
"1": "Generic fix suggestion",
|
|
158
|
+
"0": "No fix"
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"criterion": "Report Structure",
|
|
163
|
+
"weight": 0.15,
|
|
164
|
+
"scoring": {
|
|
165
|
+
"5": "Structured with severity levels, grouped findings, clear action items",
|
|
166
|
+
"3": "Some structure",
|
|
167
|
+
"1": "Flat list",
|
|
168
|
+
"0": "No structure"
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"expectedScoreWithout": 30,
|
|
173
|
+
"expectedScoreWith": 70
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"id": "bench-med-02",
|
|
177
|
+
"difficulty": "medium",
|
|
178
|
+
"description": "Detect N+1 query and memory issues in data processing",
|
|
179
|
+
"input": "Review this TypeScript service for performance issues:\n\n```typescript\nasync function generateReport(orgId: string): Promise<Report> {\n const departments = await db.departments.findMany({ where: { orgId } });\n const report: Report = { departments: [] };\n\n for (const dept of departments) {\n const employees = await db.employees.findMany({ where: { departmentId: dept.id } });\n const deptData: DepartmentReport = { name: dept.name, employees: [] };\n\n for (const emp of employees) {\n const reviews = await db.performanceReviews.findMany({ where: { employeeId: emp.id } });\n const projects = await db.projectAssignments.findMany({ where: { employeeId: emp.id } });\n \n deptData.employees.push({\n name: emp.name,\n reviews: reviews,\n projects: projects,\n avgScore: reviews.reduce((sum, r) => sum + r.score, 0) / reviews.length\n });\n }\n report.departments.push(deptData);\n }\n return report;\n}\n```",
|
|
180
|
+
"rubric": [
|
|
181
|
+
{
|
|
182
|
+
"criterion": "N+1 Detection",
|
|
183
|
+
"weight": 0.35,
|
|
184
|
+
"scoring": {
|
|
185
|
+
"5": "Identifies nested N+1 pattern: 1 + N + N*M + N*M queries (departments → employees → reviews + projects); calculates approximate query count for realistic org sizes",
|
|
186
|
+
"3": "Identifies N+1 but doesn't trace the full nesting depth",
|
|
187
|
+
"1": "Mentions 'too many queries' without specifics",
|
|
188
|
+
"0": "Misses the issue"
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"criterion": "Additional Issues",
|
|
193
|
+
"weight": 0.25,
|
|
194
|
+
"scoring": {
|
|
195
|
+
"5": "Identifies: potential division by zero (empty reviews), memory growth with large orgs, sequential reviews+projects that could be parallel, no pagination/limit, missing error handling",
|
|
196
|
+
"3": "Identifies 2-3 additional issues",
|
|
197
|
+
"1": "Only N+1 found",
|
|
198
|
+
"0": "No additional issues"
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"criterion": "Fix Quality",
|
|
203
|
+
"weight": 0.25,
|
|
204
|
+
"scoring": {
|
|
205
|
+
"5": "Provides fix using JOINs/includes/eager loading, Promise.all for parallel queries, division-by-zero guard, streaming or pagination for large datasets",
|
|
206
|
+
"3": "Provides JOIN-based fix but misses other improvements",
|
|
207
|
+
"1": "Generic fix",
|
|
208
|
+
"0": "No fix"
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"criterion": "Severity",
|
|
213
|
+
"weight": 0.15,
|
|
214
|
+
"scoring": {
|
|
215
|
+
"5": "Correctly classifies N+1 as High (in a report generation context), division-by-zero as Medium",
|
|
216
|
+
"3": "Reasonable severity",
|
|
217
|
+
"1": "Incorrect severity",
|
|
218
|
+
"0": "No severity"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
"expectedScoreWithout": 25,
|
|
223
|
+
"expectedScoreWith": 70
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"id": "bench-med-03",
|
|
227
|
+
"difficulty": "medium",
|
|
228
|
+
"description": "Detect race condition in concurrent code",
|
|
229
|
+
"input": "Review this Go HTTP handler for concurrency issues:\n\n```go\npackage main\n\nimport (\n \"fmt\"\n \"net/http\"\n \"sync\"\n)\n\nvar (\n requestCount int\n cache = make(map[string]string)\n)\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n requestCount++\n key := r.URL.Query().Get(\"key\")\n \n if val, ok := cache[key]; ok {\n fmt.Fprintf(w, \"cached: %s\", val)\n return\n }\n \n result := expensiveComputation(key)\n cache[key] = result\n fmt.Fprintf(w, \"computed: %s\", result)\n}\n\nfunc statsHandler(w http.ResponseWriter, r *http.Request) {\n fmt.Fprintf(w, \"requests: %d, cache size: %d\", requestCount, len(cache))\n}\n```",
|
|
230
|
+
"rubric": [
|
|
231
|
+
{
|
|
232
|
+
"criterion": "Race Condition Detection",
|
|
233
|
+
"weight": 0.4,
|
|
234
|
+
"scoring": {
|
|
235
|
+
"5": "Identifies: unsynchronized requestCount increment (data race), unsynchronized map read/write (Go maps are not goroutine-safe; concurrent map access will panic), cache stampede (multiple goroutines computing same key simultaneously)",
|
|
236
|
+
"3": "Identifies map race condition but misses counter or stampede",
|
|
237
|
+
"1": "Mentions concurrency issues vaguely",
|
|
238
|
+
"0": "Misses race conditions"
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"criterion": "Additional Issues",
|
|
243
|
+
"weight": 0.2,
|
|
244
|
+
"scoring": {
|
|
245
|
+
"5": "Identifies: unbounded cache growth (no eviction), no input validation on key, cache with no TTL, missing error handling on expensiveComputation",
|
|
246
|
+
"3": "Identifies 1-2 additional issues",
|
|
247
|
+
"1": "Only race conditions found",
|
|
248
|
+
"0": "No additional issues"
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"criterion": "Fix Quality",
|
|
253
|
+
"weight": 0.25,
|
|
254
|
+
"scoring": {
|
|
255
|
+
"5": "Provides sync.RWMutex for cache, atomic.AddInt64 for counter, singleflight for stampede prevention, or suggests sync.Map alternative",
|
|
256
|
+
"3": "Provides mutex fix but misses singleflight or atomic",
|
|
257
|
+
"1": "Suggests 'add a lock' without code",
|
|
258
|
+
"0": "No fix"
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"criterion": "Severity & Go-Specific Knowledge",
|
|
263
|
+
"weight": 0.15,
|
|
264
|
+
"scoring": {
|
|
265
|
+
"5": "Correctly notes concurrent map access causes runtime panic in Go (not just data corruption); classifies as Critical",
|
|
266
|
+
"3": "Notes race condition but doesn't mention Go-specific map panic",
|
|
267
|
+
"1": "Generic concurrency advice",
|
|
268
|
+
"0": "No Go-specific knowledge"
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
],
|
|
272
|
+
"expectedScoreWithout": 25,
|
|
273
|
+
"expectedScoreWith": 70
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"id": "bench-med-04",
|
|
277
|
+
"difficulty": "medium",
|
|
278
|
+
"description": "Detect authentication bypass and JWT issues",
|
|
279
|
+
"input": "Review this authentication middleware:\n\n```javascript\nconst jwt = require('jsonwebtoken');\n\nconst SECRET = 'my-secret-key-123';\n\nfunction authMiddleware(req, res, next) {\n const token = req.headers.authorization;\n \n if (!token) {\n return res.status(401).json({ error: 'No token' });\n }\n\n try {\n const decoded = jwt.verify(token, SECRET);\n req.user = decoded;\n next();\n } catch (err) {\n res.status(401).json({ error: 'Invalid token' });\n }\n}\n\nfunction adminMiddleware(req, res, next) {\n if (req.user.role === 'admin') {\n next();\n }\n res.status(403).json({ error: 'Forbidden' });\n}\n\nfunction generateToken(user) {\n return jwt.sign({ id: user.id, role: user.role, email: user.email }, SECRET);\n}\n```",
|
|
280
|
+
"rubric": [
|
|
281
|
+
{
|
|
282
|
+
"criterion": "Security Issue Detection",
|
|
283
|
+
"weight": 0.4,
|
|
284
|
+
"scoring": {
|
|
285
|
+
"5": "Identifies: hardcoded weak secret, no token expiration, missing 'Bearer ' prefix parsing, adminMiddleware missing return (sends both 403 and continues), no algorithm restriction (algorithm confusion attack), PII in token payload",
|
|
286
|
+
"3": "Identifies 3-4 of the above",
|
|
287
|
+
"1": "Only identifies hardcoded secret",
|
|
288
|
+
"0": "Misses major issues"
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"criterion": "Missing Return Bug",
|
|
293
|
+
"weight": 0.2,
|
|
294
|
+
"scoring": {
|
|
295
|
+
"5": "Identifies that adminMiddleware doesn't return after next(), causing the 403 response to always execute (sending headers after response for admin users)",
|
|
296
|
+
"3": "Notes the control flow issue but doesn't fully explain the consequence",
|
|
297
|
+
"1": "Misses the bug",
|
|
298
|
+
"0": "Not mentioned"
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"criterion": "Fix Quality",
|
|
303
|
+
"weight": 0.25,
|
|
304
|
+
"scoring": {
|
|
305
|
+
"5": "Provides: env variable for secret, token expiration, Bearer parsing, return statement fix, algorithm pinning ({algorithms: ['HS256']}), minimal payload",
|
|
306
|
+
"3": "Fixes most issues but misses algorithm pinning",
|
|
307
|
+
"1": "Partial fixes",
|
|
308
|
+
"0": "No fixes"
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"criterion": "Report Structure",
|
|
313
|
+
"weight": 0.15,
|
|
314
|
+
"scoring": {
|
|
315
|
+
"5": "Clear severity classification; Critical for secret/no-expiry/auth bypass, Medium for payload/parsing",
|
|
316
|
+
"3": "Some severity classification",
|
|
317
|
+
"1": "Flat list",
|
|
318
|
+
"0": "No structure"
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
],
|
|
322
|
+
"expectedScoreWithout": 30,
|
|
323
|
+
"expectedScoreWith": 75
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"id": "bench-hard-01",
|
|
327
|
+
"difficulty": "hard",
|
|
328
|
+
"description": "Comprehensive review of a file upload service with multiple vulnerability classes",
|
|
329
|
+
"input": "Review this file upload service for all categories of issues:\n\n```python\nimport os\nimport subprocess\nfrom flask import Flask, request, jsonify, send_file\n\napp = Flask(__name__)\nUPLOAD_DIR = '/uploads'\n\n@app.route('/upload', methods=['POST'])\ndef upload():\n file = request.files['file']\n filename = file.filename\n filepath = os.path.join(UPLOAD_DIR, filename)\n file.save(filepath)\n \n if filename.endswith('.pdf'):\n text = subprocess.check_output(f'pdftotext {filepath} -', shell=True)\n return jsonify({'text': text.decode(), 'path': filepath})\n \n return jsonify({'message': 'Uploaded', 'path': filepath})\n\n@app.route('/files/<path:filename>')\ndef serve_file(filename):\n return send_file(os.path.join(UPLOAD_DIR, filename))\n\n@app.route('/delete', methods=['POST'])\ndef delete():\n path = request.json['path']\n os.remove(path)\n return jsonify({'deleted': path})\n```",
|
|
330
|
+
"rubric": [
|
|
331
|
+
{
|
|
332
|
+
"criterion": "Vulnerability Detection Breadth",
|
|
333
|
+
"weight": 0.3,
|
|
334
|
+
"scoring": {
|
|
335
|
+
"5": "Identifies ALL: path traversal in upload (../../), command injection in pdftotext (shell=True with unsanitized filename), path traversal in serve_file, arbitrary file deletion in /delete (any path on system), no file type/size validation, no authentication, information disclosure (filepath in response), unrestricted file upload (web shells)",
|
|
336
|
+
"3": "Identifies 5-6 vulnerabilities",
|
|
337
|
+
"1": "Identifies 2-3 vulnerabilities",
|
|
338
|
+
"0": "Misses most issues"
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"criterion": "Attack Scenario Depth",
|
|
343
|
+
"weight": 0.25,
|
|
344
|
+
"scoring": {
|
|
345
|
+
"5": "Describes concrete attack chains: upload a file named '../../etc/cron.d/backdoor', upload file named '; rm -rf /' for command injection, delete /etc/passwd via delete endpoint",
|
|
346
|
+
"3": "Describes some attack scenarios but not chains",
|
|
347
|
+
"1": "Generic vulnerability descriptions",
|
|
348
|
+
"0": "No attack scenarios"
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"criterion": "Fix Completeness",
|
|
353
|
+
"weight": 0.3,
|
|
354
|
+
"scoring": {
|
|
355
|
+
"5": "Provides: filename sanitization (werkzeug.secure_filename), file type allowlisting, size limits, subprocess with list args (no shell=True), path validation (os.path.realpath check), authentication, remove filepath from response, chroot/contained upload directory",
|
|
356
|
+
"3": "Fixes 4-5 issues with code",
|
|
357
|
+
"1": "Fixes 1-2 issues",
|
|
358
|
+
"0": "No fixes"
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"criterion": "Severity Accuracy",
|
|
363
|
+
"weight": 0.15,
|
|
364
|
+
"scoring": {
|
|
365
|
+
"5": "Command injection and arbitrary file deletion as Critical; path traversal as Critical; unrestricted upload as High; missing auth as High; info disclosure as Medium",
|
|
366
|
+
"3": "Mostly correct severity",
|
|
367
|
+
"1": "Severity misclassification",
|
|
368
|
+
"0": "No severity"
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
],
|
|
372
|
+
"expectedScoreWithout": 20,
|
|
373
|
+
"expectedScoreWith": 65
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"id": "bench-hard-02",
|
|
377
|
+
"difficulty": "hard",
|
|
378
|
+
"description": "Review complex async state management with subtle bugs",
|
|
379
|
+
"input": "Review this TypeScript connection pool and caching layer for correctness and performance:\n\n```typescript\nclass ConnectionPool {\n private pool: Connection[] = [];\n private waiting: ((conn: Connection) => void)[] = [];\n private cache: Map<string, { data: any; timestamp: number }> = new Map();\n private maxSize: number;\n private cacheTimeout = 300000; // 5 min\n\n constructor(maxSize: number) {\n this.maxSize = maxSize;\n }\n\n async query(sql: string, params: any[]): Promise<any> {\n const cacheKey = sql + JSON.stringify(params);\n const cached = this.cache.get(cacheKey);\n \n if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {\n return cached.data;\n }\n\n const conn = await this.getConnection();\n const result = await conn.execute(sql, params);\n this.cache.set(cacheKey, { data: result, timestamp: Date.now() });\n this.releaseConnection(conn);\n return result;\n }\n\n private async getConnection(): Promise<Connection> {\n if (this.pool.length > 0) {\n return this.pool.pop()!;\n }\n if (this.pool.length < this.maxSize) {\n return new Connection();\n }\n return new Promise(resolve => this.waiting.push(resolve));\n }\n\n private releaseConnection(conn: Connection) {\n if (this.waiting.length > 0) {\n this.waiting.shift()!(conn);\n } else {\n this.pool.push(conn);\n }\n }\n}\n```",
|
|
380
|
+
"rubric": [
|
|
381
|
+
{
|
|
382
|
+
"criterion": "Bug Detection",
|
|
383
|
+
"weight": 0.35,
|
|
384
|
+
"scoring": {
|
|
385
|
+
"5": "Identifies ALL: getConnection size check is wrong (pool.length tracks available not total, so it creates unlimited connections), connection not released on query error (no try-finally), cache grows unboundedly, cache key collision possible with JSON.stringify, mutation writes cached to cache (shared reference), waiting queue has no timeout (can hang forever)",
|
|
386
|
+
"3": "Identifies 3-4 bugs",
|
|
387
|
+
"1": "Identifies 1-2 bugs",
|
|
388
|
+
"0": "Misses bugs"
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
"criterion": "Concurrency Analysis",
|
|
393
|
+
"weight": 0.25,
|
|
394
|
+
"scoring": {
|
|
395
|
+
"5": "Identifies race conditions: multiple concurrent calls can pop same connection (not atomic), cache stampede (multiple requests for same expired key), TOCTOU in getConnection",
|
|
396
|
+
"3": "Identifies 1-2 concurrency issues",
|
|
397
|
+
"1": "Mentions concurrency concerns vaguely",
|
|
398
|
+
"0": "No concurrency analysis"
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"criterion": "Fix Quality",
|
|
403
|
+
"weight": 0.25,
|
|
404
|
+
"scoring": {
|
|
405
|
+
"5": "Provides: separate total connection counter, try-finally for connection release, cache eviction (LRU or size-limited), semaphore or mutex for pool access, timeout for waiting, defensive copy for cached data",
|
|
406
|
+
"3": "Fixes major bugs but misses concurrency fixes",
|
|
407
|
+
"1": "Partial fixes",
|
|
408
|
+
"0": "No fixes"
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"criterion": "Overall Assessment",
|
|
413
|
+
"weight": 0.15,
|
|
414
|
+
"scoring": {
|
|
415
|
+
"5": "Provides health score, identifies this as High-risk code due to resource management bugs, recommends using a proven pool library instead",
|
|
416
|
+
"3": "Some overall assessment",
|
|
417
|
+
"1": "Only individual findings",
|
|
418
|
+
"0": "No assessment"
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
],
|
|
422
|
+
"expectedScoreWithout": 20,
|
|
423
|
+
"expectedScoreWith": 65
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
"id": "bench-hard-03",
|
|
427
|
+
"difficulty": "hard",
|
|
428
|
+
"description": "Review a multi-language microservice interaction with subtle security and reliability issues",
|
|
429
|
+
"input": "Review this API gateway handler that coordinates between microservices:\n\n```typescript\nimport express from 'express';\nimport axios from 'axios';\nimport Redis from 'ioredis';\n\nconst redis = new Redis();\nconst app = express();\n\napp.post('/api/checkout', async (req, res) => {\n const { userId, items, paymentToken, promoCode } = req.body;\n \n // Step 1: Validate promo code\n let discount = 0;\n if (promoCode) {\n const promo = await axios.get(`http://promo-service/validate/${promoCode}`);\n discount = promo.data.discount;\n }\n \n // Step 2: Check inventory\n const inventory = await axios.post('http://inventory-service/check', { items });\n if (!inventory.data.available) {\n return res.status(400).json({ error: 'Items unavailable' });\n }\n \n // Step 3: Reserve inventory\n await axios.post('http://inventory-service/reserve', { items, userId });\n \n // Step 4: Calculate total\n const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0);\n const finalTotal = total - (total * discount / 100);\n \n // Step 5: Charge payment\n const payment = await axios.post('http://payment-service/charge', {\n userId, amount: finalTotal, token: paymentToken\n });\n \n // Step 6: Create order\n const order = await axios.post('http://order-service/create', {\n userId, items, total: finalTotal, paymentId: payment.data.id\n });\n \n // Step 7: Cache order\n await redis.set(`order:${order.data.id}`, JSON.stringify(order.data));\n \n res.json({ orderId: order.data.id, total: finalTotal });\n});\n```",
|
|
430
|
+
"rubric": [
|
|
431
|
+
{
|
|
432
|
+
"criterion": "Distributed System Issues",
|
|
433
|
+
"weight": 0.3,
|
|
434
|
+
"scoring": {
|
|
435
|
+
"5": "Identifies: no saga/compensation (if payment fails, inventory stays reserved; if order creation fails, payment is charged without order), no idempotency (retry creates double charge), no timeout on service calls, no circuit breaker, race condition between check and reserve (TOCTOU)",
|
|
436
|
+
"3": "Identifies 2-3 distributed system issues",
|
|
437
|
+
"1": "Only mentions error handling",
|
|
438
|
+
"0": "Misses distributed issues"
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
"criterion": "Security Issues",
|
|
443
|
+
"weight": 0.25,
|
|
444
|
+
"scoring": {
|
|
445
|
+
"5": "Identifies: client-supplied prices (item.price from request body — price manipulation), no auth/user verification, discount could be > 100% (negative total), no input validation on items array, SSRF potential via internal service URLs, no rate limiting on checkout",
|
|
446
|
+
"3": "Identifies 3 security issues",
|
|
447
|
+
"1": "Identifies 1 security issue",
|
|
448
|
+
"0": "Misses security issues"
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"criterion": "Reliability Fix",
|
|
453
|
+
"weight": 0.3,
|
|
454
|
+
"scoring": {
|
|
455
|
+
"5": "Proposes: saga pattern with compensation handlers, idempotency keys, timeouts + circuit breakers, server-side price lookup, input validation, retry with backoff, dead letter queue for failed steps",
|
|
456
|
+
"3": "Proposes some reliability fixes",
|
|
457
|
+
"1": "Only suggests try-catch",
|
|
458
|
+
"0": "No reliability fixes"
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
"criterion": "Severity & Report Quality",
|
|
463
|
+
"weight": 0.15,
|
|
464
|
+
"scoring": {
|
|
465
|
+
"5": "Critical: price manipulation, no compensation; High: no idempotency, no timeout; Medium: missing circuit breaker, redis caching issues; structured report with priorities",
|
|
466
|
+
"3": "Some severity classification",
|
|
467
|
+
"1": "Flat list",
|
|
468
|
+
"0": "No severity"
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
],
|
|
472
|
+
"expectedScoreWithout": 20,
|
|
473
|
+
"expectedScoreWith": 65
|
|
474
|
+
}
|
|
475
|
+
]
|
|
476
|
+
}
|
package/tests/smoke.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.0.1",
|
|
3
|
+
"timeout": 60,
|
|
4
|
+
"tasks": [
|
|
5
|
+
{
|
|
6
|
+
"id": "smoke-01",
|
|
7
|
+
"description": "Review a code snippet with intentionally planted security, performance, and quality issues",
|
|
8
|
+
"input": "Review the following Express.js API endpoint for security vulnerabilities, performance issues, and code quality:\n\n```javascript\nconst express = require('express');\nconst app = express();\nconst db = require('./db');\n\napp.post('/api/login', async (req, res) => {\n const { username, password } = req.body;\n const user = await db.query(`SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`);\n if (user.rows.length > 0) {\n const token = username + Date.now();\n res.json({ token, user: user.rows[0] });\n } else {\n res.json({ error: 'Invalid credentials' });\n }\n});\n\napp.get('/api/users/:id', async (req, res) => {\n const user = await db.query(`SELECT * FROM users WHERE id = ${req.params.id}`);\n res.json(user.rows[0]);\n});\n\napp.get('/api/users', async (req, res) => {\n const users = await db.query('SELECT * FROM users');\n const result = [];\n for (const user of users.rows) {\n const orders = await db.query(`SELECT * FROM orders WHERE user_id = ${user.id}`);\n result.push({ ...user, orders: orders.rows });\n }\n res.json(result);\n});\n\napp.listen(3000);\n```\n\nProvide a structured review with severity classifications and fix suggestions.",
|
|
9
|
+
"rubric": [
|
|
10
|
+
{
|
|
11
|
+
"criterion": "Issue Detection Rate",
|
|
12
|
+
"weight": 0.3,
|
|
13
|
+
"scoring": {
|
|
14
|
+
"5": "Identifies all major issues: SQL injection (2 instances), plaintext password storage, predictable token, missing auth on /users/:id, N+1 query, missing error handling, no rate limiting, full user object in response (including password)",
|
|
15
|
+
"3": "Identifies 4-5 of the above issues",
|
|
16
|
+
"1": "Identifies only 1-2 obvious issues",
|
|
17
|
+
"0": "Misses all major issues or reports false positives"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"criterion": "Severity Classification",
|
|
22
|
+
"weight": 0.25,
|
|
23
|
+
"scoring": {
|
|
24
|
+
"5": "Correctly classifies SQL injection and auth issues as Critical/High; N+1 and error handling as Medium; uses consistent severity framework",
|
|
25
|
+
"3": "Mostly correct severity assignment with minor misclassifications",
|
|
26
|
+
"1": "Inconsistent or incorrect severity levels",
|
|
27
|
+
"0": "No severity classification"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"criterion": "Fix Quality",
|
|
32
|
+
"weight": 0.25,
|
|
33
|
+
"scoring": {
|
|
34
|
+
"5": "Provides copy-pasteable code fixes for each issue: parameterized queries, bcrypt hashing, JWT tokens, authorization middleware, eager loading/JOIN for N+1, try-catch blocks",
|
|
35
|
+
"3": "Provides fix descriptions but not all with code examples",
|
|
36
|
+
"1": "Vague fix suggestions like 'sanitize input'",
|
|
37
|
+
"0": "No fix suggestions"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"criterion": "Report Structure",
|
|
42
|
+
"weight": 0.2,
|
|
43
|
+
"scoring": {
|
|
44
|
+
"5": "Structured report with summary, severity-grouped findings, health scores, positive observations (if any), and prioritized action items",
|
|
45
|
+
"3": "Some structure but missing components (e.g., no summary or no prioritization)",
|
|
46
|
+
"1": "Flat list of issues with no organization",
|
|
47
|
+
"0": "Unstructured prose"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"passThreshold": 60
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|