Skip to content

PR-Ready Checklist (/pr-ready)

In plain terms

The final quality gate: run this before you call a task "done" to make sure everything is verified and ready to submit.

What this skill does

Quality gate and verification steps before finishing a task or submitting code

[!IMPORTANT] Run this before telling the user "I'm done" with any non-trivial task.

Trigger Conditions

  • Keywords: "I'm done", "Submit this", "Prepare for PR", "Finished", "Ready to commit"

Step 0a — Backend Reachability Check (REQUIRED, DO FIRST)

Before anything else, verify the backend is reachable:

  1. Run curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/api/system/health || echo "unreachable"
  2. If reachable (returns 200): continue to Step 0b.
  3. If not reachable:
  4. Attempt to start the backend: cd /Users/ronaldtermaat/Applications/DoubleDiamond/backend && uvicorn main:app --reload --port 8000 &
  5. Wait up to 15 seconds by polling: for i in {1..15}; do sleep 1; curl -s http://localhost:8000/api/system/health && break; done
  6. If still not reachable after 15 seconds: STOP and tell the user: > "The backend is not reachable at http://localhost:8000. Please start it with cd backend && uvicorn main:app --reload --port 8000 and re-run /pr-ready."
  7. Do NOT continue until the backend is confirmed reachable.

Step 0b — Branch Sync Check (REQUIRED, DO FIRST)

Verify the local branch is up to date with remote main:

  1. Run git fetch origin main
  2. Run git log HEAD..origin/main --oneline to check if remote main has commits not present locally
  3. If there are new commits on remote main:
  4. Inform the user that remote main has diverged (show the new commit list)
  5. Run git merge origin/main to merge the remote changes into the current local branch
  6. If the merge produces conflicts, STOP immediately. List the conflicting files and ask the user to resolve them before continuing.
  7. If the merge succeeds cleanly, inform the user and continue to Step 1.
  8. If there are no new commits, continue to Step 1.

Step 1 — Progress Tracking (REQUIRED)

Create a TodoWrite task list so the user can see live progress:

0a. Backend reachability check             (pending)
0b. Branch sync check                      (pending)
1.  Frontend lint                          (pending)
2.  Frontend type-check                    (pending)
3.  Backend type-check (mypy)              (pending)
4.  OpenAPI sync check                     (pending)
5.  Frontend tests                         (pending)
6.  Backend tests (pytest)                 (pending)
7.  SonarCloud scan                        (pending)
8.  SonarQube quality gate                 (pending)
9.  SonarQube issues                       (pending)
10. SonarQube duplication                  (pending)
11. E2E tests                              (pending)
12. Console cleanup                        (pending)
13. Auth guards                            (pending)
14. No any types                           (pending)
15. Causal order                           (pending)
16. API types check                        (pending)
17. Test alignment                         (pending)
18. Architecture review                    (pending)
19. Temp cleanup                           (pending)
20. Release notes                          (pending)
21. Summary                                (pending)

Mark each item in_progress when you start it and completed when it passes. Keep it in_progress while fixes are being applied.


Phase 1 — Static Analysis (Steps 2–5 in PARALLEL)

Send a single message with four tool calls running simultaneously:

  • Step 2 — Frontend Lint: cd frontend && npm run lint
  • Step 3 — Frontend Type-Check: cd frontend && npm run check
  • Step 4 — Backend Type-Check: cd backend && python -m mypy app/ (skip silently if mypy is not installed/configured — mark as N/A)
  • Step 5 — OpenAPI Sync Check: Inspect git diff --name-only main...HEAD for changes under backend/app/ — if any backend route or schema files were modified, flag that /openapi-sync must be run before continuing

Wait for all four to complete before proceeding. Handle any failures (see auto-fix steps below) before moving to Phase 2.


Step 2a — Frontend Lint Auto-Fix (max 2 iterations)

If Step 2 produced lint errors:

  1. Group errors by file domain:
  2. Group A: frontend/src/components/**
  3. Group B: frontend/src/hooks/**, frontend/src/services/**, frontend/src/context/**
  4. Group C: frontend/src/pages/** and any other frontend/src/** files

  5. Launch one subagent per group in parallel. Each agent must:

  6. Read the affected file(s) first
  7. Apply fixes using Edit tool only — no bash commands inside the agent
  8. Follow existing code style

  9. After all agents complete, re-run cd frontend && npm run lint.

  10. If errors remain after iteration 2, STOP and report them — do not attempt a third iteration.


Step 3a — Frontend TypeScript Auto-Fix (max 2 iterations)

If Step 3 produced type errors:

  1. Group errors by the same file domains as Step 2a (Groups A, B, C).

  2. Launch one subagent per group in parallel. Each agent must:

  3. Read the affected file(s) first
  4. Fix only type errors — do not refactor unrelated code

  5. After all agents complete, re-run cd frontend && npm run check.

  6. If errors remain after iteration 2, STOP and report them.


Phase 2 — Tests (Step 6, run frontend and backend in PARALLEL)

Send a single message with two tool calls running simultaneously:

  • Step 6a — Frontend Tests: cd frontend && npm run test -- --run
  • This generates lcov coverage (frontend/coverage/lcov.info) for SonarCloud
  • Step 6b — Backend Tests: cd backend && pytest --cov=app --cov-report=xml --tb=short -q
  • This generates backend/coverage.xml for SonarCloud

Both must pass before continuing. Do not proceed to the SonarCloud scan if either test suite fails.


Phase 3 — SonarCloud (Steps 7–10, wait built into Step 7)

Coverage reports from Step 6 are reused — do not re-run tests here.

Step 7 — Run Sonar Scan

The scanner streams live progress (Sensor steps, file indexing, upload status). After upload, poll the quality gate API to confirm results are processed.

echo "🔍 Starting SonarCloud scan — this takes 2–4 minutes..."
JAVA_HOME=/opt/homebrew/opt/java SONAR_TOKEN=${SONAR_TOKEN:-$SONARQUBE_TOKEN} sonar-scanner \
  -Dsonar.host.url=https://sonarcloud.io 2>&1 | \
  grep --line-buffered -E "INFO|WARN|ERROR|Sensor|Analysis|Upload|Quality Gate|ANALYSIS SUCCESSFUL"
echo "✅ Scan uploaded — polling SonarCloud for results..."

After the scan uploads, poll the quality gate status instead of sleeping. Use mcp__sonarqube__get_project_quality_gate_status with projectKey: "Twycis_DoubleDiamond" every 10 seconds (max 12 attempts / 2 minutes). The gate will initially return the previous result — wait until the analysisDate changes to confirm the new scan has been processed. Use run_in_background: true on any bash wait commands to avoid blocking the UI.

echo "✅ Ready — checking quality gate now"

BLOCKER — If the scan fails with 401/403 or "Project not found": The SONAR_TOKEN / SONARQUBE_TOKEN is missing, expired, or lacks permissions. Stop the PR-ready process immediately. Do NOT proceed to commit or push. Tell the user: - Generate a new Project Analysis Token at https://sonarcloud.io/account/security (type: Project Analysis Token, project: Twycis_DoubleDiamond) - Add/update SONARQUBE_TOKEN in ~/.bash_profile and run source ~/.bash_profile - Re-run /pr-ready after the token is fixed

Without a successful scan the quality gate cannot be verified and the PR MUST NOT be submitted.

Step 8 — Quality Gate

Call mcp__sonarqube__get_project_quality_gate_status with projectKey: "Twycis_DoubleDiamond".

If any condition has status: "ERROR", record which conditions failed and proceed to Step 8a.

Call mcp__sonarqube__search_sonar_issues_in_projects with issueStatuses: ["OPEN"].

Separate results into: - Frontend issues (files under frontend/) - Backend issues (files under backend/)

Step 10 — Duplication Check

Call mcp__sonarqube__search_duplicated_files (project: Twycis_DoubleDiamond).

If new duplication density > 3%, identify duplicated blocks and extract shared code before continuing.


Steps 8a/9a — SonarQube Auto-Fix (max 2 iterations)

Frontend (TypeScript) Issues

Group open frontend issues by file domain (same Groups A/B/C as Phase 1). Launch one subagent per group in parallel.

Common TypeScript rule fixes: | Rule | Fix | |---|---| | S1128 | Remove unused imports | | S7772 | Fix unnecessary type assertions | | S7773 | Remove redundant type casts | | S6582 | Simplify optional chaining | | S4325 | Remove redundant type parameters | | S7735 | Fix unnecessary non-null assertions | | S3358 | Simplify ternary expressions | | S1854 | Remove dead assignments | | S2486 | Handle or rethrow caught exceptions | | S7781 | Fix incorrect promise handling | | S4624 | Add missing return type annotations | | S7785 | Fix async/await misuse | | S6660 | Simplify boolean expressions | | S6606 | Use nullish coalescing where appropriate | | S125 | Remove commented-out code |

Each agent must: read the file first, apply targeted fixes, no bash commands.

Backend (Python) Issues

Group open backend issues by file domain. Launch one subagent per group in parallel.

Common Python fix patterns: - Empty except blocks — add specific exception type and log/re-raise - Unused imports — remove with isort conventions in mind - Magic numbers — extract to named constants - Naming conventions — follow PEP 8 (snake_case functions/variables, PascalCase classes) - Bare except: — replace with except Exception: - Missing return type hints — add annotations matching existing style

After all agents complete: 1. Re-run cd frontend && npm run lint && npm run check (frontend issues) 2. Re-run cd backend && python -m mypy app/ (backend issues) 3. Re-run the Sonar scan (Step 7 command — poll for results, no sleeping) 4. Re-check quality gate (Step 8) and issues (Step 9)

If issues remain after iteration 2, STOP and report them with file + line references.


Phase 3b — E2E Tests (Step 11)

Run after SonarQube. Requires the backend to be running (already verified in Step 0a).

Step 11 — Run E2E Tests

cd frontend && npx playwright test --reporter=html 2>&1

The tests run headless (Chromium). After the run:

  1. Check exit code: 0 = all passed, non-zero = failures.
  2. Read the JSON results from frontend/playwright-report/ or parse stdout for the summary line (e.g. 21 passed, 3 failed).
  3. For each failed test:
  4. Read the error message and trace from stdout output
  5. Identify the root cause: selector mismatch, missing data-testid, timing issue, backend state, or broken UI
  6. Apply a fix if the cause is clear and contained (e.g. update a selector, add a missing data-testid, adjust a wait)
  7. Re-run only the failing spec: npx playwright test <file> --reporter=line
  8. Max 2 fix iterations. If tests still fail after 2 iterations, STOP and report:
  9. Which tests failed
  10. The error message and last failing step
  11. Your diagnosis (what likely changed)
  12. What fix is needed (but couldn't be applied automatically)

NOTE: If the backend is not running, E2E tests will fail at login. The Step 0a check prevents this — if you reach Step 11 and the backend is still unreachable, STOP and report.

Add E2E results to the final summary table.


Phase 4 — Manual Checks (Steps 12–16, run in PARALLEL)

Send a single message with five tool calls running simultaneously:

Step 12 — Console Cleanup

Search all files changed in this branch (git diff --name-only main...HEAD) for: - console.log, console.debug, console.warn, console.error (frontend) - print( statements used for debugging (backend)

Remove any that are not intentional structured logging.

Step 13 — Auth Guards

  • Backend: For every new or modified FastAPI route file, verify each route handler includes both require_auth and require_permission as dependencies (or a documented exception).
  • Frontend: For every new API call in modified files, verify the calling code handles 401 responses (either via a global interceptor or explicit error handling).

Step 14 — No any Types

Search new and modified TypeScript files for explicit any annotations. Each occurrence must be replaced with a proper type or unknown + type narrowing.

Step 15 — Causal Order (CRITICAL)

Verify there are no fire-and-forget patterns: - FastAPI routes: No asyncio.create_task() or background tasks that must complete before the response is sent. - Frontend mutations: No floating Promises (unhandled .then() chains or missing await).

Step 16 — API Types Check

In new and modified frontend files, verify all API response shapes are imported from @/types/api (generated from openapi.json) — not from manually defined local interfaces.

Wait for all five checks to complete and record pass/fail.


Test Sync (REQUIRED)

Run /test-sync to automatically detect changed files and create or update corresponding tests.

Test Alignment Verification

[!IMPORTANT] After /test-sync completes, verify the results. Passing tests with stale assertions are worse than no tests.

Run git diff --name-only main...HEAD to confirm all changed source files have corresponding up-to-date tests:

Changed file Expected test file
backend/app/api/[x].py backend/tests/test_[x].py
backend/app/models/[x].py backend/tests/test_[x].py
frontend/src/hooks/use[X].ts frontend/src/tests/hooks/use[X].test.ts
frontend/src/components/[X].tsx frontend/src/tests/components/[X].test.tsx
  • Test file exists — if not, flag it
  • Test file was updated — if source changed but tests were not touched, verify assertions are still valid
  • New behavior is covered — new branches, fields, and validations must have a test case
  • Removed behavior is cleaned up — delete tests for functionality that no longer exists

Architecture Review

Run /architecture-review as a final check to ensure changes conform to project architecture patterns.


Phase 5 — Finalization (Pre-Push)

Temp Cleanup

Run /cleanup-temp to remove: - temp_*, lint*, *.log files - *.pyc files and __pycache__/ directories - Any other scratch files created during the session

Release Notes

Determine whether to run /release-notes:

git diff --name-only main...HEAD
  • Skip if every changed file is under tests/, coverage/, or backend/tests/ — pure test/coverage commits do not warrant a version bump.
  • Run /release-notes for everything else — this bumps version files and prepends a new entry to the release notes.

[!NOTE] Do NOT manually bump the version. /release-notes handles all version files consistently.

Branch Guard (REQUIRED, before committing)

Never commit directly to main. Determine the current branch:

git branch --show-current
  • If the current branch is main: create and switch to a new feature branch before committing, so the work can be merged into main via PR later. Namespace the branch per developer to avoid collisions:
    DEV=$(git config user.name | tr ' /' '-' | tr '[:upper:]' '[:lower:]')
    git switch -c "pr-ready/${DEV}/<short-slug>"
    
    Derive <short-slug> from the change (e.g. the primary feature or fix) — final form pr-ready/<developer>/<short-slug> (e.g. pr-ready/ronald/branch-guard). Inform the user which branch was created.
  • If the current branch is NOT main: reuse the existing branch — do not create a new one.

Commit & Push

Commit all changes and push the current (non-main) branch to remote. This triggers the SonarCloud CI analysis.


Phase 6 — Post-Push SonarQube Verification (CRITICAL)

[!IMPORTANT] The local sonar-scanner in Phase 3 catches most issues, but the remote SonarCloud CI scan is the definitive source of truth. CI may use different rules, configurations, or detect issues the local scanner missed. This phase verifies the push is clean.

Wait for Remote Scan

After pushing, poll the CI workflow status instead of sleeping. Run gh run list --branch $(git branch --show-current) --limit 1 --json status,conclusion every 15 seconds (max 20 attempts / 5 minutes) until the workflow completes. Use run_in_background: true on any bash polling commands to avoid blocking the UI. Alternatively, use gh run watch with run_in_background: true to stream status updates without blocking.

Quality Gate Re-Check

Call mcp__sonarqube__get_project_quality_gate_status with projectKey: "Twycis_DoubleDiamond". - If PASSED → continue to final report - If FAILED → proceed to repair loop

Issue Re-Check

Call mcp__sonarqube__search_sonar_issues_in_projects with issueStatuses: ["OPEN"]. - Check for any NEW issues (compare creation date with push time) - Also check mcp__sonarqube__search_duplicated_files for duplication

Repair Loop (Max 2 iterations)

If the quality gate FAILED or new issues were found:

  1. Identify all failing conditions and new issues
  2. Fix each issue in the codebase
  3. Run cd frontend && npm run check and cd backend && python -m mypy app/ to verify fixes
  4. Commit & push the fixes
  5. Poll CI workflow status (same approach as "Wait for Remote Scan" above — no sleeping)
  6. Re-check quality gate status
  7. If still failing after 2 repair iterations → STOP and report remaining issues to user

Final Summary Report

Present the results as a markdown table:

Check Status Notes
Branch Sync ✅/❌
Frontend Lint ✅/❌
Frontend Type Check ✅/❌
Backend Type Check (mypy) ✅/❌
OpenAPI Sync ✅/❌
Frontend Tests ✅/❌
Backend Tests (pytest) ✅/❌
SonarCloud Scan (local) ✅/❌
SonarQube Quality Gate (local) ✅/❌
SonarQube Issues ✅/❌ N fixed / N remain
SonarQube Duplication ✅/❌
E2E Tests ✅/❌ N passed / N failed
Console Cleanup ✅/❌
Auth Guards ✅/❌
No Any Types ✅/❌
Causal Order ✅/❌
API Types Check ✅/❌
Test Alignment ✅/❌
Architecture Review ✅/❌
Temp Cleanup ✅/❌
Release Notes ✅/❌
Post-Push Verification ✅/❌ Remote quality gate after push

Verdict: READY / NOT READY

If NOT READY, list every remaining blocker with file path and line number reference.

IMPORTANT: The Final Report is the LAST output of this skill. Do NOT call TodoWrite after presenting the report — the report itself is the deliverable and any trailing todo updates are redundant noise.

[!IMPORTANT] Run this before telling the user "I'm done" with any non-trivial task.

Trigger Conditions

  • Keywords: "I'm done", "Submit this", "Prepare for PR", "Finished", "Ready to commit"

Configuration — SonarCloud Toggle

SonarCloud integration is opt-in via the SONAR_ENABLED environment variable, mirroring the SONAR_ENABLED repo variable used by GitHub Actions. When unset or not true, all SonarCloud steps are skipped.

Check it once at the start of the run:

echo "SONAR_ENABLED=${SONAR_ENABLED:-false}"
  • If SONAR_ENABLED=true → run Phase 2 and Phase 5 normally.
  • If SONAR_ENABLED is anything else (unset, false, empty) → skip Phase 2 (Steps 5–8, 6a/7a) and Phase 5 entirely. Omit their TodoWrite entries. Mark their rows in the Final Report as ⊘ skipped (SONAR_ENABLED!=true).

Step 0 — Branch Sync Check (REQUIRED, DO FIRST)

Before anything else, verify the local branch is up to date with remote main:

  1. Run git fetch origin main
  2. Run git log HEAD..origin/main --oneline to check if remote main has commits not present locally
  3. If there are new commits on remote main:
  4. Inform the user that remote main has diverged (show the new commit list)
  5. Run git merge origin/main to merge the remote changes into the current local branch
  6. If the merge produces conflicts, STOP immediately. List the conflicting files and ask the user to resolve them before continuing.
  7. If the merge succeeds cleanly, inform the user and continue to Step 1.
  8. If there are no new commits, continue to Step 1.

Step 1 — Create TodoWrite Task List

Create a TodoWrite task list with all steps so progress is visible throughout the process:

TodoWrite:
- [ ] Branch Sync Check
- [ ] Phase 1: Lint
- [ ] Phase 1: Type Check
- [ ] Phase 1: Architecture Validation
- [ ] Step 1a: Lint auto-fix (if needed)
- [ ] Step 2a: TypeScript auto-fix (if needed)
- [ ] Step 4: Frontend Tests
- [ ] Step 4: Backend Smoke Tests
- [ ] Step 4: Latency Tests
- [ ] Step 4b: E2E Tests
- [ ] Step 5: SonarQube Scan
- [ ] Step 6: Quality Gate Check
- [ ] Step 7: SonarQube Issues Review
- [ ] Step 8: Duplication Check
- [ ] Steps 6a/7a: SonarQube Auto-Fix (if needed)
- [ ] Phase 3: Console Cleanup
- [ ] Phase 3: Auth Guards
- [ ] Phase 3: Localization
- [ ] Phase 3: No Any Types
- [ ] Phase 3: Causal Order Check
- [ ] Phase 3: No window.alert()
- [ ] Phase 3: Test Alignment
- [ ] Architecture Review
- [ ] Temp Cleanup
- [ ] Release Notes

Phase 1 — Static Analysis (Run Steps 1, 2, 3 in PARALLEL)

Launch all three checks simultaneously in a single message with multiple tool calls. Do NOT run them sequentially.

Step 1: Lint

npm run lint

Step 2: Type Check

npm run type-check && cd backend && npm run type-check

Step 3: Architecture Validation

node scripts/check-architecture.js

Wait for all three to complete before continuing. If any fail, handle them before moving to Phase 2.


Step 1a — Lint Auto-Fix (max 2 iterations)

If lint errors are found, group them by file domain and launch parallel agents. Each agent: read the file first, fix errors using only file edits — no bash commands.

File groupings:

Group Files
A backend/src/routes/**
B backend/src/services/**, backend/src/middleware/**
C hooks/**, context/**, services/**
D components/**, src/** (frontend)

After all agents complete, re-run lint:

npm run lint

Repeat up to 2 total iterations. If errors remain after 2 iterations, STOP and report all remaining errors with file and line references. Do not proceed until lint is clean.


Step 2a — TypeScript Auto-Fix (max 2 iterations)

If TypeScript errors are found, group by frontend vs backend and launch parallel agents. Each agent: read the file first, fix errors using only file edits — no bash commands.

File groupings:

Group Files
Frontend src/**, hooks/**, context/**, components/**
Backend backend/src/**

After all agents complete, re-run type check:

npm run type-check && cd backend && npm run type-check

Repeat up to 2 total iterations. If errors remain after 2 iterations, STOP and report all remaining errors with file and line references. Do not proceed until types are clean.


Step 4 — Tests

Run the following test suites. Coverage output generated here is reused by the SonarQube scan in Step 5 — do not skip.

Frontend Tests

npm run test

All tests must pass. No skipped or failing tests.

Backend Smoke Tests

cd backend && npm run test:smoke

All smoke tests must pass.

Latency Tests

cd backend && npm run test:latency

Flag any endpoint exceeding 500ms average — do not introduce latency regressions. Report flagged endpoints in the final summary.


Step 4b — E2E Tests

Requires the backend to be running on port 5001.

  1. Verify backend reachability: curl -s -o /dev/null -w "%{http_code}" http://localhost:5001/health
  2. If not reachable, attempt to start: cd backend && npm run dev & and poll for 15 seconds
  3. Run E2E tests: npx playwright test --reporter=line 2>&1
  4. If failures occur, diagnose and attempt auto-fix (max 1 iteration)
  5. All E2E tests must pass before continuing to SonarQube

Phase 2 — SonarQube

Skip this entire phase if SONAR_ENABLED is not true (see Configuration block at top). Jump straight to Phase 3.

Step 5: Run SonarQube Scan

The test coverage reports from Step 4 are already on disk. Run only the scanner — do not re-run tests.

The scanner streams live progress (Sensor steps, file indexing, upload status). After upload, poll the quality gate API to confirm results are processed.

echo "🔍 Starting SonarCloud scan — this takes 2–4 minutes..."
JAVA_HOME=/opt/homebrew/opt/java SONAR_TOKEN=${SONAR_TOKEN:-$SONARQUBE_TOKEN} sonar-scanner \
  -Dsonar.host.url=https://sonarcloud.io 2>&1 | \
  grep --line-buffered -E "INFO|WARN|ERROR|Sensor|Analysis|Upload|Quality Gate|ANALYSIS SUCCESSFUL"
echo "✅ Scan uploaded — polling SonarCloud for results..."

After the scan uploads, poll the quality gate status instead of sleeping. Use mcp__sonarqube__get_project_quality_gate_status with projectKey: "Twycis_SalesFocus" every 10 seconds (max 12 attempts / 2 minutes). The gate will initially return the previous result — wait until the analysisDate changes to confirm the new scan has been processed. Use run_in_background: true on any bash wait commands to avoid blocking the UI.

echo "✅ Ready — checking quality gate now"

BLOCKER — If the scan fails with 401/403 or "Project not found": The SONAR_TOKEN / SONARQUBE_TOKEN is missing, expired, or lacks permissions. Stop the PR-ready process immediately. Do NOT proceed to commit. Tell the user: - Generate a new Project Analysis Token at https://sonarcloud.io/account/security (type: Project Analysis Token, project: Twycis_SalesFocus) - Update SONARQUBE_TOKEN in ~/.bash_profile and run source ~/.bash_profile - Re-run /pr-ready after fixing the token

Without a working scan, the quality gate cannot be verified and the commit MUST NOT proceed.

Step 6: Quality Gate Check

Call mcp__sonarqube__get_project_quality_gate_status with projectKey: "Twycis_SalesFocus".

If any condition has status: "ERROR", do not proceed — fix issues first (see Steps 6a/7a below).

Step 7: Search Issues

Call mcp__sonarqube__search_sonar_issues_in_projects with issueStatuses: ["OPEN"] to enumerate all open issues introduced in the current branch.

Step 8: Duplication Check

Call mcp__sonarqube__search_duplicated_files to identify duplicated blocks.

  • If new_duplicated_lines_density > 3%: extract shared code into utilities or shared modules.

Steps 6a/7a — SonarQube Auto-Fix (max 2 iterations)

If the quality gate fails or open issues exist, group issues by file domain and launch parallel agents. Each agent: read the file first, fix issues using only file edits — no bash commands.

File groupings (same as lint):

Group Files
A backend/src/routes/**
B backend/src/services/**, backend/src/middleware/**
C hooks/**, context/**, services/**
D components/**, src/** (frontend)

Common fix patterns by SonarQube rule ID:

Rule Fix
S1128 Remove unused imports
S7772 Replace deprecated API usage with recommended alternative
S7773 Remove unreachable code after return/throw
S6582 Use optional chaining instead of && chains
S4325 Remove redundant type casts
S7735 Fix incorrect Promise handling (missing await or return)
S3358 Simplify nested ternaries into if/else or a lookup
S1854 Remove dead assignments (value assigned but never used)
S2486 Handle caught exceptions — don't swallow silently
S7781 Replace arguments with rest parameters
S4624 Replace template literal with string concatenation when no interpolation
S7785 Fix incorrect use of async without await
S6660 Use Array.from instead of spread for iterables
S6606 Use nullish coalescing (??) instead of || for null/undefined guards
S125 Remove commented-out code

After all agents complete, re-run the scan (no tests needed this time). The scanner streams live progress — poll the quality gate API after upload:

echo "🔍 Starting SonarCloud scan — this takes 2–4 minutes..."
JAVA_HOME=/opt/homebrew/opt/java SONAR_TOKEN=${SONAR_TOKEN:-$SONARQUBE_TOKEN} sonar-scanner \
  -Dsonar.host.url=https://sonarcloud.io 2>&1 | \
  grep --line-buffered -E "INFO|WARN|ERROR|Sensor|Analysis|Upload|Quality Gate|ANALYSIS SUCCESSFUL"
echo "✅ Scan uploaded — polling SonarCloud for results..."

After the scan uploads, poll the quality gate status (same approach as Step 5 — check analysisDate change, max 12 attempts). Use run_in_background: true on any bash wait commands to avoid blocking the UI.

echo "✅ Ready — checking quality gate now"

Then re-check the quality gate (Step 6) and issues (Step 7).

Repeat up to 2 total iterations. If issues remain after 2 iterations, STOP and report all remaining issues with rule ID, file, and line references.


Phase 3 — Manual Checks (Run Steps 9–14 in PARALLEL)

Launch all six checks simultaneously in a single message with multiple tool calls.

Step 9: Console Cleanup

Search all changed files for leftover debug output:

git diff --name-only main...HEAD

For each changed file, search for console.log, console.debug, console.warn, debugger. Remove any that are not intentional observability (i.e., not part of a logging utility).

Step 10: Auth Guards

For every new or modified route file in backend/src/routes/, verify that authentication middleware is applied. No route should be publicly accessible unless explicitly intended and documented.

Step 11: Localization

For all changed frontend files, check for hardcoded English strings in JSX or TypeScript that should be translated. All user-facing strings must use t('Category', 'Key') from useLanguage().

Step 12: No any Types

Search all new and modified TypeScript files for any type annotations. Every any must be replaced with a proper type, unknown, or a well-reasoned type assertion with an inline comment.

Step 13: Causal Order Check

Verify that no API route handlers or frontend mutations contain unawaited background tasks. Every async operation must be either awaited or explicitly fire-and-forget with a comment explaining the intent.

Step 14: No window.alert()

Search all changed frontend files for window.alert(), window.confirm(), and alert(). These must be replaced with Toast notifications or custom Modal components (per the Critical Rules in CLAUDE.md).


Test Sync (REQUIRED)

Run /test-sync to automatically detect changed files and create or update corresponding tests.

Test Alignment Verification

[!IMPORTANT] After /test-sync completes, verify the results. Passing tests with stale assertions are worse than no tests.

Run git diff --name-only main...HEAD to confirm all changed source files have corresponding up-to-date tests:

Changed file Expected test file
backend/src/routes/[x].ts backend/tests/integration/routes/[x].test.ts
backend/src/services/[x].ts backend/tests/unit/services/[x].test.ts
hooks/use[X].ts tests/unit/hooks/use[X].test.ts
services/domains/[x]Service.ts tests/unit/services/[x]Service.test.ts
  • [ ] Test file exists — if not, flag it
  • [ ] Test file was also updated — if source changed but tests were not touched, verify assertions are still valid
  • [ ] New behavior is covered — new branches, fields, and validations must have a corresponding test case
  • [ ] Removed behavior is cleaned up — delete tests for functionality that no longer exists

Architecture Review

Run /architecture-review as a final structural check.


Phase 4 — Finalization (Pre-Push)

Temp Cleanup

Run /cleanup-temp to remove all temporary files (temp_*, lint*, scratch files, etc.).

Release Notes

Determine whether to run /release-notes:

git diff --name-only main...HEAD
  • Skip if every changed file is under tests/, coverage/, or backend/coverage/ — pure test/coverage commits do not warrant a version bump
  • Run /release-notes for everything else — this bumps package.json, backend/package.json, and docs/general/MANUAL.md, and prepends a new entry to docs/general/RELEASE_NOTES.md

[!NOTE] Do NOT manually bump the version. /release-notes handles all version files consistently.

Branch Guard (REQUIRED, before committing)

Never commit directly to main. Determine the current branch:

git branch --show-current
  • If the current branch is main: create and switch to a new feature branch before committing, so the work can be merged into main via PR later. Namespace the branch per developer to avoid collisions:
    DEV=$(git config user.name | tr ' /' '-' | tr '[:upper:]' '[:lower:]')
    git switch -c "pr-ready/${DEV}/<short-slug>"
    
    Derive <short-slug> from the change (e.g. the primary feature or fix) — final form pr-ready/<developer>/<short-slug> (e.g. pr-ready/ronald/branch-guard). Inform the user which branch was created.
  • If the current branch is NOT main: reuse the existing branch — do not create a new one.

Commit & Push

Commit all changes and push the current (non-main) branch to remote. This triggers the SonarCloud CI analysis.


Phase 5 — Post-Push SonarQube Verification (CRITICAL)

Skip this entire phase if SONAR_ENABLED is not true (see Configuration block at top). The Final Report should mark Post-Push Verification as ⊘ skipped.

[!IMPORTANT] The local sonar-scanner in Phase 2 catches most issues, but the remote SonarCloud CI scan is the definitive source of truth. CI may use different rules, configurations, or detect issues the local scanner missed. This phase verifies the push is clean.

Wait for Remote Scan

After pushing, poll the CI workflow status instead of sleeping. Run gh run list --branch $(git branch --show-current) --limit 1 --json status,conclusion every 15 seconds (max 20 attempts / 5 minutes) until the workflow completes. Use run_in_background: true on any bash polling commands to avoid blocking the UI. Alternatively, use gh run watch with run_in_background: true to stream status updates without blocking.

Quality Gate Re-Check

Call mcp__sonarqube__get_project_quality_gate_status with projectKey: "Twycis_SalesFocus". - If PASSED → continue to final report - If FAILED → proceed to repair loop

Issue Re-Check

Call mcp__sonarqube__search_sonar_issues_in_projects with issueStatuses: ["OPEN"]. - Check for any NEW issues (compare creation date with push time) - Also check mcp__sonarqube__search_duplicated_files for duplication

Repair Loop (Max 2 iterations)

If the quality gate FAILED or new issues were found:

  1. Identify all failing conditions and new issues
  2. Fix each issue in the codebase
  3. Run npm run type-check && cd backend && npm run type-check to verify fixes compile
  4. Commit & push the fixes
  5. Poll CI workflow status (same approach as "Wait for Remote Scan" above — no sleeping)
  6. Re-check quality gate status
  7. If still failing after 2 repair iterations → STOP and report remaining issues to user

Final Report

Present results as a markdown table with a Notes column:

Check Status Notes
Branch Sync ✅/❌
Lint ✅/❌
Type Check ✅/❌
Architecture Validation ✅/❌
Frontend Tests ✅/❌
Backend Smoke Tests ✅/❌
Latency Tests ✅/❌
E2E Tests ✅/❌ N passed / N failed
SonarCloud Scan (local) ✅/❌
SonarQube Quality Gate (local) ✅/❌
SonarQube Issues ✅/❌ N fixed / N remain
SonarQube Duplication ✅/❌
Console Cleanup ✅/❌
Auth Guards ✅/❌
No Any Types ✅/❌
Causal Order ✅/❌
No window.alert() ✅/❌
Test Alignment ✅/❌
Architecture Review ✅/❌
Temp Cleanup ✅/❌
Release Notes ✅/❌
Post-Push Verification ✅/❌ Remote quality gate after push

Verdict: READY / NOT READY

If NOT READY, list every remaining blocker with file and line references.

IMPORTANT: The Final Report is the LAST output of this skill. Do NOT call TodoWrite after presenting the report — the report itself is the deliverable and any trailing todo updates are redundant noise.