mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 14:25:02 +00:00
550 lines
12 KiB
Markdown
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
|