$npx -y skills add andyzengmath/quantum-loop --skill ql-deslopPost-review AI-slop cleanup pass. After quality review approves a story/feature, scans only the changed files for: duplicate code, dead code, needless abstraction, boundary violations, missing tests. Proposes deletions with regression-test gate — rolls back on regression. Mandato
| 1 | # ql-deslop — post-review AI-slop cleanup |
| 2 | |
| 3 | ## Purpose |
| 4 | |
| 5 | Review approval does not mean the code is clean. LLM-authored code routinely introduces: |
| 6 | - **Duplication** of helpers / types / imports under slightly different names. |
| 7 | - **Dead code** — functions added but never called; exports that no consumer uses. |
| 8 | - **Needless abstraction** — factory for one caller; wrapper that only aliases; configurable field never varied. |
| 9 | - **Boundary violations** — private functions accessed via string names; cross-module reaches that skip the public API. |
| 10 | - **Missing tests** — paths and branches not exercised by any test. |
| 11 | |
| 12 | Per Schreiber & Tippe 2025, 12.1% of AI-generated files contain ≥1 CWE, and per Zhong et al. 2026 (278k conversations) AI suggestions increase cyclomatic complexity 10-50× more than human edits. Without an explicit cleanup step, every autonomous run accumulates slop. |
| 13 | |
| 14 | `ql-deslop` adds an explicit cleanup pass AFTER the story's review gate passes but BEFORE the merge to the feature branch. Borrowed directly from OMC Ralph Steps 7.5 (deslop) + 7.6 (regression re-verify). |
| 15 | |
| 16 | ## When to use |
| 17 | |
| 18 | - Automatically, as a mandatory step between `ql-review` PASS and the `git merge` in `ql-execute`. |
| 19 | - Manually, at any point after a story is implemented, to clean up before review. |
| 20 | - After absorbing a foreign branch (CPC promotion, cherry-pick) — the absorbed work may carry slop. |
| 21 | |
| 22 | ## Opt-out |
| 23 | |
| 24 | Single flag: `--no-deslop`. Used only when: |
| 25 | - The story is a pure test addition (nothing to clean). |
| 26 | - The deslop pass itself was run earlier in the same wave on the same files. |
| 27 | - The user explicitly demands skip (rare; recorded in commit trailer `Deslop: skipped | <reason>`). |
| 28 | |
| 29 | ## Scope — strict file-list only |
| 30 | |
| 31 | The deslop pass operates on `git diff --name-only BASE_SHA..HEAD_SHA` — the EXACT files the story touched. It never broadens scope silently. Reaching into unchanged files is an anti-pattern and is explicitly forbidden. |
| 32 | |
| 33 | ## Smell taxonomy — 5 categories |
| 34 | |
| 35 | ### 1. Duplication |
| 36 | |
| 37 | Detectors: |
| 38 | - Identifier similarity across changed files: extract top-level symbol names; flag near-duplicates (e.g., `parseRequest` / `parseReq` / `handleParse`) via Levenshtein or canonical-alpha-rename + exact match (per HyClone arXiv:2508.01357). |
| 39 | - Function-body AST hash: for each function in the diff, compute tree-sitter AST hash after alpha-renaming; flag duplicates across files. |
| 40 | - Import redundancy: same module imported as different names in sibling files. |
| 41 | |
| 42 | Action: extract common code into a shared lib; update callers; delete the duplicates. |
| 43 | |
| 44 | ### 2. Dead code |
| 45 | |
| 46 | Detectors: |
| 47 | - Language-specific reachability analysis: |
| 48 | - TypeScript/JavaScript: `knip` or `ts-prune` on the changed-files subset. |
| 49 | - Python: `vulture` on the changed-files subset. |
| 50 | - Go: `staticcheck -checks=U1000` on the changed-files subset. |
| 51 | - Rust: `cargo udeps` on the changed-files subset. |
| 52 | - DePA line-level perplexity (optional; per arXiv:2502.20246): high-z anomalies flagged for manual inspection. |
| 53 | |
| 54 | Action: delete the unused export / function / variable. Re-run tests. |
| 55 | |
| 56 | ### 3. Needless abstraction |
| 57 | |
| 58 | Detectors: |
| 59 | - Single-caller factories: factory returns type T, only one call site exists → inline the factory. |
| 60 | - Identity wrappers: function that only calls another function with same arguments → inline or delete. |
| 61 | - Never-varied config: options object with fields that are always set to the same literal → remove the option. |
| 62 | - One-member interface implemented by one class → inline unless specified as a contract. |
| 63 | |
| 64 | Action: propose refactoring with regression-test gate. |
| 65 | |
| 66 | ### 4. Boundary violations |
| 67 | |
| 68 | Detectors: |
| 69 | - Name mangling: access via `module["_privateFn"]`, reflection-style private access. |
| 70 | - Path traversal: imports that reach up too many levels (`../../../../other-module/internal`). |
| 71 | - Test imports from production: test files reaching into non-exported implementation details. |
| 72 | |
| 73 | Action: reshape through the public API, or promote the private API if genuinely needed externally. |
| 74 | |
| 75 | ### 5. Missing tests |
| 76 | |
| 77 | Detectors: |
| 78 | - AC ↔ test mapping: every AC in the PRD should have a specific test referenced by its ID (`AC-3 → tests/feature.test.ts::test_ac_3`). Missing maps surface as findings. |
| 79 | - Coverage gap on new public functions: any new exported function with <1 test invocation. |
| 80 | - Branch-coverage gap on control-flow-heavy changes. |
| 81 | |
| 82 | Action: write the missing test BEFORE deleting alleged dead code (deletion is safe only when the test suite exercises the surviving behavior). |
| 83 | |
| 84 | ## Single-pass discipline |
| 85 | |
| 86 | Each deslop invocation runs ONE pass from the taxonomy at a time: |
| 87 | |
| 88 | - **Pass 1 — dead |