claude-dev-env 1.48.0 → 1.49.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/audit-rubrics/category_rubrics/category-a-api-contracts.md +72 -0
- package/audit-rubrics/category_rubrics/category-b-selector-engine-compat.md +36 -0
- package/audit-rubrics/category_rubrics/category-c-resource-cleanup.md +35 -0
- package/audit-rubrics/category_rubrics/category-d-scoping-and-ordering.md +35 -0
- package/audit-rubrics/category_rubrics/category-e-dead-code.md +38 -0
- package/audit-rubrics/category_rubrics/category-f-silent-failures.md +38 -0
- package/audit-rubrics/category_rubrics/category-g-bounds-and-overflow.md +38 -0
- package/audit-rubrics/category_rubrics/category-h-security-boundaries.md +40 -0
- package/audit-rubrics/category_rubrics/category-i-concurrency.md +38 -0
- package/audit-rubrics/category_rubrics/category-j-code-rules-compliance.md +46 -0
- package/audit-rubrics/category_rubrics/category-k-codebase-conflicts.md +59 -0
- package/audit-rubrics/category_rubrics/category-l-behavior-equivalence.md +45 -0
- package/audit-rubrics/category_rubrics/category-m-producer-consumer-cardinality.md +44 -0
- package/audit-rubrics/category_rubrics/category-n-test-name-scenario-verifier.md +45 -0
- package/audit-rubrics/prompts/category-a-api-contracts.md +384 -0
- package/audit-rubrics/prompts/category-b-selector-engine-compat.md +401 -0
- package/audit-rubrics/prompts/category-c-resource-cleanup.md +420 -0
- package/audit-rubrics/prompts/category-d-scoping-and-ordering.md +414 -0
- package/audit-rubrics/prompts/category-e-dead-code.md +420 -0
- package/audit-rubrics/prompts/category-f-silent-failures.md +420 -0
- package/audit-rubrics/prompts/category-g-bounds-and-overflow.md +383 -0
- package/audit-rubrics/prompts/category-h-security-boundaries.md +423 -0
- package/audit-rubrics/prompts/category-i-concurrency.md +429 -0
- package/audit-rubrics/prompts/category-j-code-rules-compliance.md +463 -0
- package/audit-rubrics/prompts/category-k-codebase-conflicts.md +328 -0
- package/audit-rubrics/prompts/category-l-behavior-equivalence.md +128 -0
- package/audit-rubrics/prompts/category-m-producer-consumer-cardinality.md +129 -0
- package/audit-rubrics/prompts/category-n-test-name-scenario-verifier.md +132 -0
- package/audit-rubrics/source-material-section-types.md +51 -0
- package/hooks/blocking/plain_language_blocker.py +184 -0
- package/hooks/blocking/pr_description_enforcer.py +21 -1
- package/hooks/blocking/test_plain_language_blocker.py +247 -0
- package/hooks/blocking/test_pr_description_enforcer.py +68 -0
- package/hooks/hooks.json +15 -0
- package/hooks/hooks_constants/plain_language_blocker_constants.py +295 -0
- package/hooks/hooks_constants/pr_description_enforcer_constants.py +4 -0
- package/package.json +2 -1
- package/rules/plain-language.md +2 -0
- package/skills/bugteam/reference/teardown-publish-permissions.md +7 -2
|
@@ -225,6 +225,74 @@ def test_validate_blocks_vague_language() -> None:
|
|
|
225
225
|
assert any("Vague language" in each_violation for each_violation in violations)
|
|
226
226
|
|
|
227
227
|
|
|
228
|
+
def _has_vague_language_violation(all_violations: list[str]) -> bool:
|
|
229
|
+
return any("Vague language" in each_violation for each_violation in all_violations)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def test_vague_language_inside_fenced_code_block_is_exempt() -> None:
|
|
233
|
+
body = (
|
|
234
|
+
"The allocator now bounds retries so a runaway request cannot exhaust the "
|
|
235
|
+
"connection pool under sustained load.\n\n"
|
|
236
|
+
"```bash\ngit commit -m \"fixed bug in parser\"\n```\n"
|
|
237
|
+
)
|
|
238
|
+
assert not _has_vague_language_violation(validate_pr_body(body))
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def test_vague_language_inside_inline_code_span_is_exempt() -> None:
|
|
242
|
+
body = (
|
|
243
|
+
"This change documents the historical commit message `fixed bug` referenced "
|
|
244
|
+
"in the changelog and rewrites the surrounding allocator narrative for clarity.\n"
|
|
245
|
+
)
|
|
246
|
+
assert not _has_vague_language_violation(validate_pr_body(body))
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def test_vague_language_inside_blockquote_line_is_exempt() -> None:
|
|
250
|
+
body = (
|
|
251
|
+
"> The reviewer wrote: minor changes were requested here.\n\n"
|
|
252
|
+
"The allocator rewrite removes the unbounded retry loop and adds a hard ceiling "
|
|
253
|
+
"so a single client cannot starve the pool.\n"
|
|
254
|
+
)
|
|
255
|
+
assert not _has_vague_language_violation(validate_pr_body(body))
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def test_vague_language_inside_markdown_table_is_exempt() -> None:
|
|
259
|
+
body = (
|
|
260
|
+
"The commit-message guide contrasts weak and strong messages so contributors "
|
|
261
|
+
"learn the difference before opening a pull request.\n\n"
|
|
262
|
+
"| Bad message | Good message |\n"
|
|
263
|
+
"| --- | --- |\n"
|
|
264
|
+
"| fixed bug | bound retry loop in allocator |\n"
|
|
265
|
+
"| update code | rename pool field to active_count |\n"
|
|
266
|
+
)
|
|
267
|
+
assert not _has_vague_language_violation(validate_pr_body(body))
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def test_vague_language_in_bare_prose_still_blocks() -> None:
|
|
271
|
+
body = (
|
|
272
|
+
"The allocator rewrite removes the unbounded retry loop and adds a hard "
|
|
273
|
+
"ceiling so a single client cannot starve the pool. Fixed bug in the parser.\n"
|
|
274
|
+
)
|
|
275
|
+
assert _has_vague_language_violation(validate_pr_body(body))
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def test_vague_language_inside_heading_is_exempt() -> None:
|
|
279
|
+
body = (
|
|
280
|
+
"## Fixed bug in the allocator\n\n"
|
|
281
|
+
"The allocator rewrite removes the unbounded retry loop and adds a hard "
|
|
282
|
+
"ceiling so a single client cannot starve the connection pool.\n"
|
|
283
|
+
)
|
|
284
|
+
assert not _has_vague_language_violation(validate_pr_body(body))
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def test_vague_language_in_single_pipe_prose_line_still_blocks() -> None:
|
|
288
|
+
body = (
|
|
289
|
+
"The allocator rewrite removes the unbounded retry loop and adds a hard "
|
|
290
|
+
"ceiling so a single client cannot starve the connection pool.\n\n"
|
|
291
|
+
"| fixed bug\n"
|
|
292
|
+
)
|
|
293
|
+
assert _has_vague_language_violation(validate_pr_body(body))
|
|
294
|
+
|
|
295
|
+
|
|
228
296
|
def test_validate_blocks_short_body() -> None:
|
|
229
297
|
violations = validate_pr_body("Too short.")
|
|
230
298
|
assert any("substantive prose" in each_violation.lower() for each_violation in violations)
|
package/hooks/hooks.json
CHANGED
|
@@ -69,6 +69,11 @@
|
|
|
69
69
|
"type": "command",
|
|
70
70
|
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/blocking/open_questions_in_plans_blocker.py",
|
|
71
71
|
"timeout": 10
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"type": "command",
|
|
75
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/blocking/plain_language_blocker.py",
|
|
76
|
+
"timeout": 10
|
|
72
77
|
}
|
|
73
78
|
]
|
|
74
79
|
},
|
|
@@ -171,6 +176,16 @@
|
|
|
171
176
|
"timeout": 10
|
|
172
177
|
}
|
|
173
178
|
]
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"matcher": "AskUserQuestion",
|
|
182
|
+
"hooks": [
|
|
183
|
+
{
|
|
184
|
+
"type": "command",
|
|
185
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/blocking/plain_language_blocker.py",
|
|
186
|
+
"timeout": 10
|
|
187
|
+
}
|
|
188
|
+
]
|
|
174
189
|
}
|
|
175
190
|
],
|
|
176
191
|
"SessionStart": [
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"""Configuration constants for the plain_language_blocker PreToolUse hook."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
REPLACEMENT_BY_TERM: dict[str, str] = {
|
|
8
|
+
"addressees are requested": "(omit), please",
|
|
9
|
+
"under the provisions of": "under",
|
|
10
|
+
"interpose no objection": "don't object",
|
|
11
|
+
"afford an opportunity": "allow, let",
|
|
12
|
+
"has a requirement for": "needs",
|
|
13
|
+
"is in consonance with": "agrees with, follows",
|
|
14
|
+
"not later than 10 may": "by 10 May, before 11 May",
|
|
15
|
+
"provides guidance for": "guides",
|
|
16
|
+
"successfully complete": "complete, pass",
|
|
17
|
+
"with the exception of": "except for",
|
|
18
|
+
"due to the fact that": "due to, since",
|
|
19
|
+
"effect modifications": "make changes",
|
|
20
|
+
"in view of the above": "so",
|
|
21
|
+
"adversely impact on": "hurt, set back",
|
|
22
|
+
"at the present time": "at present, now",
|
|
23
|
+
"not later than 1600": "by 1600",
|
|
24
|
+
"combat environment": "combat",
|
|
25
|
+
"in a timely manner": "on time, promptly",
|
|
26
|
+
"in accordance with": "by, following, per, under",
|
|
27
|
+
"in the near future": "shortly, soon",
|
|
28
|
+
"is responsible for": "(omit) handles",
|
|
29
|
+
"on a regular basis": "(omit)",
|
|
30
|
+
"until such time as": "until",
|
|
31
|
+
"during the period": "during",
|
|
32
|
+
"in the process of": "(omit)",
|
|
33
|
+
"with reference to": "about",
|
|
34
|
+
"as prescribed by": "in, under",
|
|
35
|
+
"in the amount of": "for",
|
|
36
|
+
"is applicable to": "applies to",
|
|
37
|
+
"is authorized to": "may",
|
|
38
|
+
"state-of-the-art": "latest",
|
|
39
|
+
"close proximity": "near",
|
|
40
|
+
"for a period of": "for",
|
|
41
|
+
"in an effort to": "to",
|
|
42
|
+
"in the event of": "if",
|
|
43
|
+
"it is essential": "must, need to",
|
|
44
|
+
"it is requested": "please, we request, I request",
|
|
45
|
+
"notwithstanding": "inspite of, still",
|
|
46
|
+
"the undersigned": "I",
|
|
47
|
+
"arrive onboard": "arrive",
|
|
48
|
+
"in relation to": "about, with, to",
|
|
49
|
+
"incumbent upon": "must",
|
|
50
|
+
"limited number": "limits",
|
|
51
|
+
"take action to": "(omit)",
|
|
52
|
+
"as a means of": "to",
|
|
53
|
+
"in order that": "for, so",
|
|
54
|
+
"pertaining to": "about, of, on",
|
|
55
|
+
"provided that": "if",
|
|
56
|
+
"this activity": "us, we",
|
|
57
|
+
"advantageous": "helpful",
|
|
58
|
+
"consequently": "so",
|
|
59
|
+
"in regard to": "about, concerning, on",
|
|
60
|
+
"remuneration": "pay, payment",
|
|
61
|
+
"set forth in": "in",
|
|
62
|
+
"subsequently": "after, later, then",
|
|
63
|
+
"the month of": "(omit)",
|
|
64
|
+
"a number of": "some",
|
|
65
|
+
"accordingly": "so",
|
|
66
|
+
"adjacent to": "next to",
|
|
67
|
+
"appreciable": "many",
|
|
68
|
+
"appropriate": "(omit), proper, right",
|
|
69
|
+
"approximate": "about",
|
|
70
|
+
"by means of": "by, with",
|
|
71
|
+
"comply with": "follow",
|
|
72
|
+
"consolidate": "combine, join, merge",
|
|
73
|
+
"constitutes": "is, forms, makes up",
|
|
74
|
+
"demonstrate": "prove, show",
|
|
75
|
+
"discontinue": "drop, stop",
|
|
76
|
+
"disseminate": "give, issue, pass, send",
|
|
77
|
+
"expeditious": "fast, quick",
|
|
78
|
+
"immediately": "at once",
|
|
79
|
+
"in addition": "also, besides, too",
|
|
80
|
+
"in order to": "to",
|
|
81
|
+
"inasmuch as": "since",
|
|
82
|
+
"methodology": "method",
|
|
83
|
+
"necessitate": "cause, need",
|
|
84
|
+
"participate": "take part",
|
|
85
|
+
"practicable": "practical",
|
|
86
|
+
"proficiency": "skill",
|
|
87
|
+
"pursuant to": "by, following, per, under",
|
|
88
|
+
"relative to": "about, on",
|
|
89
|
+
"requirement": "need",
|
|
90
|
+
"substantial": "large, much",
|
|
91
|
+
"time period": "(either one)",
|
|
92
|
+
"utilization": "use",
|
|
93
|
+
"your office": "you",
|
|
94
|
+
"a and/or b": "a or b or both",
|
|
95
|
+
"accomplish": "carry out, do",
|
|
96
|
+
"additional": "added, more, other",
|
|
97
|
+
"addressees": "you",
|
|
98
|
+
"anticipate": "expect",
|
|
99
|
+
"assistance": "aid, help",
|
|
100
|
+
"be advised": "(omit)",
|
|
101
|
+
"capability": "ability",
|
|
102
|
+
"concerning": "about, on",
|
|
103
|
+
"equipments": "equipment",
|
|
104
|
+
"expiration": "end",
|
|
105
|
+
"facilitate": "ease, help",
|
|
106
|
+
"frequently": "often",
|
|
107
|
+
"heretofore": "until now",
|
|
108
|
+
"in lieu of": "instead",
|
|
109
|
+
"in view of": "since",
|
|
110
|
+
"indication": "sign",
|
|
111
|
+
"inter alia": "(omit)",
|
|
112
|
+
"it appears": "seems",
|
|
113
|
+
"parameters": "limits",
|
|
114
|
+
"previously": "before",
|
|
115
|
+
"prioritize": "rank",
|
|
116
|
+
"promulgate": "issue, publish",
|
|
117
|
+
"represents": "is",
|
|
118
|
+
"similar to": "like",
|
|
119
|
+
"subsequent": "later, next",
|
|
120
|
+
"sufficient": "enough",
|
|
121
|
+
"the use of": "(omit)",
|
|
122
|
+
"accompany": "go with",
|
|
123
|
+
"ascertain": "find out, learn",
|
|
124
|
+
"component": "part",
|
|
125
|
+
"currently": "(omit), now",
|
|
126
|
+
"designate": "appoint, choose, name",
|
|
127
|
+
"determine": "decide, figure, find",
|
|
128
|
+
"eliminate": "cut, drop, end",
|
|
129
|
+
"encounter": "meet",
|
|
130
|
+
"enumerate": "count",
|
|
131
|
+
"equitable": "fair",
|
|
132
|
+
"establish": "set up, prove, show",
|
|
133
|
+
"evidenced": "showed",
|
|
134
|
+
"expertise": "ability",
|
|
135
|
+
"failed to": "didn't",
|
|
136
|
+
"identical": "same",
|
|
137
|
+
"implement": "carry out, start",
|
|
138
|
+
"inception": "start",
|
|
139
|
+
"interface": "meet, work with",
|
|
140
|
+
"magnitude": "size",
|
|
141
|
+
"objective": "aim, goal",
|
|
142
|
+
"regarding": "about, of, on",
|
|
143
|
+
"remainder": "rest",
|
|
144
|
+
"selection": "choice",
|
|
145
|
+
"terminate": "end, stop",
|
|
146
|
+
"there are": "(omit)",
|
|
147
|
+
"therefore": "so",
|
|
148
|
+
"witnessed": "saw",
|
|
149
|
+
"accorded": "given",
|
|
150
|
+
"accurate": "correct, exact, right",
|
|
151
|
+
"aircraft": "plane",
|
|
152
|
+
"allocate": "divide",
|
|
153
|
+
"apparent": "clear, plain",
|
|
154
|
+
"combined": "joint",
|
|
155
|
+
"commence": "begin, start",
|
|
156
|
+
"comprise": "form, include, make up",
|
|
157
|
+
"contains": "has",
|
|
158
|
+
"disclose": "show",
|
|
159
|
+
"endeavor": "try",
|
|
160
|
+
"expedite": "hasten, speed up",
|
|
161
|
+
"feasible": "can be done, workable",
|
|
162
|
+
"finalize": "complete, finish",
|
|
163
|
+
"function": "act, role, work",
|
|
164
|
+
"herewith": "below, here",
|
|
165
|
+
"identify": "find, name, show",
|
|
166
|
+
"impacted": "affected, changed",
|
|
167
|
+
"indicate": "show, write down",
|
|
168
|
+
"initiate": "start",
|
|
169
|
+
"maintain": "keep, support",
|
|
170
|
+
"minimize": "decrease, method",
|
|
171
|
+
"numerous": "many",
|
|
172
|
+
"obligate": "bind, compel",
|
|
173
|
+
"preclude": "prevent",
|
|
174
|
+
"previous": "earlier",
|
|
175
|
+
"prior to": "before",
|
|
176
|
+
"purchase": "buy",
|
|
177
|
+
"relocate": "move",
|
|
178
|
+
"there is": "(omit)",
|
|
179
|
+
"transmit": "send",
|
|
180
|
+
"validate": "confirm",
|
|
181
|
+
"address": "discuss",
|
|
182
|
+
"attempt": "try",
|
|
183
|
+
"benefit": "help",
|
|
184
|
+
"command": "us, we",
|
|
185
|
+
"convene": "meet",
|
|
186
|
+
"evident": "clear",
|
|
187
|
+
"exhibit": "show",
|
|
188
|
+
"females": "women",
|
|
189
|
+
"forfeit": "give up, lose",
|
|
190
|
+
"forward": "send",
|
|
191
|
+
"furnish": "give, send",
|
|
192
|
+
"however": "but",
|
|
193
|
+
"initial": "first",
|
|
194
|
+
"liaison": "discussion",
|
|
195
|
+
"maximum": "greatest, largest, most",
|
|
196
|
+
"minimum": "least, smallest",
|
|
197
|
+
"monitor": "check, watch",
|
|
198
|
+
"observe": "see",
|
|
199
|
+
"operate": "run, use, work",
|
|
200
|
+
"optimum": "best, greatest, most",
|
|
201
|
+
"perform": "do",
|
|
202
|
+
"portion": "part",
|
|
203
|
+
"possess": "have, own",
|
|
204
|
+
"proceed": "do, go ahead, try",
|
|
205
|
+
"procure": "(omit)",
|
|
206
|
+
"provide": "give, offer, say",
|
|
207
|
+
"reflect": "say, show",
|
|
208
|
+
"request": "ask",
|
|
209
|
+
"require": "must, need",
|
|
210
|
+
"solicit": "ask for, request",
|
|
211
|
+
"subject": "the, this, your",
|
|
212
|
+
"therein": "there",
|
|
213
|
+
"thereof": "its, their",
|
|
214
|
+
"utilize": "use",
|
|
215
|
+
"warrant": "call for, permit",
|
|
216
|
+
"whereas": "because, since",
|
|
217
|
+
"accrue": "add, gain",
|
|
218
|
+
"advise": "recommend, tell",
|
|
219
|
+
"assist": "aid, help",
|
|
220
|
+
"attain": "meet",
|
|
221
|
+
"caveat": "warning",
|
|
222
|
+
"delete": "cut, drop",
|
|
223
|
+
"depart": "leave",
|
|
224
|
+
"desire": "want, wish",
|
|
225
|
+
"employ": "use",
|
|
226
|
+
"ensure": "make sure",
|
|
227
|
+
"expend": "spend",
|
|
228
|
+
"herein": "here",
|
|
229
|
+
"modify": "change",
|
|
230
|
+
"notify": "let know, tell",
|
|
231
|
+
"option": "choice, way",
|
|
232
|
+
"permit": "let",
|
|
233
|
+
"remain": "stay",
|
|
234
|
+
"render": "give, make",
|
|
235
|
+
"reside": "live",
|
|
236
|
+
"retain": "keep",
|
|
237
|
+
"submit": "give, send",
|
|
238
|
+
"timely": "prompt",
|
|
239
|
+
"viable": "practical, workable",
|
|
240
|
+
"elect": "choose, pick",
|
|
241
|
+
"it is": "(omit)",
|
|
242
|
+
"deem": "believe, consider, think",
|
|
243
|
+
"said": "the, this, that",
|
|
244
|
+
"same": "the, this, that",
|
|
245
|
+
"such": "the, this, that",
|
|
246
|
+
"type": "(omit)",
|
|
247
|
+
"vice": "instead of, versus",
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
ALL_TERM_PATTERNS: list[tuple[re.Pattern[str], str]] = [
|
|
251
|
+
(re.compile(r"\b" + re.escape(each_term) + r"\b", re.IGNORECASE), each_replacement)
|
|
252
|
+
for each_term, each_replacement in REPLACEMENT_BY_TERM.items()
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
ALL_SOFTWARE_TERMS: frozenset[str] = frozenset(
|
|
256
|
+
{
|
|
257
|
+
"command",
|
|
258
|
+
"function",
|
|
259
|
+
"address",
|
|
260
|
+
"parameters",
|
|
261
|
+
"interface",
|
|
262
|
+
"component",
|
|
263
|
+
"monitor",
|
|
264
|
+
"request",
|
|
265
|
+
"validate",
|
|
266
|
+
"however",
|
|
267
|
+
"forward",
|
|
268
|
+
"subject",
|
|
269
|
+
"same",
|
|
270
|
+
"such",
|
|
271
|
+
"said",
|
|
272
|
+
"type",
|
|
273
|
+
"it is",
|
|
274
|
+
"there is",
|
|
275
|
+
"there are",
|
|
276
|
+
}
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
FENCED_CODE_BLOCK_PATTERN: re.Pattern[str] = re.compile(r"```[\s\S]*?```", re.MULTILINE)
|
|
280
|
+
INLINE_CODE_PATTERN: re.Pattern[str] = re.compile(r"`[^`]+`")
|
|
281
|
+
BLOCKQUOTE_LINE_PATTERN: re.Pattern[str] = re.compile(r"^\s*>.*$", re.MULTILINE)
|
|
282
|
+
URL_PATTERN: re.Pattern[str] = re.compile(r"https?://\S+", re.IGNORECASE)
|
|
283
|
+
FILE_PATH_PATTERN: re.Pattern[str] = re.compile(
|
|
284
|
+
r"(?<![\w/\\])(?:[A-Za-z]:[\\/]|~?[\\/]|\.{1,2}[\\/])(?:[\w.\-]+[\\/])*[\w.\-]+"
|
|
285
|
+
r"|(?:[\w.\-]+[\\/])+[\w.\-]+\.[A-Za-z0-9]+"
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
MARKDOWN_EXTENSION: str = ".md"
|
|
289
|
+
ASK_USER_QUESTION_TOOL_NAME: str = "AskUserQuestion"
|
|
290
|
+
ALL_WRITE_EDIT_TOOL_NAMES: frozenset[str] = frozenset({"Write", "Edit", "MultiEdit"})
|
|
291
|
+
|
|
292
|
+
USER_FACING_PLAIN_LANGUAGE_NOTICE: str = (
|
|
293
|
+
"Plain-language check: replace each flagged formal word with the simpler "
|
|
294
|
+
"word named in the reason."
|
|
295
|
+
)
|
|
@@ -19,6 +19,8 @@ HEADING_LINE_PATTERN: re.Pattern[str] = re.compile(r"^#+[ \t].*$", re.MULTILINE)
|
|
|
19
19
|
BOLD_PAIR_PATTERN: re.Pattern[str] = re.compile(r"\*\*([^*]+?)\*\*")
|
|
20
20
|
BULLET_MARKER_PATTERN: re.Pattern[str] = re.compile(r"^\s*[-*+]\s+", re.MULTILINE)
|
|
21
21
|
BLOCKQUOTE_MARKER_PATTERN: re.Pattern[str] = re.compile(r"^\s*>\s+", re.MULTILINE)
|
|
22
|
+
BLOCKQUOTE_LINE_PATTERN: re.Pattern[str] = re.compile(r"^\s*>.*$", re.MULTILINE)
|
|
23
|
+
TABLE_ROW_LINE_PATTERN: re.Pattern[str] = re.compile(r"^\s*\|.*\|.*$", re.MULTILINE)
|
|
22
24
|
LINK_TEXT_PATTERN: re.Pattern[str] = re.compile(r"\[([^\]]+)\]\([^)]+\)")
|
|
23
25
|
WHITESPACE_RUN_PATTERN: re.Pattern[str] = re.compile(r"\s+")
|
|
24
26
|
|
|
@@ -115,6 +117,7 @@ __all__ = [
|
|
|
115
117
|
"ALL_HEAVY_TESTING_HEADERS",
|
|
116
118
|
"ALL_READABILITY_CLI_FLAG_TOKENS",
|
|
117
119
|
"ATOMIC_WRITE_TEMP_SUFFIX",
|
|
120
|
+
"BLOCKQUOTE_LINE_PATTERN",
|
|
118
121
|
"BLOCKQUOTE_MARKER_PATTERN",
|
|
119
122
|
"BOLD_PAIR_PATTERN",
|
|
120
123
|
"BULLET_MARKER_PATTERN",
|
|
@@ -147,6 +150,7 @@ __all__ = [
|
|
|
147
150
|
"SELF_CLOSING_REFERENCE_MESSAGE_SUFFIX",
|
|
148
151
|
"SELF_REFERENCE_PATTERN_TEMPLATE",
|
|
149
152
|
"STANDARD_SHAPE",
|
|
153
|
+
"TABLE_ROW_LINE_PATTERN",
|
|
150
154
|
"THIS_PR_OPENING_PATTERN",
|
|
151
155
|
"TRIVIAL_BODY_CHAR_THRESHOLD",
|
|
152
156
|
"TRIVIAL_SHAPE",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-dev-env",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.49.1",
|
|
4
4
|
"description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"system-prompts/",
|
|
21
21
|
"scripts/",
|
|
22
22
|
"_shared/",
|
|
23
|
+
"audit-rubrics/",
|
|
23
24
|
"CLAUDE.md"
|
|
24
25
|
],
|
|
25
26
|
"keywords": [
|
package/rules/plain-language.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**When this applies:** All prose you write — chat responses, `AskUserQuestion` questions and options, documentation and Markdown, PR and issue bodies, and commit messages. Anything a person reads.
|
|
4
4
|
|
|
5
|
+
**Hook enforcement:** `plain_language_blocker` (PreToolUse on `AskUserQuestion` and on Write|Edit|MultiEdit of `.md` targets) blocks a heavy word and names the everyday word to swap in. Code fences, inline code, blockquotes, URLs, and file paths are skipped so exact identifiers stay untouched. See `hooks.json` for registration.
|
|
6
|
+
|
|
5
7
|
## Rule
|
|
6
8
|
|
|
7
9
|
Write so the reader understands it on the first pass, without hunting for extra context and without wading through more than the point requires. Favor everyday words, short sentences, and concrete phrasing. This is **plain language** (ISO 24495-1:2023; U.S. Plain Writing Act of 2010) — clear writing, not dumbed-down writing.
|
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Utility scripts (progressive disclosure)
|
|
4
4
|
|
|
5
|
-
Fragile or repeatable shell sequences
|
|
5
|
+
Fragile or repeatable shell sequences live in one of two shared script directories. Match the reference depth to the directory:
|
|
6
|
+
|
|
7
|
+
- **Package-root** [`_shared/pr-loop/scripts/`](../../../_shared/pr-loop/scripts/) holds `code_rules_gate.py`, `preflight.py`, `post_audit_thread.py`, and the permission helpers. Reference it as `../../../_shared/…` in markdown and `${CLAUDE_SKILL_DIR}/../../_shared/…` at runtime (resolves to `~/.claude/_shared/`). Inventory: [`../../../_shared/pr-loop/scripts/README.md`](../../../_shared/pr-loop/scripts/README.md).
|
|
8
|
+
- **Skill-tree** [`skills/_shared/pr-loop/scripts/`](../../_shared/pr-loop/scripts/) holds `teardown_worktrees.py`, `build_audit_prompt.py`, `build_fix_prompt.py`, `init_loop_state.py`, `write_audit_outcomes.py`, `write_fix_outcomes.py`, and `_path_resolver.py`. Reference it as `../../_shared/…` in markdown and `${CLAUDE_SKILL_DIR}/../_shared/…` at runtime (resolves to `~/.claude/skills/_shared/`).
|
|
9
|
+
|
|
10
|
+
Bugteam-specific scripts (e.g. revoke, see Step 5) live in the skill-local [`scripts/`](../scripts/) directory. Anthropic: [Progressive disclosure patterns](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#progressive-disclosure-patterns) — utility scripts are **executed**, not loaded into context as primary reading. Bugteam-script inventory: [`../scripts/README.md`](../scripts/README.md). Gate-only merge-base / diff semantics: [`../../../_shared/pr-loop/code-rules-gate.md`](../../../_shared/pr-loop/code-rules-gate.md).
|
|
6
11
|
|
|
7
12
|
### Pre-flight (recommended before Step 0)
|
|
8
13
|
|
|
@@ -19,7 +24,7 @@ When the cycle exits (any reason), run these steps in order from **this** sessio
|
|
|
19
24
|
directory (Windows-safe `shutil.rmtree`):
|
|
20
25
|
|
|
21
26
|
```bash
|
|
22
|
-
python "${CLAUDE_SKILL_DIR}
|
|
27
|
+
python "${CLAUDE_SKILL_DIR}/../_shared/pr-loop/scripts/teardown_worktrees.py" \
|
|
23
28
|
--run-temp-dir "<run_temp_dir>" \
|
|
24
29
|
--all-pr-jsons '<json array of {number, owner, repo}>'
|
|
25
30
|
```
|