Install
openclaw skills install @lqclf/loop-polish-skillsFully automated iterative polishing: start project → full-stack integration verification → browser automation → scoring → auto-fix → loop until perfect → generate report. Invoke when user asks for loop polish, full verification, automated acceptance, delivery check, integration check, quality polish.
openclaw skills install @lqclf/loop-polish-skillsStart project → Full verification → Scoring → Auto-fix → Loop until perfect → Generate report. Not perfect, don't ship.
Step 1 Start → Step 2 Verify → Step 3 Score → Step 4 Fix → Step 5 Regression → Step 6 Report
↑ │
└──────────── loop if not perfect ─────────────────────┘
Preflight mode: Step 1 → Step 2 → Step 3 → Output issues → Stop (no fix, no loop)
.loop-polish.json (optional, defaults used if missing){
"mode": "full",
"max_rounds": 10,
"target_score": 100,
"scope": "all",
"auto_fix": { "enabled": true, "strategy": "conservative", "max_per_round": 3 },
"browser": { "headless": true },
"report": { "format": "markdown", "output_dir": "./polish-reports/" },
"timeout_minutes": 120
}
| Config | Default | Description |
|---|---|---|
mode | full | full / preflight (scan and score only, no fix) |
max_rounds | 10 | Maximum number of iteration rounds |
target_score | 100 | Target score. Stop when reached |
scope | all | all / frontend / backend / api |
auto_fix.strategy | conservative | conservative (compile/logic errors only) / moderate (+ data consistency) / aggressive (+ UX/performance) |
auto_fix.max_per_round | 3 | Maximum fixes per round |
browser.headless | true | Headless browser mode |
report.format | markdown | markdown / html |
report.output_dir | ./polish-reports/ | Report output directory |
timeout_minutes | 120 | Total timeout in minutes |
0. Detect project structure:
- Backend: search pom.xml/build.gradle/package.json/go.mod/requirements.txt
- Frontend: search package.json + vite.config/vue.config/next.config
- Pure frontend/backend: skip what doesn't exist, only start what's present
1. Git safety (full mode only):
- Check workspace: git status --porcelain, stash uncommitted changes if any
- Create fix branch: git checkout -b loop-polish/round-{timestamp}
- Record original branch name for step 6 checkout
2. Clean up old processes (cross-platform):
- Check ports: backend 8080/3000/5000, frontend 5173/3000
- Windows: netstat -ano | findstr :port → taskkill /PID {pid} /F
- Linux/Mac: lsof -ti :port | xargs kill -9 2>/dev/null
3. Start backend (if project has backend, by type):
Java: mvn clean package -DskipTests -q ; java -jar target/*.jar
Node: npm install ; node server.js
Python: pip install -r requirements.txt ; python app.py
Go: go build ; ./app
After startup, poll /health or /actuator/health or GET root path, up to 60s
If none reachable, poll process port (netstat/lsof to confirm port is listening)
4. Start frontend (if project has frontend):
npm install (if no node_modules) ; npm run dev
Poll dev server up to 60s
5. Failure handling:
→ Capture error logs, attempt repair (missing deps/port conflicts), retry 2x → abort if still failing
Scope control (by scope config):
scope=all: run 2.1 + 2.2 + 2.3
scope=backend: run 2.1 + 2.3
scope=frontend: run 2.2
scope=api: run 2.1
Pure frontend (no backend code): auto skip 2.1 and 2.3
Pure backend (no frontend code): auto skip 2.2
1. Scan API endpoints:
Java: Grep @RestController to locate Controller files → Grep @(Get|Post|Put|Delete)Mapping within them
Node: Grep router\.(get|post|put|delete)|app\.(get|post|put|delete)
Python: Grep @(app|router)\.(route|get|post|put|delete)
Extract: HTTP method, path, parameter names and types
2. Parse request body params (POST/PUT):
@RequestBody or body param points to DTO class → Read the DTO source → extract field names and types
No DTO → extract from @RequestParam / @PathVariable in method signature
3. Path parameter handling (GET /users/{id} etc.):
Call the module's POST to create a record → get the returned id → use for GET/PUT/DELETE path params
If POST unavailable, try GET list endpoint → take first item's id
If POST request body depends on other resources (e.g. creating order needs user ID), try creating dependency first, skip endpoint on failure
4. Auth handling:
Scan endpoints with login/auth/signin keywords → auto call to get Token
Subsequent requests auto carry Authorization: Bearer {token}
Skip auth if no login endpoint found
5. Verify each endpoint (max 2 retries per endpoint):
Normal: valid params, verify 200/201 + response is valid JSON + key fields not empty
Boundary: empty string, 0, negative, very long string
Missing required: remove required field, verify 400
Permission: no Token → 401, regular user Token on admin endpoint → 403
6. On failure, collect diagnostics:
- Last 50 lines of backend log (tail -50 or Get-Content -Tail 50)
- Full response body + request params + request headers
1. Scan frontend routes:
Vue: Grep "path:" to locate route file → extract all path values
React: Grep "path:" or path: to locate route definitions → extract all paths
Generate route list
2. Scan forms (from source, avoid blind operation):
Grep "<el-form|<a-form|<t-form|<v-form|<form|<Form" to locate form components in each page
Record which page each form is on, as interaction targets for browser verification
3. Invoke Skill: playwright-master, verify page by page per route list:
- Page load: no white screen, no console.error
- Form interaction (only forms scanned in step 2): fill → validate → submit
- List operations (if present): pagination, search, delete
- Modal/drawer (if present): open → operate → close
- Navigation: menu click, tab switch
- Skip form verification if page has no forms
4. On failure: screenshot + collect console.error + failed network request logs
For every write operation (POST/PUT/DELETE):
1. Get database connection info (search by priority):
- application.yml / application.properties: spring.datasource.url
- .env: DATABASE_URL, DB_HOST+DB_PORT+DB_NAME+DB_USER+DB_PASSWORD
- config.json / config.js: search db, database, mysql, postgres keywords
If none found, skip database verification and output notice
2. Detect database type (from connection string or driver):
MySQL: jdbc:mysql:// or mysql://
PostgreSQL: jdbc:postgresql:// or postgresql://
SQLite: jdbc:sqlite: or sqlite:
Choose corresponding CLI: mysql -e / psql -c / sqlite3
3. Verify data:
POST create → direct query, confirm record written with correct field values
PUT update → direct query, confirm fields updated
DELETE → direct query, confirm record deleted or soft-delete flag set correctly
Statistics rules:
- Total feature points = number of API endpoints + number of frontend pages
- Each API endpoint covers 2 dimensions: functional completeness (can it be called normally), error handling (are boundaries/permissions correctly rejected)
- Each frontend page covers 2 dimensions: UX (can it be operated normally), data correctness (displayed data matches backend)
- Performance: API response > 2s or page load > 3s deducts points
Scoring formula:
dimension_score = 100 × (passed_in_dimension / total_in_dimension)
final_score = completeness×0.40 + correctness×0.25 + UX×0.15 + error_handling×0.10 + performance×0.10
Deduction: single point failure deducts 100/total points, retry still fails deducts extra 5 points (max 15)
Output format:
📊 Round 1: 76.8/100 [Not passed]
Completeness:80% Correctness:72% UX:80% Error:60% Performance:90% | Passed:85/120 Failed:35
If auto_fix.enabled=false or mode=preflight: skip this step, go directly to step 6 to generate report
1. Fix priority (P1→P3):
P1 Compile/syntax errors: missing import, type mismatch, null pointer
P2 Logic/data errors: wrong query logic, wrong condition, frontend-backend mismatch
P3 UX/performance: missing loading state, unfriendly messages (aggressive strategy only)
2. Strategy scope:
conservative: P1~P2 | single file | ≤ 3 per round
moderate: P1~P2 | ≤ 2 files | ≤ 5 per round
aggressive: P1~P3 | cross-module | ≤ 10 per round
3. Fix flow:
a. Read failed case diagnostic logs + screenshots → locate root cause → read source
b. Generate fix plan (prefer minimal change)
c. AskUserQuestion before high-risk changes (Schema change, auth logic, delete >10 lines)
d. Save original code snippet before fix (for precise rollback on failure)
e. Apply fix with Edit tool → record diff
f. Local regression (only test this function point, not full run)
g. Pass → mark fixed; Fail → restore original with Edit, mark "unfixable"
4. Exit strategy:
- Same problem fails 2x → skip
- 3 consecutive rounds with no score improvement → output "auto-fix limit reached", stop loop
- Already conservative and 3 consecutive rounds with no improvement → stop immediately
Output format:
🔧 Round 1 fix (conservative):
✅ [P1] UserController.java:45 - missing @Valid
✅ [P1] order.ts:23 - path typo
⚠️ Skipped 2 need human confirmation | Fixed:2 Remaining:31
1. Retest only failed cases from previous round
2. git diff --name-only to detect changed files → only retest affected modules
3. Skip passed and unchanged modules
4. Run steps 2~3 → compare current round vs previous round score
Output format:
🔄 Round 2 regression: Retested 35 → Passed 31 Failed 4 | Score: 92.50 (+15.70 ↑)
Termination conditions (any one met):
1. score >= target_score → ✅ Passed
2. rounds >= max_rounds → ⏰ Max rounds reached
3. 3 consecutive rounds score change < 1 → 📉 Score stagnated
4. total time > timeout → ⏱️ Timeout
5. User interrupt
Report generation (output to report.output_dir):
# Loop Polish Report
## Summary
Final Score | Rounds | Total Time | Passed | Fixed | Remaining
## Score Trend
| Round | Comp | Corr | UX | Err | Perf | Score | Change |
## Fix Details
Per-round fix list + diff + outcome
## Remaining Issues + Recommendations
Unfixed items + reasons + suggestions (add unit tests, add validation, add logging, etc.)
Cleanup:
- Stop frontend and backend services (kill launched processes)
- git checkout original branch
- git stash pop (if stashed in step 1)
- Output report path
Auto-save .loop-polish-state.json on interrupt:
{
"round": 2, "step": "verify",
"passed": ["api:GET:/users", "ui:login"], "failed": ["api:PUT:/orders"],
"fixed": ["UserController.java:45"], "unfixable": [],
"scores": [{"round":1,"score":76.8,"fixes":2}]
}
On resume: read state file → skip completed steps → continue from breakpoint. Delete this file to reset.
Run loop polish # Full polish
Loop polish preflight: API only # Quick scan
Loop polish: 5 rounds, 95 score, aggressive, HTML report # Custom
Run loop polish on user module and order module, target 100 # Specific modules
npx playwright install chromium (auto-install on first run if missing)strategy=conservative for first use, increase when comfortablepolish-reports/ directory