@kensio/skills 1.13.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 +48 -0
- package/bin/kensio-skills.mjs +213 -0
- package/package.json +39 -0
- package/skills/dynamodb-single-table/SKILL.md +329 -0
- package/skills/dynamodb-single-table/references/aws-guidance.md +183 -0
- package/skills/github-issue-drafting/SKILL.md +260 -0
- package/skills/isolated-testing-style/SKILL.md +293 -0
- package/skills/pangram-check/SKILL.md +125 -0
- package/skills/pangram-check/references/configuration.md +120 -0
- package/skills/pangram-check/references/reading-results.md +69 -0
- package/skills/pangram-check/scripts/pangram-check.mjs +807 -0
- package/skills/part-factory-test-data/SKILL.md +238 -0
- package/skills/skill-template/SKILL.md +126 -0
- package/skills/technical-prose-style/SKILL.md +356 -0
- package/skills/technical-prose-style/references/measurements.md +356 -0
- package/skills/technical-prose-style/scripts/prose-check.mjs +381 -0
- package/skills/yulin-aws-simulation/SKILL.md +324 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: technical-prose-style
|
|
3
|
+
description: Write documentation, READMEs, code comments, commit messages, release notes and PR text as plain technical prose, by removing the constructions that make unedited LLM prose tiring to read. It targets significance tails, contrastive definition, negation framing, appositive tails, colon explainers and a vocabulary that keeps renaming the same thing. Ships a script that scores prose against Django, Go, Rust and Python documentation. Use when writing or editing docs, a README, a changelog, a blog post or any prose for human readers, when asked to improve, tighten or rewrite writing, when prose "sounds like AI" or "sounds like Claude", and when reviewing documentation in a pull request.
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
metadata:
|
|
6
|
+
version: "1.13.1"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Technical prose style
|
|
10
|
+
|
|
11
|
+
For anything a human reads: `docs/`, README files, code comments, commit messages, release notes,
|
|
12
|
+
issue and pull request text.
|
|
13
|
+
|
|
14
|
+
## What this is for
|
|
15
|
+
|
|
16
|
+
Unedited LLM prose is tiring to read. It is usually accurate, and the reader usually knows it was
|
|
17
|
+
machine-drafted and minds that far less. What wears them down is the shape of it. One construction
|
|
18
|
+
returns over and over. Every fact trails a clause explaining why the fact matters. A fresh synonym
|
|
19
|
+
arrives where the previous term would have done.
|
|
20
|
+
|
|
21
|
+
The goal here is prose that costs the reader less. Concealment is a different aim, and out of scope.
|
|
22
|
+
An independent detector still identifies text that follows every rule below as machine-written. Six
|
|
23
|
+
rewritten documents were put through one to check. See [Limits](#limits) at the end.
|
|
24
|
+
|
|
25
|
+
The rules below come from measurement. 192,000 words of LLM-written technical documentation were
|
|
26
|
+
compared against 66,000 words of Django, Go, Rust and Python documentation, and only the patterns
|
|
27
|
+
where the two differed by a factor of two or more were kept. The six that survived run between 2.3
|
|
28
|
+
and 8.3 times the human rate. Everything else tested came in under 1.2 times. Thresholds are set so
|
|
29
|
+
that no human document in the corpus fails and every LLM document does.
|
|
30
|
+
[references/measurements.md](references/measurements.md) records the method, the thresholds, the
|
|
31
|
+
candidates that were tested and dropped, and a dependency-parser study that falsified four more.
|
|
32
|
+
|
|
33
|
+
Read [What to leave alone](#what-to-leave-alone) before rewriting anything. Several of the usual
|
|
34
|
+
style rules make the prose worse, and the measurements show why.
|
|
35
|
+
|
|
36
|
+
## The target
|
|
37
|
+
|
|
38
|
+
Write the way Go's package documentation and the Django docs are written.
|
|
39
|
+
|
|
40
|
+
- One claim per sentence.
|
|
41
|
+
- The subject is something the reader can point at, such as a function, a queue, a file or a test.
|
|
42
|
+
Not "what a deterministic assertion wants".
|
|
43
|
+
- Present tense, active voice.
|
|
44
|
+
- Say what the thing does, then stop. Trust the reader to work out what it means for them.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
CreateQueue is idempotent. A second request for the same name returns the existing queue's URL
|
|
48
|
+
if the attributes match, and fails with QueueNameExists if they differ.
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Two sentences carrying two facts, with the consequences left to the reader.
|
|
52
|
+
|
|
53
|
+
## The four sentence patterns
|
|
54
|
+
|
|
55
|
+
Each one is a sentence shape. A banned word list can be followed perfectly while the prose still
|
|
56
|
+
reads as machine-written, because vocabulary bans do not touch any of these.
|
|
57
|
+
|
|
58
|
+
### 1. Significance tail
|
|
59
|
+
|
|
60
|
+
A fact, followed by a clause explaining why the fact matters.
|
|
61
|
+
|
|
62
|
+
Detect: `,\s+so\s+(a|an|the|it|that|this|there|nothing|no|tests?|you|we|they)\b`
|
|
63
|
+
|
|
64
|
+
The comma is what makes this a tail. `so` without one is usually doing honest work.
|
|
65
|
+
|
|
66
|
+
This is the model showing its working. State the fact and leave the working out. Where the
|
|
67
|
+
consequence genuinely matters, give it its own sentence. Most of the time a reader holding the fact
|
|
68
|
+
can derive it.
|
|
69
|
+
|
|
70
|
+
<!-- prose-check:off -->
|
|
71
|
+
|
|
72
|
+
> **Before.** The message records the instant it is hidden until, and it becomes receivable again
|
|
73
|
+
> once simulated time reaches that instant. Advancing the clock is therefore all a test needs to
|
|
74
|
+
> watch an undeleted message come back.
|
|
75
|
+
|
|
76
|
+
<!-- prose-check:on -->
|
|
77
|
+
|
|
78
|
+
> **After.** The message records the instant it is hidden until. It becomes receivable again once
|
|
79
|
+
> simulated time reaches that instant.
|
|
80
|
+
|
|
81
|
+
### 2. Contrastive definition
|
|
82
|
+
|
|
83
|
+
Defining a thing by what it is not, or by the alternative it displaces. This one has two surface
|
|
84
|
+
forms, and the checker scores them separately.
|
|
85
|
+
|
|
86
|
+
Detect (`contrastive-def`): `\b(rather than|instead of)\b`
|
|
87
|
+
|
|
88
|
+
Detect (`contrastive-coda`): `,\s+not\s+...` running to the end of the sentence
|
|
89
|
+
|
|
90
|
+
The coda is the commoner of the two, and it separates the corpora more sharply (8.3 times the human
|
|
91
|
+
rate, against 6.2 for the two-word forms). It went undetected for four releases because the first
|
|
92
|
+
regex only looks for `rather than` and `instead of`. The rule was right and the regex was half the
|
|
93
|
+
size of it. Any rule expressed as a pattern is worth checking for that same gap.
|
|
94
|
+
|
|
95
|
+
Say what the thing does. Reach for a contrast only when the reader is likely to hold the wrong
|
|
96
|
+
belief and the correction is the point of the sentence. Where that test passes, the correction has
|
|
97
|
+
earned a sentence of its own, and it reads better in one.
|
|
98
|
+
|
|
99
|
+
<!-- prose-check:off -->
|
|
100
|
+
|
|
101
|
+
> **Before.** A service is kept as state rather than by a timer, so a test that finishes with a
|
|
102
|
+
> service running leaves nothing behind it.
|
|
103
|
+
|
|
104
|
+
<!-- prose-check:on -->
|
|
105
|
+
|
|
106
|
+
> **After.** A service is kept as state. Closing the simulated environment stops it.
|
|
107
|
+
|
|
108
|
+
<!-- prose-check:off -->
|
|
109
|
+
|
|
110
|
+
> **Before.** Assert behaviour, not call counts.
|
|
111
|
+
|
|
112
|
+
<!-- prose-check:on -->
|
|
113
|
+
|
|
114
|
+
> **After.** Assert behaviour. A call count passes when the code calls the right method for the
|
|
115
|
+
> wrong reason.
|
|
116
|
+
|
|
117
|
+
### 3. Negation framing
|
|
118
|
+
|
|
119
|
+
Sentences built on `nothing`, `is not`, `does not`, `neither`.
|
|
120
|
+
|
|
121
|
+
Detect: `\b(is not|are not|does not|nothing|neither)\b`
|
|
122
|
+
|
|
123
|
+
Negation is fine when the absence is the fact being documented, such as a limitation or an
|
|
124
|
+
unsupported option. It is a tic when it is a roundabout way of stating something positive. "Nothing
|
|
125
|
+
here replaces the process clock" is the same fact as "time belongs to a `SimAws` instance", written
|
|
126
|
+
backwards.
|
|
127
|
+
|
|
128
|
+
<!-- prose-check:off -->
|
|
129
|
+
|
|
130
|
+
> **Before.** Nothing here replaces the clock for the whole process. Time belongs to a `SimAws`
|
|
131
|
+
> instance, so moving it never disturbs another simulation running in the same test file, the real
|
|
132
|
+
> clock, or any other code in the process.
|
|
133
|
+
|
|
134
|
+
<!-- prose-check:on -->
|
|
135
|
+
|
|
136
|
+
> **After.** Time belongs to a `SimAws` instance. Moving it affects that instance only. The host
|
|
137
|
+
> clock and any other simulation in the process carry on unchanged.
|
|
138
|
+
|
|
139
|
+
Headings take this worst, and they used to escape the checker (it strips headings before counting,
|
|
140
|
+
so for four releases nothing scored them). A heading framed by what a section excludes makes the
|
|
141
|
+
reader invert it to find out what the section contains. The checker now reports these as advisory,
|
|
142
|
+
because two Django headings in the human corpus are legitimately negative and a hard failure would
|
|
143
|
+
flag them.
|
|
144
|
+
|
|
145
|
+
<!-- prose-check:off -->
|
|
146
|
+
|
|
147
|
+
> **Before.** Get isolation from the data, not from setup and teardown
|
|
148
|
+
|
|
149
|
+
<!-- prose-check:on -->
|
|
150
|
+
|
|
151
|
+
> **After.** Take isolation from randomised data
|
|
152
|
+
|
|
153
|
+
### 4. Appositive tail
|
|
154
|
+
|
|
155
|
+
A trailing `, which is` / `, which means` clause that comments on the sentence it is attached to.
|
|
156
|
+
|
|
157
|
+
Detect: `, which (is|means|makes|gives|lets|keeps|does)\b`
|
|
158
|
+
|
|
159
|
+
The same reflex as the significance tail, wearing a relative pronoun. Either promote the clause to
|
|
160
|
+
its own sentence or delete it.
|
|
161
|
+
|
|
162
|
+
<!-- prose-check:off -->
|
|
163
|
+
|
|
164
|
+
> **Before.** The schedule has to exist: updating one that is not there is a
|
|
165
|
+
> `ResourceNotFoundException` rather than a create, which is another difference from EventBridge's
|
|
166
|
+
> `PutRule`.
|
|
167
|
+
|
|
168
|
+
<!-- prose-check:on -->
|
|
169
|
+
|
|
170
|
+
> **After.** The schedule has to exist. Updating one that is absent raises
|
|
171
|
+
> `ResourceNotFoundException`. EventBridge's `PutRule` creates it.
|
|
172
|
+
|
|
173
|
+
## Banned marks
|
|
174
|
+
|
|
175
|
+
Three marks are house rules. The checker fails a file for any occurrence of any of them.
|
|
176
|
+
|
|
177
|
+
- **Em dashes.** None in prose. In LLM prose written without a ban they run at 1.93 per 1000 words
|
|
178
|
+
against a human 0.24. That ban is earned. Replace with a full stop, a comma, or brackets.
|
|
179
|
+
- **Semicolons.** None in prose. This one is consistency and carries no evidence behind it. The
|
|
180
|
+
human corpus uses semicolons more than twice as often as any LLM corpus does. Split the sentence.
|
|
181
|
+
- **Mid-sentence colons.** None in prose. This is a house decision taken against the evidence, and
|
|
182
|
+
worth being clear about. A mid-sentence colon is ordinary English, and at zero tolerance every one
|
|
183
|
+
of the 15 human documents in the corpus fails. It is banned anyway, on the same reasoning as the
|
|
184
|
+
em dash. The construction reads as machine-written whoever wrote it, and the cost of doing without
|
|
185
|
+
it is low. A colon **ending a line** to introduce a list, a code block or the next paragraph is
|
|
186
|
+
exempt and always will be. Documentation cannot be written without it. Only the mid-sentence form
|
|
187
|
+
is banned, and the two are distinguished by whether the colon's object is in the same paragraph.
|
|
188
|
+
|
|
189
|
+
The `- **Term** — description` form in a list is typography, and is exempt.
|
|
190
|
+
|
|
191
|
+
Closing all three at once is the point. Banning the em dash alone moved the same pattern onto
|
|
192
|
+
colons, where nothing was watching for it. A remark with nowhere to hang becomes its own sentence.
|
|
193
|
+
|
|
194
|
+
## Use brackets
|
|
195
|
+
|
|
196
|
+
The largest single gap in the whole study. The human corpus uses parenthetical asides at 6.19 per
|
|
197
|
+
1000 words, the LLM corpus at 0.15. Forty times.
|
|
198
|
+
|
|
199
|
+
Brackets are the missing habit here. They are where a subordinate remark should go once the dash and
|
|
200
|
+
the colon are gone. A qualification, an aside, a unit or a caveat worth one clause goes in brackets,
|
|
201
|
+
the way the Rust Book and the Django docs do on nearly every page.
|
|
202
|
+
|
|
203
|
+
Nothing in the checker measures this (a rule that rewards padding would be worse than no rule), so
|
|
204
|
+
it stays a habit to build by hand. It is the one place where the fix is to add rather than to cut.
|
|
205
|
+
|
|
206
|
+
## Keep one name for one thing
|
|
207
|
+
|
|
208
|
+
Human technical writing names a thing and goes on naming it that. LLM prose reaches for a synonym.
|
|
209
|
+
|
|
210
|
+
Measured as distinct words per 100, averaged across a document, the human corpus sits at 0.628 and
|
|
211
|
+
never exceeds 0.664. The LLM corpus sits at 0.685 and never falls below 0.658. That is the cleanest
|
|
212
|
+
single separation in the whole study, and it is the one that maps most directly onto reader fatigue.
|
|
213
|
+
A new name for an old thing stops the reader to re-resolve what it refers to.
|
|
214
|
+
|
|
215
|
+
So if the thing is a queue, call it the queue every time. Call it the queue, then the message store,
|
|
216
|
+
then the buffer, and the reader pays for each change. The same holds for the identifiers in the code
|
|
217
|
+
being documented.
|
|
218
|
+
|
|
219
|
+
The checker reports this as advisory and never fails a file on it, for two reasons. It scores a
|
|
220
|
+
whole document, and there is no line to go and fix. And it is trivially gamed by padding with
|
|
221
|
+
repeated words, which would move the number the right way while making the prose worse.
|
|
222
|
+
|
|
223
|
+
## Short strings are a different genre
|
|
224
|
+
|
|
225
|
+
Everything above is calibrated on documents of 200 words and more, and the checker refuses to score
|
|
226
|
+
anything shorter. A package description, a plugin listing, a meta description or a card subtitle is
|
|
227
|
+
a different problem, and the rules above get it wrong in both directions.
|
|
228
|
+
|
|
229
|
+
Forty descriptions from long-established npm packages (express, lodash, axios, webpack, eslint and
|
|
230
|
+
the like) were compared against five written by Claude for this repository:
|
|
231
|
+
|
|
232
|
+
| | Human npm | Claude |
|
|
233
|
+
| ------------------------------------------ | ----------- | -------- |
|
|
234
|
+
| Median length | **7 words** | 38 words |
|
|
235
|
+
| Noun phrase followed by a colon and a list | **0 of 40** | 4 of 5 |
|
|
236
|
+
| Three-item list | 2 of 40 | 5 of 5 |
|
|
237
|
+
|
|
238
|
+
Nothing in the human set uses the shape. Not one. So for a short listing string:
|
|
239
|
+
|
|
240
|
+
- **Say what the thing is, in one declarative clause.** "Promise based HTTP client for the browser
|
|
241
|
+
and node.js". "Terminal string styling done right". Seven words is a normal length.
|
|
242
|
+
- **No colon followed by a catalogue.** `Thing for X: doing A, doing B, and doing C` is the shape to
|
|
243
|
+
avoid, and it is the shape Claude reaches for every time. The permission for a list-introducing
|
|
244
|
+
colon in the section above applies to prose, and it stops there.
|
|
245
|
+
- **No three-item list**, however tempting. The finding that triples are a human marker holds for
|
|
246
|
+
prose inside a document, and it inverts here.
|
|
247
|
+
- **Leave out what the thing covers.** The detail belongs in the body, which a listing page renders
|
|
248
|
+
directly underneath. Enumerating in the description says it twice.
|
|
249
|
+
- **Avoid coy abstraction.** "The style rules that turn out not to matter" withholds the content and
|
|
250
|
+
gestures at it. Either name the thing or leave it out.
|
|
251
|
+
|
|
252
|
+
One human description in the forty ran to 37 words. It did it as three separate sentences.
|
|
253
|
+
|
|
254
|
+
## What to leave alone
|
|
255
|
+
|
|
256
|
+
These are the measured non-differences. Acting on them costs effort and makes the prose worse.
|
|
257
|
+
|
|
258
|
+
- **Sentence length.** The LLM corpus averaged 20.9 words per sentence and the human exemplars 19.8.
|
|
259
|
+
Long sentences were equally common in both (10.1% over 32 words against 11.7%). Do not chop
|
|
260
|
+
sentences into fragments for rhythm. The problem is what the clauses are doing, and the count is
|
|
261
|
+
beside the point.
|
|
262
|
+
- **Ordinary vocabulary.** The Django and Go docs use `powerful`, `robust`, `simply` and `crucial`
|
|
263
|
+
ten times more often than the LLM corpus did. The signal lives in sentence shape. Cut a
|
|
264
|
+
promotional **claim** where the text is selling instead of explaining, and leave the vocabulary
|
|
265
|
+
alone.
|
|
266
|
+
- **The rule of three.** In prose, the human exemplars write "X, Y and Z" nearly twice as often as
|
|
267
|
+
the LLM corpus does. The apparent signal came entirely from lists of API names, which are
|
|
268
|
+
legitimate enumerations. Leave triples alone.
|
|
269
|
+
- **Verbless list fragments.** A sentence made of comma-separated noun phrases with no main verb
|
|
270
|
+
("The same construction over and over, every fact trailed by a clause, a fresh synonym where the
|
|
271
|
+
previous term would have done"). This one feels like a tic and measures at 1.0 times the human
|
|
272
|
+
rate. That is as close to no signal as the study found. Django and the Rust Book write them just
|
|
273
|
+
as often. A pile of them in one document is still worth breaking up, for the repetition and not
|
|
274
|
+
for the shape.
|
|
275
|
+
- **Long enumerations.** Four or more comma-separated items in a sentence run at 1.2 times, and five
|
|
276
|
+
or more at 1.4 times. Both sit under the two-times bar.
|
|
277
|
+
- **Parataxis.** The exemplars use it seven times more. Comma-spliced and juxtaposed clauses mark
|
|
278
|
+
the human corpus.
|
|
279
|
+
- **Trailing participles** (`, leaving nothing behind`, `, making it faster`). A well-known
|
|
280
|
+
suspicion that the measurement does not support. The exemplars use them twice as often.
|
|
281
|
+
- **Subordination in general.** Both corpora carry 1.4 clauses per sentence, and trailing
|
|
282
|
+
subordinate clauses separate them by only 1.25×. The tic is the narrow comma-plus-`so` collocation
|
|
283
|
+
on its own.
|
|
284
|
+
- **First person and anecdote.** Do not add either while rewriting. Inventing a voice is a different
|
|
285
|
+
failure.
|
|
286
|
+
|
|
287
|
+
If a passage still reads badly after these patterns are gone, the problem is more likely to be the
|
|
288
|
+
order of the material than the sentences.
|
|
289
|
+
|
|
290
|
+
## Document shape
|
|
291
|
+
|
|
292
|
+
- No preamble. One sentence saying what the page covers, then the first thing the reader came for.
|
|
293
|
+
- Coverage lists ("Available functionality", "What's supported") go at the end, next to Limitations.
|
|
294
|
+
A list that only repeats the headings below it should not be written at all.
|
|
295
|
+
|
|
296
|
+
## The audit pass
|
|
297
|
+
|
|
298
|
+
One pass is never enough. The patterns are reflexes, and they reappear in the replacements. Always
|
|
299
|
+
run a second pass over what has just been written.
|
|
300
|
+
|
|
301
|
+
1. Write the prose.
|
|
302
|
+
2. Run the checker on the file:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
node scripts/prose-check.mjs path/to/file.md
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
That path is relative to this skill's own directory, wherever the skill was installed. Run it from
|
|
309
|
+
there, or prefix it with the directory holding this `SKILL.md`.
|
|
310
|
+
|
|
311
|
+
The checker strips code blocks, counts each pattern per 1000 words, compares against the exemplar
|
|
312
|
+
baseline, and prints the worst sentence for every pattern over threshold. Pass a directory to score
|
|
313
|
+
a whole tree, `--json` for machine-readable output, `--examples 5` for more samples.
|
|
314
|
+
|
|
315
|
+
A page that quotes bad prose deliberately can exclude it with `<!-- prose-check:off -->` and
|
|
316
|
+
`<!-- prose-check:on -->`. This file uses those markers around its own **Before** examples. Use them
|
|
317
|
+
for quoted material only, and never to silence a passage the checker is right about.
|
|
318
|
+
|
|
319
|
+
3. Fix what it reports, then run it again. Aim for rates below `warn` on every pattern. Zero is the
|
|
320
|
+
wrong target. `warn` is the 90th percentile of the human corpus and `fail` sits above its
|
|
321
|
+
maximum. A `warn` means "at the top of the human range" and a `FAIL` means "outside it".
|
|
322
|
+
|
|
323
|
+
Prose that passes the checker can still be bad, and the checker has no opinion about whether the
|
|
324
|
+
content is correct or the page is in a sensible order. It catches the reflexes. Judgement is still
|
|
325
|
+
required for everything else.
|
|
326
|
+
|
|
327
|
+
## Limits
|
|
328
|
+
|
|
329
|
+
It fails to make text pass as human-written, and it should not be sold that way.
|
|
330
|
+
|
|
331
|
+
Six documents were rewritten to satisfy every rule here and then submitted to Pangram, a commercial
|
|
332
|
+
detector. All six were still identified as AI. The mean score moved from 0.87 to 0.79, one document
|
|
333
|
+
scored worse after the rewrite, and two were pinned at the maximum in both states. The same detector
|
|
334
|
+
scored four human control documents at zero. The instrument was working.
|
|
335
|
+
|
|
336
|
+
Style and provenance are different signals. The patterns here are real differences between human and
|
|
337
|
+
LLM technical writing, and closing them makes prose plainer. A classifier keys on something else.
|
|
338
|
+
Anyone who wants concealment is holding the wrong tool, and it is worth saying so plainly to a user
|
|
339
|
+
who asks.
|
|
340
|
+
|
|
341
|
+
## Related skills
|
|
342
|
+
|
|
343
|
+
[`avoid-ai-writing`](https://github.com/conorbronsdon/avoid-ai-writing) (MIT) catalogues about forty
|
|
344
|
+
patterns from a different register. Sycophantic tone, engagement-bait closers, rhetorical-question
|
|
345
|
+
openers, hashtag stuffing, chatbot artifacts and hedge stacking all appear in it. Reach for it when
|
|
346
|
+
the writing is a blog post, a release announcement, landing page copy or a social post. Once
|
|
347
|
+
installed, invoke it as `/avoid-ai-writing:avoid-ai-writing`.
|
|
348
|
+
|
|
349
|
+
The two overlap very little, and both are worth having for that reason. Its catalogue covers none of
|
|
350
|
+
the patterns above, and the corpus measured here scored near zero on its categories before any of
|
|
351
|
+
them were applied.
|
|
352
|
+
|
|
353
|
+
Where they disagree, this skill governs documentation. Its default target for em dashes is zero, and
|
|
354
|
+
the measurement here shows that ban moving the pattern onto colons without removing it. Its own
|
|
355
|
+
`docs` context profile already relaxes the em dash rule, so run it with that profile on anything
|
|
356
|
+
from `docs/`.
|