swarm repositories / source
aboutsummaryrefslogtreecommitdiff
path: root/skills/exterminate-slop/SKILL.md
blob: 4d1530583b31dcb71a85f5a90615f081e426aa78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
---
name: exterminate-slop
description: "Perform an exhaustive language-aware subtree audit and refactor pass for primitive obsession, under-abstraction, duplicated logic, defensive ceremony, and code-volume bloat. Use when Codex needs to inspect every source file in a requested scope, keep a persisted worklog/ledger, and refactor toward strong types, DRY abstractions, and sharply reduced code without behavior drift."
---

# Exterminate Slop

Read the target repo's AGENTS.md files first.

This is a slop extermination pass, not a style review. The objective is to crush code volume and ceremony while increasing semantic density. Preserve externally observable behavior unless the user explicitly asks for behavior change. Do not preserve backward compatibility by default.

## Language Lens

Before the first source read, determine the dominant implementation language for the requested scope and read exactly one note:

- Rust: [references/languages/rust.md](references/languages/rust.md)
- Java: [references/languages/java.md](references/languages/java.md)
- Python: [references/languages/python.md](references/languages/python.md)
- TypeScript: [references/languages/typescript.md](references/languages/typescript.md)

If the scope truly crosses language boundaries, start with the dominant language and load a second note only when edits must cross that boundary. If no note exists for the dominant language, proceed with this generic core and record the missing note in the worklog.

## Contract

- Require a concrete source subtree. If the user names only a repo, choose the smallest plausible subtree and state the assumption.
- Default to `audit_plus_refactor` unless the user clearly wants findings only.
- Build a full manifest of in-scope source files for the chosen language. No sampling and no "representative files."
- Exclude generated, vendored, build-output, fixture, snapshot, and dependency files unless the user explicitly includes them.
- Create one persistent `/tmp` worklog before the first source read. Chat is summary only; the worklog is the durable source of truth.
- Take a cheap code-volume baseline for the manifest before edits. At minimum count lines; token count is welcome when cheap.
- Partition the manifest into intentional logical cliques before deep reading.
- Read at most 8 files per wave.
- Write a `/tmp` checkpoint after every wave before reading more files.
- Record raw suspects during coverage, then promote only threshold-clearing suspects into the formal ledger after full coverage.
- Force a decision on every promoted ledger row.
- Do not edit until the promoted ledger exists, unless the user explicitly asked for a narrow hotfix instead of a full extermination pass.
- Refactor in abstraction batches, not in arbitrary file order.
- Run the narrowest meaningful checks after edits, then widen if the abstraction crosses boundaries.
- Re-scan the manifest and record residual slop plus code-volume delta.

Files may be re-read. Re-reading is expected when a file belongs to multiple logical cliques or when a later duplication cluster changes the correct abstraction boundary.

## Flow

### 0. Create The Worklog

Create a path shaped like:

```text
/tmp/exterminate-slop-<repo-or-dir>-<subtree-slug>.md
```

Seed it with the worklog skeleton below.

The worklog must hold the language lens, manifest, volume baseline, clique plan, wave checkpoints, rejected clusters, promoted ledger, edits, verification, residual sweep, and volume delta.

If interrupted or resumed, reopen the same worklog before continuing.

### 1. Lock Scope And Manifest

Enumerate the full source manifest using the loaded language note. Examples:

```bash
rg --files <subtree> -g '*.rs'
rg --files <subtree> -g '*.java'
rg --files <subtree> -g '*.py'
rg --files <subtree> -g '*.ts' -g '*.tsx' -g '*.mts' -g '*.cts'
```

Persist the manifest and baseline immediately. If the note gives different inclusion rules, follow the note.

### 2. Plan Logical Cliques

Before deep reading, group manifest files into small logical cliques.

Good clique causes:

- shared domain concepts or latent domain objects
- repeated parse, validate, normalize, or coercion flows
- repeated rendering, formatting, serialization, or transport mapping
- repeated construction, patch, query, or conversion logic
- repeated control-flow skeletons
- parameter clumps, field bundles, or option bags crossing boundaries
- module-boundary interactions
- suspected duplication clusters

Cliques may overlap. A file may appear in multiple cliques. Keep cliques to 2-8 files; split larger conceptual groups into multiple related waves.

### 3. Run Coverage Waves

For each clique wave:

- read at most 8 files
- use the language's semantic navigation tools aggressively when available
- anchor from live use sites before declaration spelunking
- update manifest coverage
- write a checkpoint containing:
  - clique id and purpose
  - files inspected
  - raw suspects
  - duplication hypotheses strengthened or weakened
  - files worth re-reading in later cliques
  - abstraction pressure
  - code-volume pressure

Do not read a 9th file until that checkpoint exists. A file counts as covered once it has been read in at least one wave.

### 4. Run Smell Passes

Run distinct passes over the manifest and checkpointed suspects. If a pass needs more context, form another clique and respect the 8-file cap again.

#### Primitive Semantics

Interrogate strings, numbers, booleans, nulls, sentinels, loose maps, loose objects, tuple-ish sequences, and raw identifiers. Ask whether the value is really an id, slug, path, URL, unit, currency, status, mode, phase, capability, policy, timestamp, validated token, finite world, or richer domain object.

#### Bundles And Bags

Interrogate tuples, argument clumps, option bags, repeated object shapes, repeated field bundles, parallel collections, public optional walls, and correlated primitive sets. Ask whether the same values travel together, whether invalid states are currently representable, and whether one named representation would delete the surrounding ceremony.

#### Duplication And Under-Abstraction

Search for repeated parse, validate, normalize, default-fill, render, serialize, authorize, query, convert, patch, compare, and error-shaping logic. Search for branch skeletons with only small local differences. Treat DRY as stronger than YAGNI.

#### Defensive Theater

Interrogate checks, wrappers, fallbacks, compatibility shims, exception laundering, nil/null/undefined handling, default values, and "safe" access paths. If static structure, construction flow, or local dominance proves the value exists, delete the ceremony. If the fallback has no honest semantics, fail fast.

#### Code-Volume Bloat

Interrogate code whose main sin is existing: pass-through layers, one-line wrappers, adapter twins, DTO mirrors, getter/setter husks, scattered casts, repeated fixtures, duplicated builders, commented-out compatibility, and explanatory locals that only compensate for weak structure. The pass has an explicit line/token reduction objective.

### 5. Promote Suspects

During coverage, keep only raw suspects. After every manifest file has been inspected at least once, promote a suspect into the formal ledger only if at least one is true:

- it appears in more than one file or module
- it crosses a meaningful boundary
- it shows invariant pressure rather than cosmetic repetition
- it deletes code volume while preserving or strengthening semantics
- the fix is locally actionable now

Anything not promoted must still be accounted for as a short rejected cluster. Persist both promoted and rejected outcomes in the worklog.

### 6. Populate And Adjudicate The Ledger

Populate the formal ledger with one row per promoted candidate.

Allowed `kind` values:

- `primitive_semantics`
- `weak_type`
- `boolean_mode`
- `tuple_or_sequence`
- `clump_or_bag`
- `duplicate_logic`
- `primitive_control_encoding`
- `defensive_theater`
- `ceremonial_layer`
- `volume_bloat`

Allowed `decision` values:

- `refactor_now`
- `defer`
- `false_positive`
- `needs_broader_design`

For every row, choose exactly one decision. The ledger is authoritative even if chat shows only a condensed view.

### 7. Refactor In Batches

Group work by semantic move:

- primitive semantics → domain type, literal world, enum, opaque/branded type, value object, validated constructor, or parser boundary
- primitive control encoding → closed variant, state type, policy object, dispatch table, or sealed/discriminated hierarchy
- tuple or clump → named domain object with the invariant in one place
- loose bag → precise typed record, variant, or boundary DTO converted immediately
- duplicate logic → one owner function, constructor, trait/protocol/interface, table, macro, generator, or module
- defensive theater → static proof, fail-fast access, or single boundary check
- volume bloat → deletion, fusion, abstraction, or mechanical modernization

Prefer the clean shape over compatibility. Apply the language note's sharper moves where it speaks.

### 8. Verify And Sweep

After edits:

- run relevant checks on the touched surface
- re-scan the same manifest
- measure code-volume delta
- update the worklog with eliminated rows, deferred rows, false positives, residual hotspots, verification, and volume results

Prefer the narrowest checks that still validate the changed surface, then widen if needed.

## Embedded Forms

### Worklog Skeleton

```text
worklog_path:
scope_root:
inspection_mode: audit_only | audit_plus_refactor
language:
language_note:
wave_size_limit: 8

volume_baseline:

manifest:

clique_plan:

wave_checkpoints:

rejected_clusters:

promoted_ledger:

edits:

verification:

residual_sweep:

volume_after:
volume_delta:
```

### File Manifest

```text
scope_root:
inspection_mode: audit_only | audit_plus_refactor
language:
language_note:
wave_size_limit: 8

files:
- [ ] path/to/file_a
- [ ] path/to/file_b
- [ ] path/to/file_c
```

Rules:

- include every source file in the requested subtree for the selected language
- mark files as inspected only after reading them
- allow files to appear in multiple clique waves
- do not delete rows from the manifest during refactoring
- use the same manifest again for the residual sweep

### Clique Wave Checkpoint

```text
clique_id:
purpose:
why_these_files_belong_together:
wave_size:

files:
- path/to/file_a
- path/to/file_b

checkpoint:
- raw suspects:
- duplication hypotheses:
- likely rereads:
- abstraction pressure:
- code-volume pressure:
```

Rules:

- `wave_size` must never exceed `8`
- write a checkpoint into the worklog after every wave before reading more files
- keep the checkpoint terse and raw; do not inflate every suspect into a formal ledger row yet
- name the clique by the suspected relationship, not by arbitrary adjacency

### Rejected Cluster

```text
cluster_id:
kind:
sites:
- path/to/file_a :: short note
- path/to/file_b :: short note

rejection_reason:
still_watch_for:
```

Good rejection reasons:

- boundary-shaped transport code
- serialization or protocol surface where primitive form is correct
- cosmetic repetition without invariant pressure
- local-only pattern with no cross-site duplication
- abstraction name still too foggy to justify extraction

### Promoted Ledger

```text
| row_id | path | symbol_or_site | kind | evidence | suspected_abstraction | duplication_cluster | volume_effect | confidence | decision | decision_reason |
|--------|------|----------------|------|----------|-----------------------|---------------------|---------------|------------|----------|-----------------|
| S001 | src/foo | User.id: string | primitive_semantics | parsed, validated, and compared in 3 places | UserId domain type | id-handling-1 | deletes repeated validation | high | refactor_now | domain identifier with repeated normalization |
| B001 | src/bar | run(..., dryRun: boolean) | boolean_mode | positional flag controls strategy | ExecutionMode variant | mode-flags-1 | removes branch duplication | high | refactor_now | bool hides a mode split |
| D001 | src/baz | copy/update loop | duplicate_logic | same field-by-field patch in 4 sites | owned patch function | patching-2 | deletes 40 lines | medium | refactor_now | one owner is obvious |
```

Requirements:

- `evidence` must name the concrete smell, not a vague feeling
- `suspected_abstraction` must be specific
- `volume_effect` must state deletion/compression potential when relevant
- `duplication_cluster` must group related rows when applicable
- `decision_reason` must explain why the row did or did not graduate into an edit
- do not create rows for suspects that failed promotion; summarize those as rejected clusters instead

## Adjudication Checklist

For every ledger row, ask:

- Does this primitive or shape carry domain semantics rather than mere transport?
- Are invalid states representable today?
- Does validation, normalization, parsing, formatting, or defaulting repeat?
- Do correlated values drift apart because no one object owns them?
- Does this cross a boundary where the weak shape becomes contagious?
- Would a stronger type or abstraction delete nearby code?
- Is the abstraction name sharp enough to carry the invariant?
- Can the fix be made locally, or does it require a broader design cut?

Decision mapping:

- `refactor_now`: the abstraction is clear and locally actionable now
- `defer`: the smell is real but the present diff would be premature
- `false_positive`: the shape is genuinely incidental or boundary-correct
- `needs_broader_design`: the smell is real but the right abstraction spans a larger domain cut

## Final Response

Always include:

- the `/tmp` worklog path
- language note used
- manifest coverage summary
- clique-wave summary
- rejected-cluster summary
- promoted-ledger summary
- volume baseline and delta

If you edited code, also include:

- abstraction batches executed
- verification summary
- residual sweep summary

If you did not edit code, include the highest-value next moves.

## Hard Failure Modes

- do not inspect only "important" files
- do not skip the `/tmp` worklog or keep checkpoint state only in chat
- do not read more than 8 files without a persisted checkpoint
- do not silently compact a wave because you feel you "basically got it"
- do not treat one clique as if it exhausts all duplication relationships
- do not promote everything into the formal ledger just to feel exhaustive
- do not drop non-promoted suspects on the floor; summarize them as rejected clusters
- do not jump into edits before the promoted ledger exists
- do not propose generic cleanup without row-level evidence
- do not preserve compatibility unless the user asked for it
- do not let tests, lint, or formatters substitute for the extermination pass