scan-reward-hacking · v1.0.0 · 2026-03-20 · sha256 1afa37f80d2af681
scan-reward-hacking v1.0.0A
Immutable. This exact content is served forever at /api/v1/blob/1afa37f80d2af681.
---
name: scan-reward-hacking
description: Scan for reward hacking patterns in recent changes
disable-model-invocation: true
allowed-tools: Bash, Read, Grep
version: 1.0.0
---
# Scan for Reward Hacking Patterns
You are scanning for "reward hacking" patterns - code that makes linters pass without actually fixing type safety issues. This is a verification step that MUST be run before marking TypeScript work complete.
## What to Scan
Scan the project structure and look for `src/`, `apps/`, `packages/`, `lib/` directories. If `$ARGUMENTS` is provided, scan those paths instead.
Store the detected scan targets in a variable (e.g., `SCAN_DIRS`) and use them in all grep commands below.
## Forbidden Patterns to Detect
Run these grep commands against the detected directories and report ALL matches:
```bash
# 1. Undocumented double-casts (HIGH SEVERITY)
grep -rn "as unknown as" $SCAN_DIRS --include="*.ts" --include="*.tsx"
# 2. Direct any casts (HIGH SEVERITY)
grep -rn "as any" $SCAN_DIRS --include="*.ts" --include="*.tsx"
# 3. Void tricks to suppress unused warnings (CRITICAL - IMMEDIATE FIX)
grep -rn "void (0" $SCAN_DIRS --include="*.ts" --include="*.tsx"
grep -rn "void _" $SCAN_DIRS --include="*.ts" --include="*.tsx"
# 4. Underscore-prefixed local variables (MEDIUM SEVERITY)
# Look for const _varName = or let _varName = that aren't function parameters
grep -rn "const _[a-zA-Z]" $SCAN_DIRS --include="*.ts" --include="*.tsx"
grep -rn "let _[a-zA-Z]" $SCAN_DIRS --include="*.ts" --include="*.tsx"
# 5. TypeScript directive comments (HIGH SEVERITY)
grep -rn "@ts-ignore" $SCAN_DIRS --include="*.ts" --include="*.tsx"
grep -rn "@ts-expect-error" $SCAN_DIRS --include="*.ts" --include="*.tsx"
# 6. Exported but potentially unused types (LOW SEVERITY - informational)
# This requires more analysis - flag for manual review
grep -rn "^export type [A-Z]" $SCAN_DIRS --include="*.ts" --include="*.tsx"
grep -rn "^export interface [A-Z]" $SCAN_DIRS --include="*.ts" --include="*.tsx"
```
## How to Evaluate Matches
### `as unknown as` - Check for Documentation
**ACCEPTABLE** (has required documentation):
```typescript
// LIBRARY TYPE LIMITATION: The thirdPartyWrapper() function returns a type
// that TypeScript can't verify implements the expected interface.
// Verified at runtime that the object has the required methods.
// TODO: Remove when library updates types (tracked in TICKET-XXX)
const wrapped = thirdPartyResult as unknown as ExpectedInterface;
```
**NOT ACCEPTABLE** (no documentation):
```typescript
const campaigns = result as unknown as Campaign[];
```
### `as any` - Almost Always Wrong
**ACCEPTABLE** (rare - only in test mocks):
```typescript
// In test file only
const mockDb = { query: vi.fn() } as any as Database;
```
**NOT ACCEPTABLE** (production code):
```typescript
const data = response.data as any;
```
### `void` Patterns - Always Wrong
**NEVER ACCEPTABLE**:
```typescript
void (0 as unknown as _Type); // Lint suppression trick
void _schemaCheck; // Unused variable suppression
```
### Underscore Variables - Context Matters
**ACCEPTABLE** (function parameters):
```typescript
function handleEvent(_event: Event, data: Data) {
// _event intentionally unused
return process(data);
}
```
**NOT ACCEPTABLE** (local variables):
```typescript
const _user = useUser(); // Keep for future use <- DELETE THIS
```
## Output Format
Present findings in this format:
```markdown
## Reward Hacking Scan Results
### CRITICAL (Must Fix Immediately)
- `file.ts:123` - `void (0 as unknown as Type)` - Lint suppression trick
### HIGH SEVERITY (Must Fix Before Merge)
- `file.ts:456` - `as unknown as Campaign[]` - Missing documentation
- `file.ts:789` - `as any` in production code
### MEDIUM SEVERITY (Should Fix)
- `file.ts:101` - `const _user = ...` - Unused local variable
### ACCEPTABLE (No Action Needed)
- `file.test.ts:50` - `as any` in test mock - Standard test practice
- `file.ts:200` - `as unknown as` with full documentation - Third-party limitation
### Summary
- Critical: X issues
- High: Y issues
- Medium: Z issues
- Total requiring action: X + Y + Z
```
## Verdict
After scanning, provide a clear verdict:
**PASS**: No forbidden patterns found, or all patterns are properly documented/in tests.
**FAIL**: Forbidden patterns found that require fixes before work can be considered complete.
## If FAIL
List the specific fixes needed:
```markdown
## Required Fixes
1. `apps/api/src/services/UserService.ts:243`
- Current: `as unknown as CreateUserRequest`
- Fix: Fix the query return type or add Zod validation at the boundary
2. `apps/web/src/pages/Dashboard.tsx:117`
- Current: `const _user = useUser();`
- Fix: Delete the line entirely
```
The agent must address ALL issues before marking their work complete.