Files
metabuilder/docs/stub-detection/README.md
2025-12-25 13:05:24 +00:00

550 lines
12 KiB
Markdown

# Stub Implementation Detection Guide
## Overview
Stub detection automatically identifies incomplete, placeholder, or mock implementations in the codebase. This prevents accidental deployment of unfinished code and helps teams track what still needs to be completed.
## What is a Stub?
A stub is a function or component that:
- Throws "not implemented" errors
- Returns placeholder values (null, empty objects, mock data)
- Contains TODO/FIXME comments indicating incomplete work
- Only logs to console without doing real work
- Has minimal/empty implementation
- Contains placeholder text in UI
## Detection Methods
### 1. Pattern-Based Detection
Scans code for specific patterns that indicate stubs:
#### Error Throwing
```typescript
// ❌ Detected as stub
export function processData(data) {
throw new Error('not implemented')
}
```
#### Console Logging Only
```typescript
// ❌ Detected as stub
export function validateEmail(email) {
console.log('validating:', email) // Nothing else
}
```
#### Null/Undefined Returns
```typescript
// ❌ Detected as stub
export function fetchData() {
return null
}
```
#### Placeholder Text
```typescript
// ❌ Detected as stub
function Dashboard() {
return <div>TODO: Build dashboard</div>
}
```
#### Mock Data with Markers
```typescript
// ❌ Detected as stub
export function getUsers() {
return [ // stub data
{ id: 1, name: 'John' }
]
}
```
### 2. Completeness Analysis
Analyzes implementation quality:
- **Logical Lines**: Actual code (excluding returns and comments)
- **Return Lines**: How many return statements
- **JSX Lines**: For components, how much actual UI
- **Completeness Score**: 0-100% based on implementation density
**Scoring**:
- **0%**: Throws not implemented error
- **0-30%**: Critical (only logging, returning null, no real logic)
- **30-60%**: Medium (minimal implementation, mostly mock data)
- **60-80%**: Low (mostly complete, some placeholders)
- **80-100%**: Good (real implementation)
### 3. Code Indicators
Detects special markers:
| Indicator | Severity | Meaning |
|-----------|----------|---------|
| `throw new Error('not implemented')` | Critical | Explicitly unimplemented |
| `// TODO:` or `// FIXME:` | Medium | Known issue, incomplete |
| `console.log()` only | High | Debug logging, not real code |
| `// mock`, `// stub` | Medium | Explicitly marked placeholder |
| `return null` | Low | Empty return value |
| `<> </>` | High | Empty component fragment |
## Workflow Integration
### Automatic Detection
The `detect-stubs.yml` workflow runs:
- On every PR (to flag new stubs)
- On every push to main/master
- Weekly scheduled (Monday midnight)
### PR Comments
Posts a summary comment showing:
- Total stubs found
- Severity breakdown
- Critical issues with file/line/function
- Recommendations for fixes
Example:
```
## 🔍 Stub Implementation Detection Report
### Summary
- Pattern-Based Stubs: 5
- Low Completeness Items: 3
- Average Completeness: 72%
### Severity Breakdown
- 🔴 Critical: 2
- 🟠 Medium: 2
- 🟡 Low: 1
### 🔴 Critical Issues Found
| File | Line | Function | Type |
|------|------|----------|------|
| src/api/users.ts | 42 | fetchUsers | throws-not-implemented |
| src/components/Dashboard.tsx | 15 | Dashboard | empty-fragment |
```
## Local Usage
### Run Detection Locally
```bash
# Pattern-based stub detection
npx tsx scripts/detect-stub-implementations.ts
# Completeness analysis
npx tsx scripts/analyze-implementation-completeness.ts
# Generate detailed report
npx tsx scripts/generate-stub-report.ts
# All three
npm run detect-stubs
```
### Output Formats
All scripts output JSON for programmatic access:
#### Pattern Detection Output
```json
{
"totalStubsFound": 5,
"bySeverity": {
"high": 2,
"medium": 2,
"low": 1
},
"byType": {
"not-implemented": 2,
"todo-comment": 1,
"console-log-only": 1,
"returns-empty-value": 1
},
"criticalIssues": [
{
"file": "src/api/users.ts",
"line": 42,
"function": "fetchUsers",
"type": "not-implemented"
}
]
}
```
#### Completeness Analysis Output
```json
{
"totalAnalyzed": 45,
"bySeverity": {
"critical": 2,
"high": 5,
"medium": 8,
"low": 12
},
"flagTypes": {
"has-todo-comments": 5,
"throws-not-implemented": 2,
"only-console-log": 1
},
"averageCompleteness": 72.4,
"criticalStubs": [
{
"file": "src/api/users.ts",
"line": 42,
"name": "fetchUsers",
"type": "function",
"flags": ["throws-not-implemented"],
"summary": "Potential stub: throws-not-implemented"
}
]
}
```
## Common Stub Patterns & Fixes
### Pattern 1: Not Implemented Error
**Problem**: Function explicitly throws unimplemented error
**Severity**: 🔴 Critical
**Fix**: Implement the function
```typescript
// ❌ Before
export async function fetchUserData(id: string) {
throw new Error('not implemented')
}
// ✅ After
export async function fetchUserData(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`)
if (!response.ok) throw new Error(`Failed to fetch user ${id}`)
return response.json()
}
```
### Pattern 2: Console Logging Only
**Problem**: Function only logs without doing real work
**Severity**: 🟠 High
**Fix**: Replace logging with actual implementation
```typescript
// ❌ Before
export function calculateTotal(items: Item[]): number {
console.log('calculating total for:', items)
// nothing else
}
// ✅ After
export function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0)
}
```
### Pattern 3: Return Null/Undefined
**Problem**: Function returns null or undefined
**Severity**: 🟡 Medium
**Fix**: Return actual data or use types to force implementation
```typescript
// ❌ Before
export function getConfig() {
return null // TODO: load config
}
// ✅ After
export function getConfig(): Config {
return configLoader.load()
}
```
### Pattern 4: Placeholder Component
**Problem**: Component renders placeholder text instead of UI
**Severity**: 🟠 High
**Fix**: Implement the component properly
```typescript
// ❌ Before
export function Dashboard() {
return <div>TODO: Build dashboard</div>
}
// ✅ After
export function Dashboard() {
return (
<div className="dashboard">
<Header />
<Sidebar />
<MainContent />
</div>
)
}
```
### Pattern 5: Mock Data
**Problem**: Function returns hardcoded mock data
**Severity**: 🟠 Medium
**Fix**: Replace with real data source
```typescript
// ❌ Before
export function getUsers(): User[] {
return [ // mock data
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane', email: 'jane@example.com' }
]
}
// ✅ After
export async function getUsers(): Promise<User[]> {
const data = await Database.query('SELECT * FROM users')
return data.map(row => new User(row))
}
```
### Pattern 6: TODO Comments
**Problem**: Code has TODO/FIXME comments indicating incomplete work
**Severity**: 🟡 Medium/Low
**Fix**: Create GitHub issue and remove TODO from code
```typescript
// ❌ Before
export function validateEmail(email: string): boolean {
// TODO: Add real email validation
return true
}
// ✅ After (create issue #123 first)
export function validateEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return emailRegex.test(email)
}
```
### Pattern 7: Empty Component
**Problem**: Component has minimal or empty JSX
**Severity**: 🟠 High
**Fix**: Implement the component's UI
```typescript
// ❌ Before
export function UserList() {
return <div></div>
}
// ✅ After
export function UserList() {
const users = useQuery('users')
return (
<div className="user-list">
{users.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
)
}
```
## Best Practices
### 1. Never Leave Stubs in Main Branch
```bash
# Before merging, ensure no stubs in changed files
git diff HEAD~1 -- 'src/**/*.ts' | grep -i 'todo\|not implemented'
```
### 2. Use Types to Force Implementation
```typescript
// ❌ Function can return anything
function getValue() {
// oops, forgot to implement
}
// ✅ Type forces implementation
function getValue(): string {
// TypeScript error: missing return
// MUST implement
}
```
### 3. Create Issues Instead of TODOs
```typescript
// ❌ Don't do this
function processData(data) {
// TODO: add caching (#TBD)
return compute(data)
}
// ✅ Do this
// Implemented cache per issue #456
const cache = new LRUCache()
function processData(data) {
return cache.getOrCompute(data, () => compute(data))
}
```
### 4. Test Stubs Explicitly
```typescript
// Make stubs fail tests explicitly
describe('getUsers', () => {
it('should fetch users from API', async () => {
// This WILL fail if implementation is missing
const users = await getUsers()
expect(users).toBeDefined()
expect(users.length).toBeGreaterThan(0)
expect(users[0].name).toBeDefined()
})
})
```
### 5. Use Linting to Prevent Stubs
Add ESLint rules to `.eslintrc.json`:
```json
{
"rules": {
"no-console": ["error", { "allow": ["warn", "error"] }],
"no-throw-literal": "error",
"no-empty-function": ["error", { "allow": ["arrowFunctions"] }]
}
}
```
## Interpreting the Report
### Severity Levels
- **🔴 Critical** (Completeness: 0%)
- Blocks production
- Must fix immediately
- Examples: `throw new Error('not implemented')`
- **🟠 High** (Completeness: 10-30%)
- Should fix before merge
- Likely causes bugs
- Examples: Console logging only, empty components
- **🟡 Medium** (Completeness: 40-70%)
- Should fix soon
- Partial implementation
- Examples: Mock data, basic structure
- **🟢 Low** (Completeness: 80-99%)
- Nice to fix
- Mostly complete
- Examples: Minor TODOs, edge cases
### Metrics Explained
| Metric | Meaning |
|--------|---------|
| Logical Lines | Lines that do actual work (not returns/comments) |
| Return Lines | Number of return statements |
| JSX Lines | For components, lines rendering UI |
| Completeness | Estimated % of implementation done |
| Flags | Detected stub indicators |
## Artifacts
The workflow uploads three artifacts:
1. **stub-patterns.json** - Raw pattern detection data
2. **implementation-analysis.json** - Completeness scoring
3. **stub-report.md** - Formatted markdown report
4. **changed-stubs.txt** - Stubs in changed files (PRs only)
Available for 30 days after workflow run.
## CI/CD Integration
### Failing Builds
The workflow runs with `continue-on-error: true`, so stubs don't block merging. However, you can:
1. Enable stricter linting to fail on TODOs
2. Require test coverage (which fails with stubs)
3. Use branch protection rules to require review of detected stubs
### GitHub Checks
- Posts check run with stub detection results
- Shows in PR checks section
- Includes summary of critical issues
## Troubleshooting
### "No stubs found" but code looks incomplete
- Patterns may not match your specific style
- Check individual function with completeness analyzer
- Consider adding custom patterns to detection script
### Too many false positives
- Edit `STUB_PATTERNS` in `detect-stub-implementations.ts`
- Adjust completeness thresholds in `analyze-implementation-completeness.ts`
- Add file/function exclusions
### Stubs not showing in PR comment
- Check workflow permissions (needs `pull-requests: write`)
- Verify GitHub API isn't rate limited
- Check workflow logs for errors
## Extension Points
### Add Custom Patterns
Edit `scripts/detect-stub-implementations.ts`:
```typescript
const STUB_PATTERNS = [
// ... existing patterns
{
name: 'Your custom pattern',
pattern: /your regex here/,
type: 'custom-stub',
severity: 'high',
description: 'Your description'
}
]
```
### Add Custom Analysis
Create new script in `scripts/`:
```bash
npx tsx scripts/my-custom-analysis.ts > my-report.json
```
Then add to workflow in `.github/workflows/detect-stubs.yml`.
## References
- [Workflow Definition](.github/workflows/detect-stubs.yml)
- [Detection Script](scripts/detect-stub-implementations.ts)
- [Completeness Analyzer](scripts/analyze-implementation-completeness.ts)
- [Report Generator](scripts/generate-stub-report.ts)
---
**Last updated**: December 25, 2025