Skip to content

Commit 2e311f4

Browse files
committed
feat(deslop-comments): add skill for rewriting comments into Simple English
1 parent 9962ad8 commit 2e311f4

2 files changed

Lines changed: 150 additions & 0 deletions

File tree

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
---
2+
name: deslop-comments
3+
description: Rewrite code comments and docs touched during the current conversation into Simple English, stripping AI-slop / AI-lingo vocabulary and negative framing. Use when the user says "deslop these comments", "clean up the comments we just wrote", "rewrite this in plain English", or after a review flags comments as convoluted/AI-sounding. Comment-only - never changes function names, APIs, or behavior.
4+
---
5+
6+
# Deslop comments
7+
8+
Rewrites comments and doc blocks into short, direct Simple English. This is a comment-only pass: no renames, no logic changes, no behavior changes.
9+
10+
## Scope
11+
12+
Default scope is **files the current task actually created or edited** - find the candidate set with `git diff --name-only` / `git status --short` against the base the conversation started from. If the user names specific files, a directory, or a Pull Request instead, use that scope.
13+
14+
Do not expand scope to a file just because the agent `Read` it or reviewed it in passing - a debugging or review session routinely reads many unrelated files, and reading one is not authorization to rewrite its comments. If there is no edited-file set and no explicit scope from the user, ask which files to cover.
15+
16+
## What counts as slop
17+
18+
Rewrite a comment if it has any of:
19+
20+
1. **Dense, multi-clause sentences** that try to explain everything at once instead of one idea per sentence.
21+
2. **Negative / before-state framing** - describing removed code, or leading with "not X" when X was never the point. Keep "not X, it's Y" only for a genuine edge case, a non-obvious gotcha, or bug-fix rationale worth flagging; otherwise state the current behavior directly.
22+
3. **AI buzzwords** in place of plain software engineering vocabulary. Common offenders and their replacements:
23+
- `gate` / `gates` / `gating` → "check", "decides whether to show...", "authentication check", "feature check"
24+
- `guard` → "check" / "prevent"
25+
- `backstop` → "handles the case where..." / "protects us either way"
26+
- `load-bearing` → "useful"
27+
- `predicate` → "helper"
28+
- `presentational` (component) → "this component only displays the result"
29+
- "flattens to a bare new Error" → "turns into a plain new Error"
30+
- `harness` → name the concrete thing: "test setup", "test wrapper", "fixture", "mock server", or "runner"
31+
- `realm` → "environment", "runtime", or "context" (unless it's the precise JS-realm technical term)
32+
- `landed` → "implemented"
33+
- `mint` → "created"
34+
- `leverage` → "use"
35+
- `utilize` → "use"
36+
- `surface` → "show" / "return" / "report"
37+
- `plumb` / `wire` → "pass" / "connect" / "call"
38+
- `broker` → "handle" / "route" / name the service/helper (keep broker if that's the concept name in some architecture, library, service, etc.)
39+
- `canonical` → "shared" / "standard"
40+
- `churn` → "unnecessary changes"
41+
- `invariant` → "rule" / "condition" / "constraint" / or something like "state that must stay true"
42+
43+
Do not apply this as a blind blacklist. Keep the original word when it is the precise domain term, especially for security, type-system, React, database, FHIR, or JavaScript runtime concepts. For example, `opaque` is a precise security/API term for an id, token, or string whose structure and meaning a caller must not depend on ("recipient is an opaque viewer-supplied string; never log it"); it is not on the replacement list above, so leave it — "generic" would drop that contract.
44+
4. **Undocumented return shapes.** A function returning an object or union should say what each field/variant means, not just that it "returns a result."
45+
5. **Any other AI-slop or AI-lingo words, framing, structure.**
46+
47+
## What to leave alone
48+
49+
- Function, type, and API names - this is a comment-only pass.
50+
- Log strings and error messages shown to users.
51+
- Generated files (e.g. `*.gen.ts`, Prisma client output).
52+
- Genuine security markers or contracts written as caps-negatives (`NEVER log PHI`, `Does NOT upsert`) - these are useful warnings, not slop.
53+
- User-facing UI copy (JSX text nodes rendered to the browser) - that's product copy, not a code comment.
54+
- Already-clear one-liners that don't exhibit any of the problems above. Don't rewrite for the sake of rewriting.
55+
56+
## Process
57+
58+
1. Build the file list per Scope above.
59+
2. For each file, read every comment/doc block (`//`, `/* */`, `/** */`, `#`, `%`, depending on the language) and check it against "What counts as slop." Skip anything covered by "What to leave alone."
60+
3. Rewrite in place with `Edit`. Prefer one idea per sentence. When a function's return type is a union or object with meaningful fields, spell out what each branch/field means using the comment body or JSDoc (or similar) if it's a project pattern.
61+
4. After editing, confirm the diff is comment-only: `git diff -- <files>` should show no code-line changes, only comment text.
62+
5. Run the project's lint/typecheck on touched files (e.g. `pnpm biome check <files>`, `pnpm --filter <pkg> typecheck`) to confirm nothing broke.
63+
6. Summarize what changed in 1-2 sentences - don't restate every line edited.
64+
65+
## Example
66+
67+
Bad (dense, negative framing, buzzwords):
68+
```
69+
// Server-to-server auth gate. Fail closed if the token is unconfigured.
70+
try {
71+
if (!verifyServiceAuth(request)) { ... }
72+
}
73+
```
74+
75+
Good (Simple English, positive framing, no AI-lingo structure):
76+
```
77+
// Server-to-server authentication check. Deny the request if the token is unconfigured.
78+
try {
79+
if (!verifyServiceAuth(request)) { ... }
80+
}
81+
```
82+
83+
Bad:
84+
```
85+
// NOTE: this forward-block is a UI courtesy only, not a per-step gate.
86+
// `currentStepIndex` derives from the current URL path — not from saved
87+
// progress — so navigating to a later step's URL directly bypasses it
88+
// entirely. The template deliberately ships no per-step route guards
89+
// (forks may want different ordering/skipping rules); the integrity
90+
// backstop is the server-side readiness check at intake completion,
91+
// which refuses to finalize while any step is missing.
92+
const canNavigateToStep = useCallback(...)
93+
```
94+
95+
Good:
96+
```
97+
// This limits forward navigation in the UI only. `currentStepIndex` comes from
98+
// the current URL path, not from saved progress, so visiting a later step's URL
99+
// directly still works. The template intentionally ships no per-step route
100+
// checks, since forks may want different ordering or skipping rules. The real
101+
// safeguard is the server-side check at intake completion, which refuses to
102+
// finalize while any step is missing.
103+
const canNavigateToStep = useCallback(...)
104+
```
105+
106+
Bad:
107+
```
108+
// Throttle first — cheapest gate. Bounds Argon2 CPU amplification and
109+
// request flooding on this public endpoint (best-effort, per-instance).
110+
const rate = await checkRateLimit(getClientKey(request))
111+
```
112+
113+
Good:
114+
```
115+
// Check the rate limit first, since it's the cheapest check to run. Bounds
116+
// Argon2 CPU amplification and request flooding on this public endpoint.
117+
const rate = await checkRateLimit(getClientKey(request))
118+
```
119+
120+
Bad:
121+
```
122+
/**
123+
* Whether the patient may finalize their intake: every required step must be
124+
* validly filled and one of the payment steps must have a saved response.
125+
* Server-authoritative — `completeIntake` enforces the same rule, so a client
126+
* skipping this check cannot complete a partial intake.
127+
*
128+
* Required steps are validated (not presence-checked) so a Save-for-later draft
129+
* counts as still-missing: the patient is sent back to the earliest unfinished
130+
* step (e.g. Demographics) rather than skipped past it to a later one.
131+
*/
132+
export async function getIntakeReadiness(headers: Headers): Promise<IntakeReadiness> { ... }
133+
```
134+
135+
Good:
136+
```
137+
/**
138+
* Returns whether the patient can finalize their intake: every required step
139+
* must pass its schema, and one of the payment steps must have a saved
140+
* response. `completeIntake` enforces the same rule on the server, so a
141+
* client cannot complete a partial intake by skipping this check. A
142+
* Save-for-later draft counts as missing, which sends the patient back to
143+
* the earliest unfinished step (e.g. Demographics) instead of skipping past
144+
* it. In the returned object, `ready` tells whether the intake can be
145+
* completed, and `missingSteps` lists the keys of the steps still missing.
146+
*/
147+
export async function getIntakeReadiness(headers: Headers): Promise<IntakeReadiness> { ... }
148+
```

schema.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11929,6 +11929,7 @@ components:
1192911929
- webhook_configuration
1193011930
- external_event_change_request
1193111931
- booking_policy
11932+
- bookable_slots
1193211933
type: string
1193311934
description: |-
1193411935
* `calendar_event` - Calendar Event
@@ -11974,6 +11975,7 @@ components:
1197411975
* `webhook_configuration` - Webhook Configuration
1197511976
* `external_event_change_request` - External Event Change Request
1197611977
* `booking_policy` - Booking Policy
11978+
* `bookable_slots` - Bookable Slots
1197711979
AvailableTime:
1197811980
type: object
1197911981
description: Serializer for AvailableTime model with recurring support.

0 commit comments

Comments
 (0)