227 lines
4.4 KiB
Markdown
227 lines
4.4 KiB
Markdown
|
|
# Code Quality Checklist
|
||
|
|
|
||
|
|
This document provides a quick reference for code quality checks that MUST be performed before completing any story.
|
||
|
|
|
||
|
|
## Pre-Completion Checklist
|
||
|
|
|
||
|
|
Before asking for user acceptance in Step 4 (Verification), ALL of the following must pass:
|
||
|
|
|
||
|
|
### Rust Backend
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Run Clippy (linter)
|
||
|
|
cd src-tauri
|
||
|
|
cargo clippy --all-targets --all-features
|
||
|
|
# Expected: 0 errors, 0 warnings
|
||
|
|
|
||
|
|
# 2. Run cargo check (compilation)
|
||
|
|
cargo check
|
||
|
|
# Expected: successful compilation
|
||
|
|
|
||
|
|
# 3. Run tests
|
||
|
|
cargo test
|
||
|
|
# Expected: all tests pass
|
||
|
|
```
|
||
|
|
|
||
|
|
**Result Required:** ✅ 0 errors, 0 warnings, all tests pass
|
||
|
|
|
||
|
|
### TypeScript Frontend
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Run TypeScript compiler check (type errors)
|
||
|
|
npx tsc --noEmit
|
||
|
|
# Expected: 0 errors
|
||
|
|
|
||
|
|
# 2. Run Biome check (linter + formatter)
|
||
|
|
npx @biomejs/biome check src/
|
||
|
|
# Expected: 0 errors, 0 warnings
|
||
|
|
|
||
|
|
# 3. Apply fixes if needed
|
||
|
|
npx @biomejs/biome check --write src/
|
||
|
|
npx @biomejs/biome check --write --unsafe src/ # for unsafe fixes
|
||
|
|
|
||
|
|
# 4. Build
|
||
|
|
npm run build
|
||
|
|
# Expected: successful build
|
||
|
|
```
|
||
|
|
|
||
|
|
**Result Required:** ✅ 0 errors, 0 warnings, successful build
|
||
|
|
|
||
|
|
## Common Biome Issues and Fixes
|
||
|
|
|
||
|
|
### 1. `noExplicitAny` - No `any` types
|
||
|
|
|
||
|
|
**Bad:**
|
||
|
|
```typescript
|
||
|
|
const handler = (data: any) => { ... }
|
||
|
|
```
|
||
|
|
|
||
|
|
**Good:**
|
||
|
|
```typescript
|
||
|
|
const handler = (data: { className?: string; children?: React.ReactNode; [key: string]: unknown }) => { ... }
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. `noArrayIndexKey` - Don't use array index as key
|
||
|
|
|
||
|
|
**Bad:**
|
||
|
|
```typescript
|
||
|
|
{items.map((item, idx) => <div key={idx}>...</div>)}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Good:**
|
||
|
|
```typescript
|
||
|
|
{items.map((item, idx) => <div key={`item-${idx}-${item.id}`}>...</div>)}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. `useButtonType` - Always specify button type
|
||
|
|
|
||
|
|
**Bad:**
|
||
|
|
```typescript
|
||
|
|
<button onClick={handler}>Click</button>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Good:**
|
||
|
|
```typescript
|
||
|
|
<button type="button" onClick={handler}>Click</button>
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. `noAssignInExpressions` - No assignments in expressions
|
||
|
|
|
||
|
|
**Bad:**
|
||
|
|
```typescript
|
||
|
|
onMouseOver={(e) => (e.currentTarget.style.background = "#333")}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Good:**
|
||
|
|
```typescript
|
||
|
|
onMouseOver={(e) => {
|
||
|
|
e.currentTarget.style.background = "#333";
|
||
|
|
}}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5. `useKeyWithMouseEvents` - Add keyboard alternatives
|
||
|
|
|
||
|
|
**Bad:**
|
||
|
|
```typescript
|
||
|
|
<button onMouseOver={handler} onMouseOut={handler2}>...</button>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Good:**
|
||
|
|
```typescript
|
||
|
|
<button
|
||
|
|
onMouseOver={handler}
|
||
|
|
onMouseOut={handler2}
|
||
|
|
onFocus={handler}
|
||
|
|
onBlur={handler2}
|
||
|
|
>...</button>
|
||
|
|
```
|
||
|
|
|
||
|
|
### 6. `useImportType` - Import types with `import type`
|
||
|
|
|
||
|
|
**Bad:**
|
||
|
|
```typescript
|
||
|
|
import { Message, Config } from "./types";
|
||
|
|
```
|
||
|
|
|
||
|
|
**Good:**
|
||
|
|
```typescript
|
||
|
|
import type { Message, Config } from "./types";
|
||
|
|
```
|
||
|
|
|
||
|
|
## Common Clippy Issues and Fixes
|
||
|
|
|
||
|
|
### 1. Unused variables
|
||
|
|
|
||
|
|
**Bad:**
|
||
|
|
```rust
|
||
|
|
} catch (e) {
|
||
|
|
```
|
||
|
|
|
||
|
|
**Good:**
|
||
|
|
```rust
|
||
|
|
} catch (_e) { // prefix with underscore
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Dead code warnings
|
||
|
|
|
||
|
|
**Option 1:** Remove the code if truly unused
|
||
|
|
|
||
|
|
**Option 2:** Mark as allowed if used conditionally
|
||
|
|
```rust
|
||
|
|
#[allow(dead_code)]
|
||
|
|
struct UnusedStruct {
|
||
|
|
field: String,
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Explicit return
|
||
|
|
|
||
|
|
**Bad:**
|
||
|
|
```rust
|
||
|
|
fn get_value() -> i32 {
|
||
|
|
return 42;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Good:**
|
||
|
|
```rust
|
||
|
|
fn get_value() -> i32 {
|
||
|
|
42
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Quick Verification Script
|
||
|
|
|
||
|
|
Save this as `check.sh` and run before every story completion:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
#!/bin/bash
|
||
|
|
set -e
|
||
|
|
|
||
|
|
echo "=== Checking Rust Backend ==="
|
||
|
|
cd src-tauri
|
||
|
|
cargo clippy --all-targets --all-features
|
||
|
|
cargo check
|
||
|
|
cargo test
|
||
|
|
cd ..
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "=== Checking TypeScript Frontend ==="
|
||
|
|
npx tsc --noEmit
|
||
|
|
npx @biomejs/biome check src/
|
||
|
|
npm run build
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "✅ ALL CHECKS PASSED!"
|
||
|
|
```
|
||
|
|
|
||
|
|
## Zero Tolerance Policy
|
||
|
|
|
||
|
|
- **No exceptions:** All errors and warnings MUST be fixed
|
||
|
|
- **No workarounds:** Don't disable rules unless absolutely necessary
|
||
|
|
- **No "will fix later":** Fix immediately before story completion
|
||
|
|
- **User must see clean output:** When running checks, show clean results to user
|
||
|
|
|
||
|
|
## When Rules Conflict with Requirements
|
||
|
|
|
||
|
|
If a linting rule conflicts with a legitimate requirement:
|
||
|
|
|
||
|
|
1. Document why the rule must be bypassed
|
||
|
|
2. Use the minimal scope for the exception (line/function, not file)
|
||
|
|
3. Add a comment explaining the exception
|
||
|
|
4. Get user approval
|
||
|
|
|
||
|
|
Example:
|
||
|
|
```typescript
|
||
|
|
// Biome requires proper types, but react-markdown types are incompatible
|
||
|
|
// Using unknown for compatibility
|
||
|
|
const code = ({ className, children }: { className?: string; children?: React.ReactNode; [key: string]: unknown }) => {
|
||
|
|
...
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Integration with SDSW
|
||
|
|
|
||
|
|
This checklist is part of **Step 4: Verification** in the Story-Driven Spec Workflow.
|
||
|
|
|
||
|
|
**You cannot proceed to story acceptance without passing all checks.**
|