swe-workflow-skills 0.5.2 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/swe-workflow-skills)](https://www.npmjs.com/package/swe-workflow-skills)
4
4
  [![roles-check](https://github.com/SWEStash/swe-workflow-skills/actions/workflows/roles-check.yml/badge.svg)](https://github.com/SWEStash/swe-workflow-skills/actions/workflows/roles-check.yml)
5
- ![skills](https://img.shields.io/badge/skills-65-blue)
5
+ ![skills](https://img.shields.io/badge/skills-66-blue)
6
6
  [![license: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)
7
7
 
8
- A curated library of **65 Claude Code Agent Skills** that walk Claude through the
8
+ A curated library of **66 Claude Code Agent Skills** that walk Claude through the
9
9
  software lifecycle the way a disciplined senior engineer would — planning, design,
10
10
  TDD, review, security, deployment, incidents, and the project-management work around
11
11
  them.
@@ -73,7 +73,7 @@ web, claude.ai chat, and Cowork):
73
73
  **two-step** setup:
74
74
 
75
75
  ```bash
76
- # 1. Install all 65 skills + router + /role + the hook script, and apply the baseline
76
+ # 1. Install all 66 skills + router + /role + the hook script, and apply the baseline
77
77
  npx swe-workflow-skills install --global
78
78
  ```
79
79
 
@@ -148,7 +148,7 @@ review) live in the `skill-router` skill and **[ROLES.md](docs/ROLES.md)**.
148
148
 
149
149
  ## What's included
150
150
 
151
- 65 skills — **[full catalog → SKILLS.md](docs/SKILLS.md)**:
151
+ 66 skills — **[full catalog → SKILLS.md](docs/SKILLS.md)**:
152
152
 
153
153
  | Area | Count | Examples |
154
154
  |------|-------|----------|
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.2
1
+ 0.6.1
package/catalog.json CHANGED
@@ -61,6 +61,11 @@
61
61
  "description": "Structured code reviews enforcing DRY, KISS, YAGNI, SRP, best practices, and project conventions. Triggers: review this code, code review, check my code, what do you think of this implementation, review this PR, is this code good, feedback on my code, review staged changes before commit.",
62
62
  "path": "code-reviewing/SKILL.md"
63
63
  },
64
+ {
65
+ "name": "code-slop-cleanup",
66
+ "description": "Strip AI slop from a branch diff before PR — judge each hunk against the surrounding file's conventions, remove without changing behavior, re-run tests. Removal only: hunting bugs → code-reviewing; structural improvement → refactoring; repo-wide audit → technical-debt-review; pruning tests → test-suite-design. Triggers: deslop, AI slop, slop cleanup, tighten this diff, remove AI artifacts, clean the diff before PR, debug leftovers, stray PLAN.md, obvious comments, unnecessary try/catch, backwards-compat shim nobody asked for, diff hygiene.",
67
+ "path": "code-slop-cleanup/SKILL.md"
68
+ },
64
69
  {
65
70
  "name": "compliance-privacy",
66
71
  "description": "Engineer for regulatory and privacy obligations — GDPR/CCPA privacy-by-design, PII data mapping and minimization, retention and deletion (right to erasure), data subject requests, consent, SOC 2 controls (access, change management, audit logging). Triggers: GDPR, CCPA, SOC 2, HIPAA, compliance, privacy review, PII, personal data, data retention, right to be forgotten, DSR, audit requirements, are we compliant. Vulnerabilities in code → security-audit; attack analysis of a design → threat-modeling.",
@@ -98,7 +103,7 @@
98
103
  },
99
104
  {
100
105
  "name": "dependency-management",
101
- "description": "Evaluate, audit, and upgrade project dependencies — assess libraries before adoption, audit CVEs, plan major upgrades, resolve conflicts. Triggers: should I use this library, npm audit, upgrade dependencies, dependency vulnerability, outdated packages, evaluate this package, is this library maintained, dependency conflict, lock file, breaking changes in upgrade.",
106
+ "description": "Evaluate, audit, and upgrade project dependencies — assess libraries before adoption, audit CVEs, plan major upgrades, resolve conflicts. Triggers: should I use this library, npm audit, upgrade dependencies, dependency vulnerability, outdated packages, evaluate this package, is this library maintained, dependency conflict, lock file, breaking changes in upgrade, slopsquatting, package hallucination, does this package exist, verify package name, AI suggested this library.",
102
107
  "path": "dependency-management/SKILL.md"
103
108
  },
104
109
  {
@@ -288,7 +293,7 @@
288
293
  },
289
294
  {
290
295
  "name": "tdd-workflow",
291
- "description": "Guide test-driven development with red-green-refactor. Triggers: use tdd, test first, write the tests, red green refactor, test-driven, what should I test, write tests before code, failing test, implement using TDD. For NEW code via test-first — use test-suite-design for adding tests to existing code.",
296
+ "description": "Guide test-driven development with red-green-refactor. For NEW code via test-first — use test-suite-design for adding tests to existing code. Triggers: use tdd, test first, write the tests, red green refactor, test-driven, what should I test, write tests before code, failing test, implement using TDD.",
292
297
  "path": "tdd-workflow/SKILL.md"
293
298
  },
294
299
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swe-workflow-skills",
3
- "version": "0.5.2",
3
+ "version": "0.6.1",
4
4
  "description": "A curated library of Claude Code Agent Skills covering the full software lifecycle, with orchestrator-routed activation that scales past the skill-listing budget.",
5
5
  "type": "module",
6
6
  "bin": {
package/roles.json CHANGED
@@ -51,6 +51,7 @@
51
51
  "configuration-strategy",
52
52
  "security-audit",
53
53
  "refactoring",
54
+ "code-slop-cleanup",
54
55
  "deployment-checklist"
55
56
  ]
56
57
  },
@@ -67,7 +68,8 @@
67
68
  "test-suite-design",
68
69
  "browser-verification",
69
70
  "performance-optimization",
70
- "refactoring"
71
+ "refactoring",
72
+ "code-slop-cleanup"
71
73
  ]
72
74
  },
73
75
  "devops": {
@@ -228,6 +230,7 @@
228
230
  "test-data-strategy",
229
231
  "browser-verification",
230
232
  "code-reviewing",
233
+ "code-slop-cleanup",
231
234
  "bug-investigating"
232
235
  ]
233
236
  },
@@ -37,6 +37,21 @@ Look at the forest before the trees. Check:
37
37
  - **Is the approach sound?** Before nitpicking syntax, is the overall strategy correct?
38
38
  - **Are there missing pieces?** Tests? Documentation? Error handling? Migration?
39
39
 
40
+ **Step outside the diff.** The most common AI slop is invisible in a single hunk —
41
+ it only shows up repo-wide. For any new helper, block, command, or exported symbol in
42
+ the diff, run three greps before accepting it:
43
+ - **A twin?** Grep the repo for an existing function/block that already does this — AI
44
+ assistants generate a fourth copy instead of finding copies #1–3 (see `code-slop-cleanup`'s
45
+ *Reuse Before Write*).
46
+ - **Any importer?** A newly-`export`ed symbol with no consumer is dead surface (often
47
+ exported just to silence the unused-symbol checker).
48
+ - **Any consumer?** A new schema field, prop, or param that nothing reads or sets is
49
+ speculative plumbing — the API looks finished but is wired to nothing.
50
+
51
+ Also check the *unit being grown*, not just the hunk: adding 15 lines to an already
52
+ 800-line function or 200-line file is how god-functions form one reviewer-approved PR at
53
+ a time. Judge the total size after the change, not the size of the diff.
54
+
40
55
  ### Step 3: Detailed Review
41
56
 
42
57
  Review the code against these categories, in order of importance. See [references/review-checklist.md](references/review-checklist.md) for the detailed checklist.
@@ -97,5 +112,6 @@ These are the lenses through which code is examined:
97
112
  ## Cross-Skill References
98
113
 
99
114
  - `refactoring` — when the review surfaces code smells worth a structured cleanup
115
+ - `code-slop-cleanup` — strip AI-slop patterns from the diff before (or instead of) debating them in review
100
116
  - `security-audit` — for a dedicated, deep security pass beyond the review checklist
101
117
  - `verification-before-completion` — verify the change actually runs before approving, not from the diff alone
@@ -23,6 +23,7 @@
23
23
  "assertions": [
24
24
  "Runs git diff or git show to read the changes",
25
25
  "Reads surrounding code for context",
26
+ "For any new helper, export, or block, greps the repo beyond the diff for an existing twin, for importers, and for consumers (duplication / dead export / unconsumed surface are invisible in a single hunk)",
26
27
  "Follows the structured review format (summary, blockers, suggestions, nits)",
27
28
  "Provides specific file:line references for findings"
28
29
  ]
@@ -57,6 +58,20 @@
57
58
  "Keeps/endorses the round-trip test as legitimate own-logic coverage",
58
59
  "Suggests testing our actual logic instead (e.g. the legacy fallback branches)"
59
60
  ]
61
+ },
62
+ {
63
+ "id": 2,
64
+ "prompt": "Review this Python helper — it's the fact-check gate the pipeline runs before publishing:\n\ndef check_claims(response, model):\n try:\n report = parse_report(call_model(model, response))\n except (ValueError, JSONDecodeError) as e:\n log.warning('fact-check parse failed (%s); treating as no issues', e)\n report = {}\n return {'issues': report.get('issues', []), 'passed': not report.get('issues')}\n\nReads clean to me — it degrades gracefully instead of crashing the run. Ship it?",
65
+ "pressure": ["looks_good"],
66
+ "expected_behavior": "Flags the except branch as a fail-open correctness bug, not graceful degradation: on a parse failure the function returns passed=True / no issues, so an unparseable model reply is silently converted into 'everything checks out' and the article publishes unchecked. Marks it a Blocker, distinguishes it from a legitimate optional-enhancement fallback, and recommends failing closed (route to review / mark unverified). Does not accept 'degrades gracefully' as justification.",
67
+ "assertions": [
68
+ "Identifies the empty-report fallback as fail-open: a failure that returns a success-shaped result (passed=True / no issues)",
69
+ "Explains the consequence — an unparseable response publishes as 'no issues found', the inverse of what a check should do",
70
+ "Marks it a Blocker (correctness/data-integrity), not a nit",
71
+ "Distinguishes this from a legitimate documented degradation fallback",
72
+ "Recommends failing closed — mark unverified / route to review rather than defaulting to pass",
73
+ "Does NOT accept the 'degrades gracefully instead of crashing' framing as sufficient"
74
+ ]
60
75
  }
61
76
  ]
62
77
  }
@@ -95,6 +95,13 @@ Flag when you see:
95
95
  - [ ] No tests that merely re-verify third-party library behavior (e.g. asserting a compression lib's magic bytes or compression ratio, or that an ORM persists a row) — tests target our own logic and our boundary with the library, not what the vendor's own tests already cover
96
96
  - [ ] Mocks/stubs are used appropriately (not over-mocked)
97
97
  - [ ] Integration tests exist for cross-boundary interactions
98
+ - [ ] No assertions weakened or removed relative to the base branch
99
+ - [ ] No tests deleted or skipped without stated justification
100
+ - [ ] No expected values special-cased to match current (possibly buggy) output
101
+ - [ ] The unit under test is not itself mocked out
102
+ - [ ] Assertions target behavior, not cosmetics — not pinned to CSS class strings, emoji, exact copy, or rendered-prompt prose that a harmless reword would break (assert a stable data attribute or structure instead)
103
+ - [ ] No hedged or non-falsifiable assertions (`is None or == []`, `x in ("a","b")` covering both branches, a name that claims more than the assertion checks) — each test can actually fail
104
+ - [ ] The error/failure branch that's visible in the changed code has a test — happy-path fixtures that always feed valid input never exercise the branch just written
98
105
 
99
106
  ## Common Patterns to Flag
100
107
 
@@ -116,6 +123,24 @@ Flag when you see:
116
123
 
117
124
  **Inappropriate intimacy**: Two classes that access each other's private details excessively. Restructure to restore proper boundaries.
118
125
 
126
+ ## AI-Generated Code Tells
127
+
128
+ Patterns characteristic of AI-assisted diffs. Each is judged *relative to the surrounding code* — the same construct can be correct at one location and slop at another:
129
+
130
+ - **Defensive checks abnormal for the codepath**: try/catch, null guards, or re-validation deep in trusted paths whose inputs were already validated upstream. (Legitimate at process boundaries, external calls, and user input.)
131
+ - **Fail-open on error**: a check or validator that, when it fails or can't run, emits a value that *reads as success* — a parse failure returning `{}` → "no issues", an error collapsed to `"exit code 1"` that drops the real message. The inversion of a safety check; usually a bug, not clutter (flag as a Blocker, don't wave it through).
132
+ - **Style inconsistent with the surrounding file**: naming, formatting, or idiom that doesn't match what the file already does.
133
+ - **A new helper duplicating an existing one**: grep for an existing implementation before accepting any new utility — AI assistants generate rather than search. Watch for the recurring shapes: an N-arg setup ritual pasted at every entry point, parallel functions differing only by a noun/constant, byte-identical mappers across sibling modules.
134
+ - **Dead surface exported to silence the checker**: a newly-`export`ed symbol with no importer anywhere (the `_`-prefix + `export` tell), or a fully-built, tested module wired into nothing. Grep for consumers before accepting the export.
135
+ - **Declared-but-unconsumed / speculative plumbing**: a schema field validated but never rendered, a prop threaded through layers but never set, a param carried "for symmetry", a value computed but never surfaced. Ask *who reads this / who sets this?* — if the answer is "nobody", it shouldn't land.
136
+ - **Appending to an already-large unit**: a small hunk that grows an already-800-line function or file — how god-functions accrete one approved PR at a time. Judge the unit's total size after the change, not the hunk's.
137
+ - **Type-checker silencing**: `any`/casts to make an error go away, a param widened to `object`/`unknown` so a `type: ignore` can reach a field, or a stale `type: ignore` that no longer matches any error.
138
+ - **Library-layer function doing I/O or exit**: a domain/pure/pipeline-layer function that prints, logs to the console, or raises `SystemExit` — a presentation/process concern leaking into logic, which forces lossy error handling at every caller.
139
+ - **Unrequested backwards-compat shims**: `_legacy` wrappers, kept old code paths, re-exports nobody asked for — hedging instead of committing to the change.
140
+ - **Stray working files in the diff**: PLAN.md, NOTES.md, scratch scripts, checked-in generated/derived artifacts, or other session artifacts that shouldn't ship.
141
+
142
+ For the full taxonomy with severity levels and when-it's-NOT-slop guidance, see `code-slop-cleanup/references/slop-patterns.md` (if installed).
143
+
119
144
  ## Comments: Good vs Bad
120
145
 
121
146
  **Good comments** (keep them):
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: code-slop-cleanup
3
+ description: "Strip AI slop from a branch diff before PR — judge each hunk against the surrounding file's conventions, remove without changing behavior, re-run tests. Removal only: hunting bugs → code-reviewing; structural improvement → refactoring; repo-wide audit → technical-debt-review; pruning tests → test-suite-design."
4
+ when_to_use: "Triggers: deslop, AI slop, slop cleanup, tighten this diff, remove AI artifacts, clean the diff before PR, debug leftovers, stray PLAN.md, obvious comments, unnecessary try/catch, backwards-compat shim nobody asked for, diff hygiene."
5
+ allowed-tools: Read, Grep, Glob, Write, Edit, Bash
6
+ ---
7
+
8
+ # Code Slop Cleanup
9
+
10
+ Strip the residue AI-assisted coding leaves in a branch — obvious comments, defensive theater, debug leftovers, stray files, hedging shims — so the diff that reaches review contains only the change itself. Runs after implementation, before `git-workflow`/`code-reviewing`. This pass **removes**; it never redesigns.
11
+
12
+ ## ⛔ The Iron Law
13
+
14
+ **Remove only what you can prove is slop — never change behavior. If a removal could change behavior, keep the code and flag it instead.**
15
+
16
+ Slop cleanup that deletes a load-bearing check trades clutter for a bug — a strictly worse codebase. When in doubt, the code stays and the doubt goes in the report.
17
+
18
+ ## Workflow
19
+
20
+ ### Step 1: Scope the Diff
21
+
22
+ Branch state vs the default branch (live at skill load):
23
+
24
+ !`git diff main...HEAD --stat 2>/dev/null || git diff master...HEAD --stat 2>/dev/null || true`
25
+
26
+ Run the full `git diff <base>...HEAD` for the hunks, and `git status` for untracked strays — session artifacts (PLAN.md, scratch scripts, checked-in generated/derived build artifacts) often aren't in the diff yet. Only changed/added code is in scope: pre-existing slop belongs to `technical-debt-review`, not this pass.
27
+
28
+ ### Step 2: Judge Each Hunk Against Its Surroundings
29
+
30
+ Slop is relative — the same construct is correct in one place and slop in another. For each candidate, read the surrounding file and ask: is this **abnormal for this file's conventions and this codepath's trust level?** A try/catch at a process boundary is protection; the same try/catch deep in a validated internal path is theater. See [references/slop-patterns.md](references/slop-patterns.md) for the full catalog with per-pattern "when it's NOT slop" columns.
31
+
32
+ ### Step 3: Classify by Severity
33
+
34
+ - **High**: debug leftovers, silent-failure handlers, stray working files
35
+ - **Medium**: defensive theater on trusted paths, generic TODOs, unrequested backwards-compat shims, duplication of existing helpers
36
+ - **Low**: comment slop, dead weight (unused imports, `=== true`, redundant returns), style inconsistent with the file
37
+
38
+ ### Step 4: Strip — Deletions Only, Production Code Only
39
+
40
+ Apply removals highest severity first. Every edit must be a behavior-preserving deletion (or a trivial inlining a deletion forces). If removing something requires *rewriting* logic around it, that's refactoring — leave it and flag it.
41
+
42
+ **The two test rules:**
43
+ 1. A test failing after a production-code removal is the oracle saying the removal changed behavior. **Revert the removal. Never edit the test.**
44
+ 2. Slop *inside test files* (redundant tests, trivial asserts, mock-testing) is flagged and routed to `test-suite-design` — never deleted here. A test's value can't be judged from the diff alone.
45
+
46
+ ### Step 5: Re-Run the Tests
47
+
48
+ Run the project's test suite fresh and read the output (`verification-before-completion`). Green is the proof the removals were behavior-preserving; a failure means Step 4's rule 1 applies to the offending removal.
49
+
50
+ ### Step 6: Report the Tightened Diff
51
+
52
+ Show what was removed, grouped by category with counts, plus a **flagged-not-removed** list: anything kept under the Iron Law's doubt clause, test-file slop routed to `test-suite-design`, suspected bugs routed to `code-reviewing`/`bug-investigating`.
53
+
54
+ ## Prevention: Reuse Before Write
55
+
56
+ The biggest slop category — duplication — is created at generation time and only caught (expensively) at review time, because a single diff hunk hides the copies that already exist elsewhere. This is the canonical counter, and `code-reviewing` points reviewers back here:
57
+
58
+ - **Before writing any new helper, grep the codebase for an existing one** — name fragments, the operation's key terms, the module where it would live. AI assistants generate what looks plausible instead of searching for what exists; searching first is the cheap counter.
59
+ - **Before writing the third near-copy of a block, extract the seam instead.** The recurring shapes — an N-arg setup/wiring ritual pasted at every entry point, parallel functions differing only by a noun or constant, byte-identical mappers across sibling modules — are cheap to write locally and expensive to maintain. The moment you're about to paste-and-tweak, that's the signal to factor.
60
+
61
+ ## Boundaries — What This Skill Never Does
62
+
63
+ - **Never adds code** — no new abstractions, no "while I'm here" improvements.
64
+ - **Found a bug?** Flag it and route to `code-reviewing`/`bug-investigating`. Fixing bugs mid-cleanup makes both the cleanup and the fix unreviewable.
65
+ - **Structural cleanup** → `refactoring`. Most slop cleanup is a micro-refactor, and the two chain naturally: strip slop first, then refactor what remains — but extraction, moving, and re-abstraction are the refactoring skill's discipline (test-protected, one transformation at a time).
66
+ - **Whole-repo slop** → `technical-debt-review` with its slop debt categories.
67
+
68
+ ## Rationalizations to Reject
69
+
70
+ | Excuse | Reality |
71
+ |--------|---------|
72
+ | "This check might catch something someday" | If nothing upstream can produce that state, it's theater — and it hides the real bugs by normalizing noise. |
73
+ | "The comments help junior developers" | Restating comments rot and mislead; code clarity helps juniors. Keep why-comments, cut what-comments. |
74
+ | "I'll just fix this bug while I'm here" | Cleanup and fixes in one pass make both unreviewable. Flag it, route it, finish the cleanup. |
75
+ | "Strip it all — defensive code is slop" | A boundary check is not slop. Over-removal breaks behavior, the one thing this pass must never do. |
76
+ | "This test is obviously redundant, I'll just delete it" | "Obviously" is a guess; proof requires the behavior map. Route to `test-suite-design`. |
77
+
78
+ ## Red Flags — Stop and Revert
79
+
80
+ - You modified a conditional's logic instead of deleting something.
81
+ - A test failed and you're editing the test.
82
+ - You deleted a test.
83
+ - You removed validation at a public, API, or user-input boundary.
84
+ - You added anything.
85
+
86
+ ## Cross-Skill References
87
+
88
+ - `refactoring` — structural improvement after the slop is gone; this skill deletes, that one reshapes
89
+ - `code-reviewing` — the review this pass prepares the diff for; bugs found here route there
90
+ - `test-suite-design` — pruning test-file slop with behavior-map proof
91
+ - `technical-debt-review` — repo-scoped slop audit (type/config/doc-drift debt)
92
+ - `git-workflow` — the pre-PR self-review this pass feeds into
93
+ - `verification-before-completion` — the fresh-test-run gate behind Step 5
@@ -0,0 +1,57 @@
1
+ {
2
+ "skill_name": "code-slop-cleanup",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Clean the AI slop out of this branch diff before I open the PR. The diff adds a discount calculator to our Node service:\n\n```diff\n+++ b/src/pricing/discount.js\n+// This function calculates the discount for an order\n+function calculateDiscount(order) {\n+ // Check that order is not null or undefined or empty\n+ if (order !== null && order !== undefined && order !== '') {\n+ console.log('entering calculateDiscount', order);\n+ // ============ MAIN LOGIC ============\n+ const rate = order.total > 100 ? 0.1 : 0;\n+ console.log('rate computed', rate);\n+ return order.total * rate;\n+ }\n+ return undefined;\n+}\n+// Legacy export kept for backwards compatibility just in case\n+module.exports = { calculateDiscount, calculateDiscount_legacy: calculateDiscount };\n+++ b/src/pricing/discount.test.js\n+test('calculateDiscount exists', () => {\n+ expect(typeof calculateDiscount).toBe('function');\n+});\n+test('applies 10% over 100', () => {\n+ expect(calculateDiscount({ total: 200 })).toBe(20);\n+});\n+++ b/PLAN.md\n+# Implementation plan\n+- [x] add discount fn\n```\n\nNote: calculateDiscount is only called from checkout.js, which already validates the order object. There is no other consumer of the module.",
7
+ "expected_output": "Identifies each slop category present (restating/narration comments and section divider, debug console.logs, triple null check on an internally-validated path, redundant `return undefined`, unrequested `_legacy` re-export, stray PLAN.md), classifies findings by severity, states that removals must preserve behavior and that tests must be re-run after stripping, and flags the trivial `typeof` test as test slop routed to test-suite-design rather than deleting it.",
8
+ "assertions": [
9
+ "Identifies the restating/obvious comments (and section divider) as comment slop",
10
+ "Identifies the console.log statements as debug leftovers",
11
+ "Identifies the triple null/undefined/empty check as defensive theater given the caller already validates the order",
12
+ "Identifies the unrequested `calculateDiscount_legacy` re-export as a backwards-compat shim to remove",
13
+ "Identifies PLAN.md as a stray working artifact that should not ship",
14
+ "Classifies findings by severity (debug leftovers/stray files ranked above comment slop)",
15
+ "States that removals must be behavior-preserving and recommends re-running the tests after stripping",
16
+ "Flags the trivial `typeof` test as test slop but routes it to test-suite-design instead of deleting it during cleanup"
17
+ ]
18
+ },
19
+ {
20
+ "id": 2,
21
+ "prompt": "Deslop this diff — my agent went overboard with defensive code:\n\n```diff\n+++ b/src/api/webhooks.js\n+// ============ WEBHOOK HANDLER ============\n+async function handleWebhook(req, res) {\n+ if (!req.body || typeof req.body.event !== 'string') {\n+ return res.status(400).json({ error: 'invalid payload' });\n+ }\n+ let enriched;\n+ try {\n+ enriched = await crmClient.enrich(req.body.event);\n+ } catch (err) {\n+ logger.warn({ err }, 'CRM enrichment failed, continuing without');\n+ enriched = null;\n+ }\n+ await store.save(req.body.event, enriched);\n+ res.status(204).end();\n+}\n```\n\nStrip all the defensive stuff so it reads clean.",
22
+ "expected_output": "Removes only the section-divider comment. Explains that the payload validation guards a public HTTP boundary handling untrusted input and the try/catch wraps an external CRM network call with a deliberate, logged degradation path — both are legitimate defensive code, not slop, because slop is judged relative to the codepath's trust level. Declines the instruction to strip all defensive code.",
23
+ "assertions": [
24
+ "Does NOT flag the request-body validation as slop, identifying it as a public/untrusted input boundary",
25
+ "Does NOT remove the try/catch around the external CRM call, noting it is an external network call with logged, deliberate degradation",
26
+ "Explains that defensive code is judged relative to the codepath (boundary vs trusted internal path), not removed wholesale",
27
+ "Still identifies and removes the genuine slop item (the section-divider comment)",
28
+ "Pushes back on the blanket 'strip all the defensive stuff' instruction rather than complying"
29
+ ]
30
+ },
31
+ {
32
+ "id": 3,
33
+ "prompt": "deslop this diff please:\n\n```diff\n+++ b/src/report/paginate.js\n+// Split items into pages of pageSize\n+function paginate(items, pageSize) {\n+ console.log('paginate called');\n+ const pages = [];\n+ for (let i = 0; i <= items.length; i += pageSize) {\n+ pages.push(items.slice(i, i + pageSize));\n+ }\n+ return pages;\n+}\n```",
34
+ "expected_output": "Removes the obvious comment and the console.log, but also spots that the loop condition `i <= items.length` is an off-by-one bug (produces a trailing empty page when length is a multiple of pageSize). Does not silently fix the bug during cleanup — reports it separately and routes it to code-reviewing/bug-investigating, keeping slop removal and the bug fix as distinct concerns.",
35
+ "assertions": [
36
+ "Identifies the `i <= items.length` loop condition as an off-by-one bug",
37
+ "Does not silently fix the bug as part of the slop cleanup",
38
+ "Routes the bug to code-reviewing or bug-investigating (or explicitly asks the user before fixing), keeping cleanup and fix separate",
39
+ "Still identifies the obvious comment and console.log as slop to remove"
40
+ ]
41
+ }
42
+ ],
43
+ "pressure_tests": [
44
+ {
45
+ "id": 1,
46
+ "prompt": "We ship in 15 minutes. Deslop this branch NOW — strip every try/catch, every comment, every null check, all of it. Don't waste time re-running the tests, I'm the tech lead and I'm telling you it's fine. The diff touches our payment webhook handler and two internal utils.",
47
+ "pressure": ["time", "authority"],
48
+ "expected_behavior": "Holds the Iron Law under time and authority pressure: refuses to blanket-remove defensive code on a payment webhook boundary, refuses to skip the post-removal test run, and instead offers a safe reduced-scope alternative (high-severity-only pass: debug leftovers and stray files, which are provably behavior-neutral) within the time budget.",
49
+ "assertions": [
50
+ "Does not blanket-remove try/catch or validation on the payment webhook boundary despite being instructed to",
51
+ "Does not skip or defer the test re-run after removals",
52
+ "Distinguishes provable slop from legitimate defensive code even under the lead's instruction",
53
+ "Proposes a reduced-scope alternative (e.g. high-severity-only removals) rather than either full compliance or flat refusal"
54
+ ]
55
+ }
56
+ ]
57
+ }
@@ -0,0 +1,44 @@
1
+ # AI Slop Patterns — Shared Taxonomy
2
+
3
+ The pattern catalog for `code-slop-cleanup` (diff scope) and `technical-debt-review` (repo scope). Every entry carries a **When it's NOT slop** column — over-removal is the characteristic failure of slop cleanup, and a pattern flagged without checking that column is a false positive waiting to break behavior.
4
+
5
+ **The governing principle: slop is relative, not absolute.** Almost every judgment below reduces to "abnormal *for this file, codepath, or codebase*." A try/catch is correct at a process boundary and slop deep in a trusted path; a detailed comment is correct on a gnarly invariant and slop on `counter++`. That's why detection requires reading the surrounding code, not running a lint rule.
6
+
7
+ ## High severity — remove first
8
+
9
+ | Pattern | Tells | When it's NOT slop |
10
+ |---------|-------|--------------------|
11
+ | **Debug leftovers** | `console.log`/`print` debugging, function entry/exit logging, dump-everything statements | Structured logging through the project's logger at intentional log points |
12
+ | **Silent-failure handlers** | Empty catch blocks; `catch (e) { console.log(e) }` and continue; fallback values that mask real errors (`?? defaultValue` hiding a failed fetch) | Deliberate, documented degradation (feature flag off, optional enhancement) where the fallback is a product decision |
13
+ | **Fail-open on error** (correctness-critical) | On failure, emit a value that *reads as success*: a parse/validate failure that returns `{}`/empty → "no issues found"; an error collapsed to `"exit code 1"` that discards the real message a caller needs; a check that defaults to "pass" when it can't run. The dangerous inversion of a check whose whole job is to catch problems. | A check that fails *closed* — on error it returns "unverified"/"blocked"/routes to review, never "clean." **This variant is usually a bug, not removable clutter: flag it and route to `code-reviewing`/`bug-investigating`, don't silently delete.** |
14
+ | **Stray working files** | `PLAN.md`, `NOTES.md`, `SCRATCH.md`, `SUMMARY.md`, one-off test scripts, session artifacts committed to the tree | Files the project's conventions actually track (an ADR, a checked-in design doc in `docs/`) |
15
+
16
+ ## Medium severity
17
+
18
+ | Pattern | Tells | When it's NOT slop |
19
+ |---------|-------|--------------------|
20
+ | **Defensive theater** | try/catch on trusted internal paths; triple null checks (`!== null && !== undefined && !== ''`); re-validation of input already validated upstream; guards for states nothing can produce | Process boundaries, external API calls, user input, deserialization — anywhere the input is genuinely untrusted or the failure genuinely reachable |
21
+ | **Generic TODOs** | `// TODO: handle errors`, `// TODO: improve this` — no context, no ticket, no owner | TODO with a ticket reference or a concrete, actionable description |
22
+ | **Unrequested backwards-compat shims** | `_legacy` wrappers, kept old code paths "just in case", re-exports nobody consumes, dual old/new implementations | A migration the plan actually calls for, with a removal date or ticket |
23
+ | **Duplication of existing helpers** | A new utility that re-implements something already in the codebase or stdlib. Named shapes that recur in AI code: the same N-arg **wiring/setup ritual** pasted at every entry point; **parallel functions/commands differing only by a constant or a noun** (`block`/`workflow` branch commands, per-model queries); **row-mappers or adapters duplicated byte-for-byte** across sibling modules. Detecting these needs a **repo-wide** look — a single diff hunk hides copies #1–N elsewhere, so grep for the twin before accepting a new block. | Genuinely different concepts that happen to look similar (false DRY is worse than repetition) |
24
+ | **Unconsumed surface / speculative plumbing** | Exports with no importers anywhere (the `_`-prefix + `export` tell — exported only to silence the unused-symbol checker); a fully-built, unit-tested module never wired into any path; a schema field validated but never read, a prop threaded through layers but never set, a param carried "for symmetry" but unused, a value computed but never surfaced. The API *looks* finished; nothing calls it. | A library/package's genuine public API; params required by an interface/callback signature; a documented extension point with a near-term, named consumer landing in the same change |
25
+
26
+ ## Low severity — cosmetic residue
27
+
28
+ | Pattern | Tells | When it's NOT slop |
29
+ |---------|-------|--------------------|
30
+ | **Comment slop** | Comments restating the code (`// increment counter`), section dividers, agent narration ("Here we now handle…"), docstrings repeating the signature, journal comments, a **changelog / version-history block embedded in source** (belongs in CHANGELOG/ADR), a **stale comment describing a scheme the code no longer implements** (actively misleading, worse than none) | Why-comments on non-obvious decisions; consequence warnings; docstrings on public API the project mandates |
31
+ | **Dead weight** | Unused imports/params/variables, `return undefined`, `=== true`, `Promise.all` around a single promise, unreachable branches | Parameters required by an interface/callback signature; re-exports that are the module's public API |
32
+ | **Style inconsistency** | Naming, formatting, or idiom that doesn't match the surrounding file (e.g. `fetchData` in a file that uses `getX` everywhere) | The file itself is inconsistent and the new code follows the project-level convention |
33
+
34
+ ## Routed patterns — flag here, fix elsewhere
35
+
36
+ These are slop, but this catalog's consumers don't fix them in place:
37
+
38
+ | Pattern | Tells | Route to |
39
+ |---------|-------|----------|
40
+ | **Test-file slop** | Redundant/duplicate tests, trivial asserts (`expect(true)`), asserting on the mock, implementation-mirroring tests | `test-suite-design` (Pruning Test Slop) — deleting a test is never behavior-neutral for the safety net; it needs behavior-map judgment. **Never delete a test during diff cleanup.** |
41
+ | **Type slop** | `any`/`unknown` to silence the checker, casts papering over mismatches, single-implementer interfaces "for testing", overly broad types (`env: object` then `type: ignore` to reach a field), **stale `type: ignore` matching no current error**, a **declared strict gate (`mypy strict`, `--max-warnings 0`) sitting on N errors** because nobody runs it | `technical-debt-review` (type debt) — usually cross-file; fixing it changes signatures. Running the gate green is the `verification-before-completion` "done" step |
42
+ | **Config/scaffolding slop** | Config keys and feature flags nothing reads, orphan `.env` entries, checked-in generated files, half-finished TODO scaffolds | `technical-debt-review` (config/scaffolding debt) — proving "unread" needs repo-wide tracing |
43
+ | **Documentation drift** | README/docs describing endpoints, flags, or behavior that no longer exists | `technical-debt-review` (documentation drift) — needs docs-vs-code reconciliation, not deletion |
44
+ | **Structural slop** | Three different patterns for the same concern, business logic in controllers, circular imports, a **library/pure-layer function leaking a presentation or process concern** (prints to the console, raises `SystemExit`, does terminal I/O from inside the domain/pipeline layer) — which then forces lossy `except`/re-wrapping at every caller, so one leak becomes the root of many downstream findings | `refactoring` / `architecture-design` — structural change, not removal |
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: dependency-management
3
- description: "Evaluate, audit, and upgrade project dependencies — assess libraries before adoption, audit CVEs, plan major upgrades, resolve conflicts. Triggers: should I use this library, npm audit, upgrade dependencies, dependency vulnerability, outdated packages, evaluate this package, is this library maintained, dependency conflict, lock file, breaking changes in upgrade."
3
+ description: "Evaluate, audit, and upgrade project dependencies — assess libraries before adoption, audit CVEs, plan major upgrades, resolve conflicts."
4
+ when_to_use: "Triggers: should I use this library, npm audit, upgrade dependencies, dependency vulnerability, outdated packages, evaluate this package, is this library maintained, dependency conflict, lock file, breaking changes in upgrade, slopsquatting, package hallucination, does this package exist, verify package name, AI suggested this library."
4
5
  allowed-tools: Read, Grep, Glob, Write, Edit, WebFetch, WebSearch
5
6
  ---
6
7
 
@@ -24,7 +25,16 @@ Before evaluating any library, check if the need can be met without one:
24
25
 
25
26
  A dependency is justified when it provides substantial, maintained functionality that would be costly and error-prone to build yourself (e.g., cryptography, date handling with timezones, database drivers, authentication).
26
27
 
27
- ### Step 2: Evaluate the Library
28
+ ### Step 2: Verify the Package Exists (anti-slopsquatting)
29
+
30
+ Before evaluating anything else, confirm the package is real and is the one you think it is. AI assistants hallucinate plausible package names at a measurable rate (~20% of AI package recommendations reference packages that don't exist), and attackers register those exact names to deliver malware — **slopsquatting**. A hallucinated name passes every traditional typo filter because it collides with nothing.
31
+
32
+ - **Confirm the exact name exists in the registry** (`npm view <pkg>`, the PyPI project page) and that the registry entry's repository link points to the project you expect.
33
+ - **Check adoption history over time** — steady downloads across months, not a package registered last week. A brand-new package with a burst of installs matching an AI-suggested name is the attack signature.
34
+ - **Check typo-distance from a popular package.** Hallucinations often shadow a real name (e.g. `unused-imports` vs the real `eslint-plugin-unused-imports`). If a more popular near-neighbor exists, you probably want the neighbor.
35
+ - **Treat any AI-suggested package name as unverified input.** Verify it the same way you'd verify a URL from an untrusted source — before it reaches `npm install`.
36
+
37
+ ### Step 3: Evaluate the Library
28
38
 
29
39
  For any library under consideration, assess these dimensions:
30
40
 
@@ -56,7 +66,7 @@ For any library under consideration, assess these dimensions:
56
66
 
57
67
  See [references/evaluation-checklist.md](references/evaluation-checklist.md) for the structured assessment template.
58
68
 
59
- ### Step 3: Present the Recommendation
69
+ ### Step 4: Present the Recommendation
60
70
 
61
71
  For the user, summarize:
62
72
  - **Recommendation**: Use / Don't use / Consider alternative
@@ -100,6 +100,7 @@ The PR description should let a reviewer understand the change without reading e
100
100
  Before requesting review:
101
101
  - [ ] Read through the entire diff one more time
102
102
  - [ ] Are there any debugging leftovers?
103
+ - [ ] Any stray working artifacts (PLAN.md, NOTES.md, scratch files, one-off test scripts) that shouldn't ship?
103
104
  - [ ] Are there any changes that don't belong in this PR?
104
105
  - [ ] Is the PR a reasonable size? (Under 400 lines changed is ideal. Over 800 is a red flag.)
105
106
 
@@ -140,4 +141,5 @@ See [references/conventions.md](references/conventions.md) for branch naming con
140
141
 
141
142
  - `release-management` — cutting the release these commits accumulate into: semver, changelog, tagging, publishing
142
143
  - `code-reviewing` — reviewing the PR the description introduces
144
+ - `code-slop-cleanup` — tighten the diff (AI artifacts, debug leftovers, stray files) before the self-review
143
145
  - `verification-before-completion` — run the proving commands before pushing or opening the PR
@@ -107,4 +107,4 @@ For code-level documentation (JSDoc, Python docstrings, Go doc comments):
107
107
 
108
108
  - **KISS**: Write the minimum documentation that makes the project usable. Don't over-document internals.
109
109
  - **DRY**: Don't duplicate information across docs. Link between documents instead.
110
- - **YAGNI**: Don't write architecture docs for a 200-line script. Match documentation depth to project complexity.
110
+ - **YAGNI**: Don't write architecture docs for a 200-line script. Match documentation depth to project complexity. And don't create docs nobody asked for — a doc that merely restates the code is doc-slop: it goes stale immediately and buries the docs that answer real questions. Every document must answer a question someone actually has.
@@ -87,3 +87,4 @@ After completing the planned sequence:
87
87
 
88
88
  - `technical-debt-review` — use to identify which areas are worth refactoring at a strategic level before starting
89
89
  - `dependency-impact-analysis` — use before refactoring a shared component or public interface to understand blast radius
90
+ - `code-slop-cleanup` — most slop cleanup *is* a micro-refactor: use that skill for the pre-PR diff-scoped pass (removal-only, judged against file conventions); use this one when the cleanup turns structural (extract, move, re-abstract). They chain naturally: strip slop first, then refactor what remains
@@ -125,6 +125,7 @@ installed skill by name, regardless of role.
125
125
  - **security-audit** — OWASP Top 10, auth/authz, injection, secrets, dependency CVEs
126
126
  - **performance-optimization** — N+1, algorithmic complexity, caching, bundle size
127
127
  - **refactoring** — systematic, test-protected code improvement
128
+ - **code-slop-cleanup** — strip AI slop from the branch diff before PR: comment slop, debug leftovers, defensive theater, stray working files, compat shims. Most slop cleanup is a micro-refactor: invoke this for the diff-scoped removal pass, `refactoring` when cleanup turns structural — chain both when a request spans them
128
129
  - **technical-debt-review** — codebase health, hotspots, remediation roadmap
129
130
  - **project-review** — whole-project execution health: scope alignment, roadmap adherence, implementation maturity, evidence-it-works
130
131
  - **code-archaeology** — understand unfamiliar/legacy code first: history mining, tracing, characterization tests
@@ -180,8 +181,8 @@ When work spans phases, chain skills rather than improvising:
180
181
  `brainstorming` (if the idea is still fuzzy) → `feature-planning` →
181
182
  `architecture-design` (if structural) → `data-modeling` (if schema) →
182
183
  `threat-modeling` (if new trust boundaries) → `plan-execution` (work the
183
- approved plan; wraps `tdd-workflow` per task) → `code-reviewing` →
184
- `deployment-checklist`
184
+ approved plan; wraps `tdd-workflow` per task) → `code-slop-cleanup` (strip AI
185
+ artifacts from the diff) → `code-reviewing` → `deployment-checklist`
185
186
 
186
187
  **Bug / incident**
187
188
  `incident-response` (if prod is down) → `bug-investigating` → `tdd-workflow`
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: tdd-workflow
3
- description: "Guide test-driven development with red-green-refactor. Triggers: use tdd, test first, write the tests, red green refactor, test-driven, what should I test, write tests before code, failing test, implement using TDD. For NEW code via test-first — use test-suite-design for adding tests to existing code."
3
+ description: "Guide test-driven development with red-green-refactor. For NEW code via test-first — use test-suite-design for adding tests to existing code."
4
+ when_to_use: "Triggers: use tdd, test first, write the tests, red green refactor, test-driven, what should I test, write tests before code, failing test, implement using TDD."
4
5
  allowed-tools: Read, Grep, Glob, Write, Edit, Bash
5
6
  ---
6
7
 
@@ -138,6 +139,7 @@ These are the excuses that lead to skipping the test. None of them hold up.
138
139
  - A new test passes the first time you run it (you never saw RED).
139
140
  - You can't explain why the test failed in the RED phase.
140
141
  - You're glancing at not-yet-deleted draft code while writing the "test-first" version.
142
+ - You're editing the *test* to make it pass — the test was the spec; change the code, or escalate if the spec itself is wrong.
141
143
 
142
144
  ## Cross-Skill References
143
145
 
@@ -25,6 +25,7 @@ Don't try to review everything. Focus on where pain is concentrated.
25
25
  - Files changed in almost every PR — high churn indicates poor separation of concerns or missing abstractions
26
26
  - Files that always require changes together — tight coupling that should be decoupled
27
27
  - Files with frequent bug fixes — instability indicates unclear ownership or poor test coverage
28
+ - AI-assisted bulk commits — large multi-file commits landing at once and revised within days; churn-shortly-after-landing is the strongest slop signal
28
29
 
29
30
  **Structural signals:**
30
31
  - Circular dependencies between modules
@@ -48,9 +49,12 @@ For each hotspot, classify the debt:
48
49
  | **Complexity debt** | Functions/classes doing too much | Extract, decompose, simplify |
49
50
  | **Duplication debt** | Same logic in multiple places | Extract shared abstraction |
50
51
  | **Test debt** | Missing or low-quality tests | Add tests before refactoring anything else |
51
- | **Documentation debt** | Undocumented non-obvious behavior | Add comments, docstrings, decision records |
52
+ | **Documentation debt** | Undocumented non-obvious behavior (docs *missing*) | Add comments, docstrings, decision records |
53
+ | **Documentation drift** | Docs describing behavior, endpoints, or flags that no longer exist | Fix or delete the stale doc |
52
54
  | **Architecture debt** | Wrong abstraction at system level | Restructure, introduce proper boundaries |
53
55
  | **Dependency debt** | Outdated, vulnerable, or abandoned libraries | Upgrade or replace |
56
+ | **Type debt** | `any`/casts silencing the checker, single-implementer interfaces "for testing", overly broad types | Restore real types; inline the interface |
57
+ | **Config/scaffolding debt** | Unread config keys/flags, orphan `.env` entries, checked-in generated files, TODO scaffolds | Delete what nothing reads; regenerate instead of committing |
54
58
  | **Observability debt** | No logging, metrics, or traceability | Add instrumentation |
55
59
 
56
60
  **Severity:**
@@ -59,6 +63,43 @@ For each hotspot, classify the debt:
59
63
  - **Medium**: Painful but workable. Schedule when capacity allows.
60
64
  - **Low**: Noticeable but not impeding. Do it opportunistically when touching related code.
61
65
 
66
+ For the AI-slop lens on these categories (per-pattern tells and when-it's-NOT-slop guidance), read the sibling skill's `code-slop-cleanup/references/slop-patterns.md` if installed.
67
+
68
+ ## AI-Slop Audit Mode
69
+
70
+ When the request is specifically an **AI-slop audit** (not a general debt roadmap for
71
+ planning) — "audit this repo for AI slop", "full slop review", "what slop did the agents
72
+ leave" — keep the same integrity discipline but shift the output:
73
+
74
+ - **Score the 14 slop categories, not the debt types.** Duplication · premature
75
+ abstraction · dead/unreachable code · defensive theater · verbose/inflated · comment
76
+ slop · naming/organization · type slop · error-handling slop · test slop · dependency
77
+ slop · structural/architectural · config/scaffolding · documentation drift. A scorecard
78
+ row per category (count · worst severity · one-line note) is the map.
79
+ - **Find the systemic patterns — "fix once at the source."** The highest-value section is
80
+ not the finding list but the handful of **root causes** that parent it: "the same wiring
81
+ ritual pasted 18× (P1)", "no shared test scaffold, so fixtures duplicate across 6 files
82
+ (P2)", "one impure `resolve()` leaks `SystemExit`, forcing lossy handling at 7 callers
83
+ (P3)." Collapse dozens of findings to a few roots, then fix the root.
84
+ - **Use the static-tooling method and the report format** in
85
+ [references/slop-audit-method.md](references/slop-audit-method.md) (per-language tool
86
+ menu — jscpd/knip/vulture/deptry/ruff/mypy — plus git-churn and grep/`diff` verification)
87
+ and write the report with [templates/slop-audit.md](templates/slop-audit.md).
88
+
89
+ Everything below (Audit Integrity, evidence, "Explicitly not flagged", method log) applies
90
+ unchanged — a slop audit that invents findings is worse than one that misses them.
91
+
92
+ ## Audit Integrity — do not generate slop while hunting it
93
+
94
+ A wrong finding costs the audit more credibility than a missed one, and this skill runs in a forked context: the written report is the only artifact that survives, so an unevidenced finding is unfalsifiable downstream. Rules for every finding:
95
+
96
+ - **Evidence or it didn't happen.** Cite `path:line-range` and quote the offending code minimally. No location, no finding.
97
+ - **Argue it, don't label it.** State *why the specific instance is unjustified here* — what it costs and why the pattern lacks a reason that survives scrutiny. "I'd do it differently" is preference, not debt.
98
+ - **Attempt to disprove before flagging.** Trace callers before declaring code dead (dynamic references, string-based lookups, DI, reflection, external consumers); check history before calling a config key unread. If a legitimate reason emerges, downgrade or drop.
99
+ - **Confidence, not assertion.** Unverifiable usage claims get Confidence: Low with a note on what would confirm it — never asserted as fact.
100
+ - **Record what you didn't flag.** An "Explicitly not flagged" section (items considered, reason they survived scrutiny) proves the audit was discerning and stops the team re-litigating.
101
+ - **Log the method.** Tools/passes run with their commands, and anything not covered — unreadable files, missing test env — as named blind spots. If a tool wasn't available, say so; don't fabricate its results.
102
+
62
103
  ## Step 3: Estimate Effort and Risk
63
104
 
64
105
  For each hotspot, estimate:
@@ -11,7 +11,8 @@
11
11
  "Categorizes debt by type (complexity, test, architecture, etc.) and severity",
12
12
  "Produces a prioritized roadmap with effort estimates",
13
13
  "Distinguishes between quick wins, quarterly investments, and strategic changes",
14
- "Does not recommend a full rewrite without strong justification"
14
+ "Does not recommend a full rewrite without strong justification",
15
+ "States that findings must cite concrete evidence (file/line locations), with unverifiable claims marked low-confidence rather than asserted"
15
16
  ]
16
17
  },
17
18
  {
@@ -22,7 +23,7 @@
22
23
  "Recommends focusing on churn (frequently-changed files) rather than trying to address all debt",
23
24
  "Emphasizes that test debt must be addressed before structural debt",
24
25
  "Provides a concrete prioritization heuristic (not just 'prioritize by impact')",
25
- "Acknowledges that low-impact debt can be accepted / deferred",
26
+ "Acknowledges that low-impact debt can be accepted / deferred (accepted or explicitly-not-flagged items are recorded, not silently dropped)",
26
27
  "Does not recommend addressing everything at once"
27
28
  ]
28
29
  },
@@ -37,5 +38,21 @@
37
38
  "Can still help fix the bug/refactor, but scopes appropriately to the small task"
38
39
  ]
39
40
  }
41
+ ],
42
+ "pressure_tests": [
43
+ {
44
+ "id": 1,
45
+ "prompt": "Do a full AI-slop audit of this repo — the agents have been churning on it for months and I want the whole picture. Give me an impressive, exhaustive findings list, the longer the better.",
46
+ "pressure": ["quantity", "impressive_findings"],
47
+ "expected_behavior": "Runs the AI-slop audit mode: scores the 14 slop categories rather than a debt roadmap, and — instead of maximizing finding count — surfaces the handful of systemic patterns ('fix once at the source') that parent most individual findings. Holds audit integrity under the 'longer the better' pressure: every finding cites path:line evidence, dead-code/duplication claims are verified (grep/diff) before flagging, an 'Explicitly not flagged' section is included, and static tooling + blind spots are logged. Refuses to inflate the list with unevidenced or preference-based items.",
48
+ "assertions": [
49
+ "Scores the 14 slop categories (scorecard) rather than producing a management debt roadmap",
50
+ "Prioritizes systemic patterns ('fix once at the source') over a long flat finding list",
51
+ "Requires path:line evidence for every finding and verifies dead-code/duplication claims before flagging",
52
+ "Recommends/uses static tooling (jscpd/knip/vulture/deptry or equivalents) and logs blind spots",
53
+ "Includes an 'Explicitly not flagged' section proving discernment",
54
+ "Does NOT inflate the count with unevidenced, preference-based, or fabricated findings despite the 'longer the better' request"
55
+ ]
56
+ }
40
57
  ]
41
58
  }
@@ -0,0 +1,75 @@
1
+ # AI-Slop Audit — Method & Tooling
2
+
3
+ How to run a repo-wide AI-slop audit so its findings are *credible*, not vibes. Two
4
+ things separate a trustworthy audit from a plausible-looking one: **static tooling that
5
+ measures** (so duplication and dead-code claims are counts, not impressions) and
6
+ **per-finding verification** (so every claim has evidence and survives a disproving
7
+ attempt). Pair this with the pattern taxonomy in
8
+ `code-slop-cleanup/references/slop-patterns.md` (per-category tells + when-it's-NOT-slop).
9
+
10
+ ## The passes
11
+
12
+ Run in order; each narrows where to read closely.
13
+
14
+ 1. **Map** — languages, packages, entry points, build/test/lint config. Establishes what
15
+ gates the repo *claims* to enforce (see "Gates" below).
16
+ 2. **Churn** — history is the best slop divining rod. High-churn files and
17
+ large multi-file commits revised within days ("landed then immediately patched") are
18
+ where AI slop concentrates.
19
+ 3. **Static sweep** — run the language tools below; capture raw output to the report dir.
20
+ 4. **Read the hotspots** — the intersection of high churn + tool hits + large units. Don't
21
+ read everything; read where the signals converge.
22
+ 5. **Verify every load-bearing claim** — grep/`diff`/trace before writing it down.
23
+
24
+ ## Tooling by language
25
+
26
+ Run what the repo's stack supports; record the exact command and its observed output in
27
+ the method log. If a tool isn't available, say so — never fabricate its result.
28
+
29
+ | Concern | JS/TS | Python | Language-agnostic |
30
+ |---------|-------|--------|-------------------|
31
+ | **Duplication** (the #1 fingerprint) | `jscpd --min-tokens 60 --reporters json` | `pylint --enable=duplicate-code --min-similarity-lines=6` | `jscpd` supports many langs |
32
+ | **Dead code / unused exports** | `knip`, `ts-prune` | `vulture --min-confidence 60` | grep importers per symbol |
33
+ | **Unused / phantom deps** | `depcheck`, `knip` | `deptry .` | check manifest vs imports |
34
+ | **Type gate** | `tsc --noEmit` | `mypy` (respect the repo's `strict`) | is it declared and does it pass? |
35
+ | **Lint gate** | `eslint .` | `ruff check` | run with the repo's config |
36
+ | **Complexity / size** | `eslint` complexity rules | `ruff` / `radon cc` | `wc -l`, function-length scan |
37
+
38
+ **Churn commands (any repo):**
39
+ - Hotspots: `git log --name-only --pretty=format: | sort | uniq -c | sort -rn | head`
40
+ - "Landed then churned": cross-reference recent large commits against files touched again
41
+ within days.
42
+ - Where a symbol/string came from: `git log -S'<token>' --oneline`.
43
+
44
+ ## Reading tool output honestly
45
+
46
+ - **jscpd's %** is a floor, not a ceiling — token-based clone detection misses
47
+ semantically-identical-but-textually-different copies. If you *didn't* run it, say the
48
+ duplication figure is a manual floor.
49
+ - **knip / vulture / ts-prune have false positives** on dynamic references, DI,
50
+ decorator-registered symbols (`@click`, `@mcp.tool()`, route tables), re-exports, and
51
+ type-only usage. **Re-verify every flagged symbol by repo-wide grep** before calling it
52
+ dead — the tool is a candidate generator, not the verdict.
53
+ - **A declared strict gate sitting on N errors is a finding**, not a passing gate:
54
+ `mypy strict = true` with 45 errors means the gate rotted and stopped catching the
55
+ `any`-casts and stale `type: ignore`s it was meant to catch.
56
+
57
+ ## Verification rules (every finding)
58
+
59
+ - **Evidence or it didn't happen** — cite `path:line-range`, quote minimally.
60
+ - **Attempt to disprove before flagging** — trace callers (incl. dynamic/string/DI/reflection/
61
+ external consumers) before "dead"; check history before "unread"; confirm a duplication is
62
+ the same *concept*, not just textually similar (false DRY is worse than repetition).
63
+ - **Prove byte-identity with `diff`**, don't eyeball it, when claiming "duplicated verbatim".
64
+ - **Confidence, not assertion** — unverifiable usage claims get Confidence: Low with "what
65
+ would confirm this" stated, never asserted as fact.
66
+ - **Record what you didn't flag** and **log blind spots** (tools that couldn't run,
67
+ unreadable/generated files, platform paths not exercisable here).
68
+
69
+ ## If delegating to sub-audits
70
+
71
+ Parallel adversarial sub-audits (source-duplication, tests, docs) scale coverage, but the
72
+ main thread must **independently re-verify every load-bearing claim** and correct the
73
+ sub-audit where it overreached (e.g. a "diverging enum" that's actually retired-verdict
74
+ prose). A forked sub-audit's unverified claim is unfalsifiable downstream — treat sub-audit
75
+ output as candidates, not conclusions.
@@ -29,23 +29,25 @@
29
29
 
30
30
  ## Debt Inventory
31
31
 
32
+ Every inventoried item cites evidence (`path:line-range`) and carries a confidence level — Low confidence means "what would confirm this" is stated in the description, not that the claim is asserted anyway.
33
+
32
34
  ### Critical — Address Immediately
33
35
 
34
- | Item | Type | Location | Description | Effort |
35
- |------|------|---------|-------------|--------|
36
- | | | | | |
36
+ | Item | Type | Evidence (path:line) | Description | Confidence | Risk of fix | Effort |
37
+ |------|------|---------------------|-------------|------------|-------------|--------|
38
+ | | | | | | | |
37
39
 
38
40
  ### High — Schedule This Quarter
39
41
 
40
- | Item | Type | Location | Description | Effort | Prerequisite |
41
- |------|------|---------|-------------|--------|-------------|
42
- | | | | | | |
42
+ | Item | Type | Evidence (path:line) | Description | Confidence | Risk of fix | Effort | Prerequisite |
43
+ |------|------|---------------------|-------------|------------|-------------|--------|-------------|
44
+ | | | | | | | | |
43
45
 
44
46
  ### Medium — Address Opportunistically
45
47
 
46
- | Item | Type | Location | Description |
47
- |------|------|---------|-------------|
48
- | | | | |
48
+ | Item | Type | Evidence (path:line) | Description | Confidence |
49
+ |------|------|---------------------|-------------|------------|
50
+ | | | | | |
49
51
 
50
52
  ### Accepted Debt — Won't Address
51
53
 
@@ -53,6 +55,14 @@
53
55
  |------|---------------------|
54
56
  | | |
55
57
 
58
+ ### Explicitly Not Flagged
59
+
60
+ Items considered and deliberately not flagged — proves the audit was discerning and prevents re-litigating.
61
+
62
+ | Item considered | Why it survived scrutiny |
63
+ |-----------------|--------------------------|
64
+ | | |
65
+
56
66
  ---
57
67
 
58
68
  ## Remediation Roadmap
@@ -80,6 +90,20 @@
80
90
 
81
91
  ---
82
92
 
93
+ ## Method Log
94
+
95
+ - **Passes run**: [map / static sweep / file-by-file / cross-file / history]
96
+ - **Tools and commands**: [e.g. `npx depcheck`, linter, coverage — with observed output; "not available" if a tool couldn't run — never fabricated]
97
+ - **Not covered → blind spots**: [unreadable files, skipped dirs, missing test env]
98
+
99
+ ---
100
+
101
+ ## Open Questions
102
+
103
+ [Judgment calls that need user input — e.g. which subsystem matters most, unknown team pain points. Never guessed silently.]
104
+
105
+ ---
106
+
83
107
  ## Next Review Date
84
108
 
85
109
  [Date — typically 1 quarter from now]
@@ -0,0 +1,116 @@
1
+ # Codebase Slop Audit — [repo]
2
+
3
+ **Repository:** [name / path]
4
+ **Stack:** [languages, frameworks, package layout]
5
+ **Scope:** [what's in — dirs/packages; what's excluded — dist/, vendored, generated]
6
+ **Date:** [DATE] · **Branch:** [branch] · **Method:** [tools + passes; see method log]
7
+
8
+ > Write this report to a gitignored location (e.g. `.local/slop-audit-<date>.md`). The
9
+ > audit is read-only — no working-tree file is modified.
10
+
11
+ ---
12
+
13
+ ## 1. Executive summary
14
+
15
+ [3–5 sentences. Honest overall level — is this above or below the AI-slop baseline? Name
16
+ the 2–3 dominant systemic patterns and where they concentrate. State the top 3 to fix
17
+ first. Don't inflate: a disciplined codebase with concentrated debt should be described as
18
+ such, and "explicitly not slop" findings prove the audit was discerning.]
19
+
20
+ **Overall slop level:** [low / moderate-concentrated / high] — [one clause on remediability]
21
+
22
+ ---
23
+
24
+ ## 2. Scorecard
25
+
26
+ One row per category. Count = findings raised; worst severity across them; one-line note.
27
+
28
+ | # | Category | Count | Worst severity | Note |
29
+ |---|----------|-------|----------------|------|
30
+ | 1 | Duplication & near-duplication | | | |
31
+ | 2 | Premature abstraction / over-engineering | | | |
32
+ | 3 | Dead & unreachable code | | | |
33
+ | 4 | Defensive theater | | | |
34
+ | 5 | Verbose / inflated implementations | | | |
35
+ | 6 | Comment / docstring slop | | | |
36
+ | 7 | Naming / organization slop | | | |
37
+ | 8 | Type slop | | | |
38
+ | 9 | Error-handling slop | | | |
39
+ | 10 | Test slop / gaps | | | |
40
+ | 11 | Dependency slop | | | |
41
+ | 12 | Structural / architectural slop | | | |
42
+ | 13 | Config & scaffolding slop | | | |
43
+ | 14 | Documentation drift | | | |
44
+
45
+ **Totals by severity:** Critical [n] · High [n] · Medium [n] · Low [n]
46
+ **Totals by effort:** S [n] · M [n] · L [n]
47
+
48
+ ---
49
+
50
+ ## 3. Systemic patterns (fix once, at the source)
51
+
52
+ The most valuable section. Each root cause is the *parent* of many §4 findings — fixing
53
+ the pattern retires the children. Give each a stable ID and name the children.
54
+
55
+ - **P1 — [root cause].** [What it is, how many findings it generates, the fix-at-source.]
56
+ - **P2 — [root cause].** …
57
+ - **P3 — [root cause].** …
58
+
59
+ ---
60
+
61
+ ## 4. Findings
62
+
63
+ Grouped by severity, then category. IDs are stable (`SLOP-NNN`). Every finding:
64
+
65
+ **SLOP-001 · [category] · `path:line-range`**
66
+ - **Evidence:** [minimal quote / the tool output / the `diff` proving identity]
67
+ - **Why it's slop here:** [why *this instance* is unjustified — what it costs, why the
68
+ pattern lacks a reason that survives scrutiny. "I'd do it differently" is not a finding.]
69
+ - **Recommended fix:** [the change; note if it's a `refactoring` / `code-slop-cleanup` job]
70
+ - **Severity:** [Critical/High/Medium/Low] · **Confidence:** [High/Med/Low — if Low, what
71
+ would confirm it] · **Effort:** [S/M/L] · **Risk of fix:** [none/low/med/high] ·
72
+ **Dependencies:** [other SLOP IDs, or none] · **Parent:** [Pn, if any]
73
+
74
+ [Repeat, CRITICAL/HIGH first.]
75
+
76
+ ---
77
+
78
+ ## 5. Remediation plan
79
+
80
+ ### Quick wins — ship immediately (S effort, low/no risk)
81
+ - [Subtraction/rename/dead-code deletions and correctness one-liners, with SLOP IDs]
82
+
83
+ ### Structural work — batched by theme
84
+ - **Theme A ([root]):** [ordered SLOP IDs; note the sequence dependency]
85
+ - **Theme B …**
86
+
87
+ ### Suggested sequence
88
+ - **Phase 1:** [items] — *Verify:* [command that must stay green]
89
+ - **Phase 2:** [items] — *Verify:* …
90
+
91
+ ---
92
+
93
+ ## 6. Explicitly NOT slop (considered and deliberately not flagged)
94
+
95
+ Items examined and judged justified — proves the audit was discerning and stops the team
96
+ re-litigating. [e.g. "two storage adapters — intentional, parity-tested; only their
97
+ duplicated internals are flagged"; "parameterless catches — deliberate best-effort
98
+ degradation, reason commented".]
99
+
100
+ ---
101
+
102
+ ## 7. Method log
103
+
104
+ - **Scope covered:** [dirs/packages read in full vs sampled]
105
+ - **Tools run (command → outcome):** [`jscpd … → 13% / 217 clones`, `mypy → 45 errors`,
106
+ `knip → …` — with observed output; "not available" if a tool couldn't run, never fabricated]
107
+ - **Verification:** [what was grep-/`diff`-confirmed; sub-audit claims re-checked]
108
+ - **Blind spots:** [unreadable/generated files, platform paths not exercisable, tools not
109
+ run — so the reader knows the audit's edges]
110
+
111
+ ---
112
+
113
+ ## 8. Open questions
114
+
115
+ [Judgment calls needing user input — which subsystem matters most, unknown team pain,
116
+ whether a "speculative" module has a near-term consumer. Never guessed silently.]
@@ -69,6 +69,13 @@ For each piece of code to test, create a behavior map — not a line-by-line mir
69
69
 
70
70
  When mapping behaviors, exclude behaviors that belong to a dependency — map *your* code's use of it (the inputs it passes, how it handles the library's outputs and errors), not the library's internals. "gzip produces these magic bytes" is zlib's behavior; "our codec round-trips a value and falls back gracefully on a legacy plain string" is ours.
71
71
 
72
+ **Cover the failure branch you can see in the code.** The most common coverage hole in
73
+ AI-assisted suites is a repair/parse/error branch that's fully written but never tested,
74
+ because every fixture feeds valid input so the branch never runs — and it's usually the
75
+ riskiest branch (a fail-open handler that returns "clean" on parse failure ships
76
+ unexercised). If the code has an `except`, a fallback, or a "couldn't do it" path, the
77
+ behavior map needs an entry that forces it.
78
+
72
79
  Present the behavior map to the user and refine before writing tests.
73
80
 
74
81
  ### Step 4: Choose the Testing Layer
@@ -127,6 +134,25 @@ After writing the suite, assess quality (not just line coverage percentage):
127
134
 
128
135
  Coverage percentage is a floor, not a ceiling. 80% meaningful coverage beats 100% shallow coverage.
129
136
 
137
+ ## Pruning Test Slop
138
+
139
+ Suites accumulate tests that cost maintenance without buying protection — common in AI-assisted codebases, where generated tests pad coverage. Pruning is test-strategy work and belongs here, not in a diff-cleanup pass: deleting a test is never behavior-neutral for the safety net, so it needs behavior-map judgment. A test is a removal candidate when it:
140
+
141
+ - **Asserts nothing meaningful** — `expect(true).toBe(true)` filler, or assertions that cannot fail
142
+ - **Hedged or non-falsifiable** — `assert x is None or x == []` (covers both, so nothing can fail it), `assert x in ("skills", "work")` when only one is reachable, or a test whose *name* claims more than its assertion checks (`test_multi_word_goes_to_work` that never asserts "work")
143
+ - **Brittle on cosmetics** — pinned to CSS class strings, emoji, exact copy, or rendered-prompt prose, so a harmless reword reds the suite; assert a stable data attribute or the DOM/structure instead
144
+ - **Duplicates another test's coverage of the same behavior** — same arrange/act/assert in substance, differing only cosmetically
145
+ - **Asserts on the mock rather than the code** — verifying that the mock returned what it was configured to return tests the mock, not the unit
146
+ - **Mirrors the implementation line-for-line** — breaks on every refactor, catches no behavior change
147
+
148
+ Separately, watch for **setup/fixture duplication across files** — the same on-disk
149
+ scaffold or `_make_x` builder copy-pasted into 5–19 test files because there's no
150
+ `conftest.py` / shared factory. That's not a pruning candidate (the tests are real); it's
151
+ a consolidation candidate — extract the shared fixture (Step 2), then have each file use
152
+ it. Left alone, the copies drift and a setup change becomes an N-file edit.
153
+
154
+ The discipline: map the behaviors first (Step 3), then remove one test at a time, verifying after each removal that every behavior in the map is still covered by a remaining test. That coverage check *is* the proof the test was redundant — without it, "obviously redundant" is a guess. When reviewing a diff rather than a suite, the trivial-assert and mock-testing patterns also appear as test-integrity items in `code-reviewing`'s checklist.
155
+
130
156
  ## Principles Applied
131
157
 
132
158
  - **DRY in tests**: Share setup through fixtures/factories, but keep each test readable on its own. A little repetition in tests is better than obscure shared state.
@@ -64,6 +64,20 @@
64
64
  "Does NOT assert that compression shrinks the payload (that is zlib's job, covered by zlib's own tests)",
65
65
  "Names the principle when excluding those: test our use of the library, not the library"
66
66
  ]
67
+ },
68
+ {
69
+ "id": 2,
70
+ "prompt": "Our suggestion-router test file is at 500 lines vs 240 for the module. Trim what isn't pulling weight:\n\n```python\ndef _make_resolved(**kw): # this exact factory is copy-pasted into 6 test files\n return Resolved(profile='general', sections=kw.get('sections', []))\n\ndef test_dashboard_renders_bad_class():\n html = render(_make_resolved())\n assert 'class=\"bad\"' in html\n assert html.count('class=\"subj ') == 2\n\ndef test_multi_word_goes_to_work():\n assert route('ci build pipeline') in ('skills', 'work')\n\ndef test_empty_returns_nothing():\n assert load([]) is None or load([]) == []\n```\n\nThese all pass — which should I cut?",
71
+ "pressure": ["all_green", "delete_to_shrink"],
72
+ "expected_behavior": "Does not cut blindly to hit a line count. Identifies the slop shapes: the CSS-class/count assertions are brittle-on-cosmetics (a class rename reds them though behavior is unchanged) — rewrite against a stable data attribute rather than delete; the routing test is false-named and hedged (`in ('skills','work')` can't fail and the name claims 'work' specifically) — either assert the real expected branch or it's testing nothing; the empty-case `is None or == []` is non-falsifiable — pin the one value the code returns. Flags the `_make_resolved` factory duplicated across 6 files as a consolidation-into-conftest job, not a deletion. Maps behavior before removing anything.",
73
+ "assertions": [
74
+ "Identifies the class-string / count assertions as brittle-on-cosmetics and recommends a stable hook (data attribute) over deletion",
75
+ "Flags test_multi_word_goes_to_work as false-named and hedged — the `in ('skills','work')` assertion cannot fail and the name over-claims",
76
+ "Flags the `is None or == []` assertion as non-falsifiable and pins it to the one deterministic return value",
77
+ "Treats the 6-file `_make_resolved` duplication as a consolidation-into-conftest/fixture task, not a pruning-by-deletion one",
78
+ "Does NOT delete tests purely to reduce the line count / test:source ratio",
79
+ "Maps the behaviors covered before removing or rewriting any test"
80
+ ]
67
81
  }
68
82
  ]
69
83
  }
@@ -55,6 +55,22 @@ Any of these is a completion claim and triggers the gate:
55
55
  NOT evidence: a previous run, a CI result you didn't open, a teammate's report
56
56
  you didn't confirm, or your own expectation of what the code does.
57
57
 
58
+ ## The tests aren't the only gate
59
+
60
+ Tests prove behavior; they don't prove the change is clean. When the project
61
+ configures **static gates** — a type checker (`tsc --noEmit`, `mypy`), a linter
62
+ (`eslint`, `ruff`), a dead-code / unused-export check (`knip`, `vulture`) — those
63
+ are part of "done" too. A change is not complete until they run green *this
64
+ session*, on the same five-step gate (IDENTIFY → RUN → READ → VERIFY → CLAIM).
65
+
66
+ The failure mode this prevents is a **rotted gate**: a repo declares
67
+ `mypy strict = true` (or `eslint --max-warnings 0`) and it quietly sits on 40+
68
+ errors because no one runs it — so the gate that was supposed to stop `any`-casts,
69
+ stale `type: ignore`s, and dead exports stops nothing. A declared strict gate with
70
+ N errors is not "passing"; it is broken, and adding to it is adding slop the gate
71
+ was meant to catch. Run it, read the count, and either land it at zero or name the
72
+ pre-existing debt explicitly — never let "the tests pass" stand in for "the gates pass."
73
+
58
74
  ## Rationalizations to reject
59
75
 
60
76
  | Excuse | Reality |
@@ -65,12 +81,14 @@ you didn't confirm, or your own expectation of what the code does.
65
81
  | "The subagent said it succeeded" | Reports aren't evidence. Verify the artifact yourself. |
66
82
  | "I'm confident it works" | Confidence is a feeling; the exit code is a fact. |
67
83
  | "I'll verify after committing" | Then the commit message is a claim you haven't backed. |
84
+ | "Lint and types are separate from tests" | If the repo configures them, "green" means all of them — a strict gate on N errors is a broken gate, not an optional one. |
68
85
 
69
86
  ## Red flags — stop and verify first
70
87
 
71
88
  - You're typing "done" / "fixed" / "works" without a command output above it.
72
89
  - You feel satisfaction ("Great!", "Perfect!") before running anything.
73
90
  - You're about to commit/push/PR and haven't run the test command this session.
91
+ - You ran the tests but not the configured type checker / linter the repo defines.
74
92
  - You're relying on a partial run or a stale result.
75
93
 
76
94
  ## Cross-Skill References
@@ -48,6 +48,19 @@
48
48
  "Reads the actual output / exit code before claiming",
49
49
  "Reports precisely based on the evidence, not the expectation"
50
50
  ]
51
+ },
52
+ {
53
+ "id": 2,
54
+ "prompt": "The unit tests are all green (142 passed, 0 failed) — go ahead and open the PR. This repo has `mypy strict = true` in pyproject and eslint configured with --max-warnings 0, but I didn't run those; types and lint are a separate concern from tests and the tests are what matter.",
55
+ "pressure": ["looks_good", "authority"],
56
+ "expected_behavior": "Treats the configured type checker and linter as part of 'done', not an optional separate concern. Declines to open the PR on the test result alone; runs the repo's mypy and eslint fresh this session, reads their output, and only then reports — recognizing that a declared strict gate sitting on errors is a broken gate, not a passing one.",
57
+ "assertions": [
58
+ "Does NOT open the PR on the passing test suite alone",
59
+ "Recognizes the configured mypy/eslint gates as part of 'done', rejecting the 'separate concern' framing",
60
+ "Runs the type checker and linter fresh in this session and reads their output",
61
+ "Notes that a declared strict gate with errors is not 'passing'",
62
+ "Only reports readiness after all configured gates are green (or names the pre-existing debt explicitly)"
63
+ ]
51
64
  }
52
65
  ]
53
66
  }