# Cursor Final-Review Pipeline → Manual Fix Workflow

A reusable pattern: use Cursor's strongest model for a read-only external review, then fix Critical/High findings manually with safe patches. This bridges the gap between "audit" (Cursor) and "fix" (manual).

## When to Use

- A project has already undergone multi-model audits (Kimi, Qwen, DeepSeek) and needs a **final external review** from Cursor's strongest model before go-live
- You want a fresh set of eyes with no prior bias from the project's audit history
- The codebase is mature (tests pass, lint clean, mypy clean) and you need a production-readiness stamp

## Workflow Steps

### 1. Read Context First

```bash
# Read handoff docs to understand current state
# Check git HEAD, test baseline, lint/type-check baseline
git log --oneline -3
pytest -q -m "not integration" --tb=no
ruff check app tests
mypy app
```

Also read: `docs/SESSION_HANDOFF.md`, `docs/NEXT_SESSION_START.md`, `docs/backend-audit-consolidated.md` to understand prior findings and deferred items.

### 2. Launch Cursor Read-Only Review

```bash
agent -p "IMPORTANT: You are doing a final external code review of [project]...

[Comprehensive prompt with:]
- Project state summary
- Prior audit findings (37/55 fixed, 5 unfixed, etc.)
- Review scope (production-readiness, architecture, security, etc.)
- Constraints (DO NOT add features, DO NOT rewrite, DO NOT make changes)
- OUTPUT FORMAT with severity levels
- Instructions to use --mode ask (read-only)

=== FINDINGS ===
### Critical (N issues)
### High (N issues)
### Medium (N issues)
### Low (N issues)

=== VERDICT ===
Ready for UI/UX walkthrough? Yes/No (with justification)
" \
  --model claude-opus-4-7-thinking-max \
  --mode ask \
  --workspace /path/to/project \
  --trust 2>&1
```

**Model choice:** Always use `claude-opus-4-7-thinking-max` for the most thorough review. This is Cursor's strongest available model (Opus 4.7 with 1M Max Thinking context).

**Prompt structure (proven pattern from real session):**
The prompt should include these sections in order:
1. **Project State** — HEAD commit, test count, lint/mypy status, what's been built, what's deferred
2. **Prior Audit Context** — how many findings already fixed, how many unfixed/deferred (so Cursor doesn't duplicate)
3. **Review Scope** — 10-12 specific areas to examine (production-readiness, auth/security, Docker/infra, test quality, etc.)
4. **Constraints** — DO NOT add features, DO NOT rewrite, DO NOT weaken tests, ASK before architecture changes
5. **Required Output Format** — severity tables with file:line and details
6. **Verdict** — Yes/No with justification

### 3. Evaluate Findings

Cursor outputs findings as `--mode ask` which prevents any file edits. Review and classify:

- **Critical** — Data loss, security vulns, correctness bugs → fix immediately
- **High** — Production-readiness gaps, reliability, contract issues → fix this batch
- **Medium** — Code quality, maintainability → fix if trivial (< 5 lines)
- **Low** — Style, cosmetics, deferred items → skip unless trivial

Cross-reference against the project's existing audit to avoid duplicated effort.

### 4. Present Findings with Opinionated Recommendations

When presenting findings to the user, **don't just dump the table.** The user wants:
- Opinionated yes/no/maybe on what to fix, with effort estimates and risk assessment
- Clear grouping: "✅ Do these — trivial, zero risk" vs "🤷 Worth doing — low risk" vs "⏭️ Skip"
- The reasoning behind each recommendation, not just options
- This avoids the user having to ask "should I fix all of these?"

Pattern (proven effective): pick 3 buckets:
```
**✅ Do these — trivial, zero risk, < 3 lines each:**
- ID: Fix (1 line)

**🤷 Worth doing — low risk, small patch:**
- ID: Fix (~8 lines)

**⏭️ Skip these — not worth the churn:**
- ID: Reason (architectural, dead code, cosmetic)
```

### 5. Fix Critical + High (Manual Patches)

For each finding that needs a fix:

```bash
# 1. Read the current code
read_file path/to/file.py

# 2. Apply the fix (minimal, safe change)
patch old_string=... new_string=... path=...

# 3. Repeat for all independent fixes in a batch
# Use the todo tool to track progress
todo todos=[...]
```

**Fix order (within same severity class):**
1. Configuration / ops fixes (environment vars, pool settings, nginx)
2. Small structural fixes (import hoisting, type annotations, error mappings)
3. Data integrity fixes (unique constraints, upsert keys, migration)
4. Interface contract fixes (response schemas, OpenAPI)

**For items that need a user decision (architectural changes):**
- Present the finding with clear options
- Recommend one option and explain why
- Defer if the user isn't available

### 6. Watch for Silent Patch Failures

**Known gotcha:** When `patch()` receives identical `old_string` and `new_string`, it returns success without making changes. This is easy to trigger when you copy-paste the existing code as your baseline, accidentally edit nothing, and call patch. Always verify the diff output shows actual changes. If in doubt, re-read the file after patching.

### 7. Run Verification After Each Batch

```bash
pytest -q -m "not integration" --tb=short
ruff check app tests alembic
mypy app
```

Address any regressions:
- Unused imports (`F401`) — remove or run `ruff check --fix`
- Import sorting (`I001`) — run `ruff check --fix`
- SIM108/SIM105 style nits — run `ruff check --fix --unsafe-fixes`
- Missing type imports (`F821`) — manual patch

### 8. Commit Separately

Each fix gets its own commit with a clear message:

```
fix: cursor-review — [description] ([finding ID])
```

Group related fixes (same module, same type) into one commit.

## Known Findings Patterns

From real sessions, Cursor's strongest model catches:

| Pattern | Cursor Finds Well | Notes |
|---------|-------------------|-------|
| TV episode discrimination bugs | Critical data-loss issues | SQL upsert keys missing season/episode |
| DB pool tuning gaps | Production-readiness | Missing pool_recycle, pool_size |
| API contract inconsistencies | Response model mismatches | ErrorResponse.shape vs HTTPException.detail |
| Unique constraint gaps | Race-condition prevention | Missing on profile sub-tables |
| Security header / key mgmt gaps | ENCRYPTION_KEY fallback | Key separation enforcement |
| Async singleton races | Medium confidence | Often duplicates prior audit findings |
| Cross-module coupling | Known, flags as ASK | Architecture decisions, needs user input |
| Docker compose string interpolation edge cases | Env var :? vs :- | Production validation |

## Things Cursor's Strongest Model Overlooked This Session

No review is perfect. In the May 17, 2026 session, Cursor missed:
- **Existing redundant double-rollback** in debrid repo (L8 fix existed for user repo but wasn't propagated)
- **Existing profile dependency type hint issue** (AsyncIterator vs AsyncSession)
- **media_type regex misalignment** (movie/tv vs series from Stremio)

These were Medium-level items caught by my own reading of the codebase. Lesson: **always do your own file reading** even after a Cursor review.

## Example Prompt (Abridged from Real Session)

```
IMPORTANT: You are doing a final external code review of a streaming app backend...

## Project State
This is a FastAPI + SQLAlchemy async DDD backend with 6 complete modules.
Git HEAD: cba8d09. 511 unit tests passing, ruff clean, mypy clean.
3 multi-model audit passes already completed. 37/55 findings fixed. 5 unfixed remain.

## Your Job — Final Senior-Engineering Review
Review for:
1. Production-readiness — logging, error handling, graceful shutdown
2. Backend architecture — DDD layering, circular imports, module boundaries
3. Auth/session/security — JWT, refresh rotation, rate limiting, CORS
4. Docker/PostgreSQL/Redis — pool settings, connection lifecycle
5. Profile system — watch history, continue-watching, last-profile protection
6. API contract consistency — all error responses use {"detail": "..."}
7. Streaming resolver reliability — timeout handling, fallback chains
8. Redis/cache behavior — singleton client, TTLs, fail-open
9. Async/performance risks — blocking calls, N+1 queries
10. Test quality — coverage gaps, fixture correctness

## Constraints — STRICT RULES
- DO NOT add features
- DO NOT rewrite working systems
- DO NOT change code unless fixing Critical or High findings
- For Medium/Low: only fix if TRULY trivial (< 5 lines)
- For architecture changes: ASK FIRST
```

## Post-Audit: Fixing Tests Broken by Interface Changes

When fixing Critical findings (e.g., TV episode discrimination), interface signatures often change (new optional params). This breaks mock repositories in test files. Fix pattern:

1. Update the **port/interface** (`interfaces.py`) — add optional params with `= None` defaults
2. Update the **implementation** (`repositories.py`) — add the params
3. Update the **application layer** (`use_cases.py`) — forward the params
4. Update the **presentation layer** (`routers.py`) — accept optional query params
5. Update **test mocks** — add the same optional params with matching signatures
6. Do NOT change test logic — only update mock method signatures

Key principle: **all new params are optional with `= None` defaults** so existing callers and tests that don't pass them continue to work with the old (previously buggy) behavior.
