@assuredloop/orca-bot-kit 0.1.0 → 0.2.0
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/LICENSE +21 -0
- package/README.md +545 -3
- package/SETUP.md +270 -0
- package/package.json +32 -13
- package/rules/evidence.md +15 -0
- package/rules/finishing.md +20 -0
- package/rules/limits.md +18 -0
- package/rules/mail.md +17 -0
- package/rules/profiles.md +9 -0
- package/rules/review.md +14 -0
- package/rules/scope.md +20 -0
- package/rules/simple.md +14 -0
- package/rules/talk.md +13 -0
- package/rules/tests-first.md +15 -0
- package/rules/the-ask.md +19 -0
- package/skills/obk-arch/LICENSES.md +45 -0
- package/skills/obk-arch/NOTICE.md +134 -0
- package/skills/obk-arch/SKILL.md +387 -0
- package/skills/obk-bot-building/LICENSES.md +21 -0
- package/skills/obk-bot-building/NOTICE.md +113 -0
- package/skills/obk-bot-building/SKILL.md +235 -0
- package/skills/obk-debugging/LICENSES.md +67 -0
- package/skills/obk-debugging/NOTICE.md +115 -0
- package/skills/obk-debugging/SKILL.md +419 -0
- package/skills/obk-decision-memo/LICENSES.md +49 -0
- package/skills/obk-decision-memo/NOTICE.md +181 -0
- package/skills/obk-decision-memo/SKILL.md +241 -0
- package/skills/obk-finops/LICENSES.md +19 -0
- package/skills/obk-finops/NOTICE.md +77 -0
- package/skills/obk-finops/SKILL.md +146 -0
- package/skills/obk-fleet-review/LICENSES.md +52 -0
- package/skills/obk-fleet-review/NOTICE.md +104 -0
- package/skills/obk-fleet-review/SKILL.md +219 -0
- package/skills/obk-grilling/LICENSES.md +42 -0
- package/skills/obk-grilling/NOTICE.md +103 -0
- package/skills/obk-grilling/SKILL.md +217 -0
- package/skills/obk-grooming/LICENSES.md +52 -0
- package/skills/obk-grooming/NOTICE.md +111 -0
- package/skills/obk-grooming/SKILL.md +219 -0
- package/skills/obk-handoff/LICENSES.md +45 -0
- package/skills/obk-handoff/NOTICE.md +51 -0
- package/skills/obk-handoff/SKILL.md +119 -0
- package/skills/obk-personal-facilitation/LICENSES.md +53 -0
- package/skills/obk-personal-facilitation/NOTICE.md +62 -0
- package/skills/obk-personal-facilitation/SKILL.md +86 -0
- package/skills/obk-recall/LICENSES.md +42 -0
- package/skills/obk-recall/NOTICE.md +53 -0
- package/skills/obk-recall/SKILL.md +129 -0
- package/skills/obk-researching/LICENSES.md +67 -0
- package/skills/obk-researching/NOTICE.md +170 -0
- package/skills/obk-researching/SKILL.md +259 -0
- package/skills/obk-reviewing/LICENSES.md +66 -0
- package/skills/obk-reviewing/NOTICE.md +58 -0
- package/skills/obk-reviewing/SKILL.md +408 -0
- package/skills/obk-tdd/LICENSES.md +68 -0
- package/skills/obk-tdd/NOTICE.md +54 -0
- package/skills/obk-tdd/SKILL.md +516 -0
- package/skills/obk-tdd/mutation-tools.md +80 -0
- package/skills/obk-teach/LICENSES.md +42 -0
- package/skills/obk-teach/NOTICE.md +65 -0
- package/skills/obk-teach/SKILL.md +106 -0
- package/skills/obk-why/LICENSES.md +42 -0
- package/skills/obk-why/NOTICE.md +74 -0
- package/skills/obk-why/SKILL.md +169 -0
- package/skills/obk-writing/LICENSES.md +272 -0
- package/skills/obk-writing/NOTICE.md +161 -0
- package/skills/obk-writing/SKILL.md +254 -0
- package/src/book.js +268 -0
- package/src/bot.js +451 -0
- package/src/cli.js +1130 -0
- package/src/conversations.js +150 -0
- package/src/groom.js +157 -0
- package/src/health.js +309 -0
- package/src/hooks.js +202 -0
- package/src/init.js +314 -0
- package/src/launch.js +276 -0
- package/src/message.js +380 -0
- package/src/orca.js +291 -0
- package/src/pause.js +58 -0
- package/src/record.js +209 -0
- package/src/restart.js +192 -0
- package/src/retire.js +92 -0
- package/src/roster.js +71 -0
- package/src/rules.js +408 -0
- package/src/skills.js +629 -0
- package/src/sources.js +370 -0
- package/src/up.js +475 -0
- package/src/usage.js +401 -0
- package/bin/okb.js +0 -4
- package/src/index.js +0 -11
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: obk-reviewing
|
|
3
|
+
description: >-
|
|
4
|
+
Reviewing a change, and receiving a review of your own: what a reviewer is
|
|
5
|
+
given and what it is not, the angles worth taking on a diff, the test to put
|
|
6
|
+
a finding through before writing it, the findings that are usually wrong,
|
|
7
|
+
what a report says, and how to answer one without performing agreement. Use
|
|
8
|
+
whenever you are reading someone else's change (a diff, a branch, a pull
|
|
9
|
+
request, a patch) or have been asked to look at, check over or give an
|
|
10
|
+
opinion on work you did not write, and equally whenever findings come back
|
|
11
|
+
on your own work and you have to decide what to do about each one.
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Reviewing
|
|
15
|
+
|
|
16
|
+
Two jobs, and they are different: reading someone else's change, and answering
|
|
17
|
+
a reading of your own. A review is worth having only when the reader did not
|
|
18
|
+
write the code, and it is worth acting on only when each finding survives being
|
|
19
|
+
checked.
|
|
20
|
+
|
|
21
|
+
The reviewer comments and does not edit. Whoever wrote the code makes the
|
|
22
|
+
change, and the check is run again afterwards.
|
|
23
|
+
|
|
24
|
+
Scale the reading to the change. A review is not skipped because the work is
|
|
25
|
+
small, but a small change gets a small review: the questions that could matter
|
|
26
|
+
here, not the whole list every time. Formality repeated on every change costs
|
|
27
|
+
trust as surely as missing a defect does.
|
|
28
|
+
|
|
29
|
+
Question the approach before the edge cases. If the change solves the problem
|
|
30
|
+
in the wrong place, or solves the wrong problem, the boundary conditions inside
|
|
31
|
+
it are beside the point; settle the shape first and look at the details after.
|
|
32
|
+
|
|
33
|
+
These are defaults for work where nothing says otherwise. A user who asks for
|
|
34
|
+
something else gets what they asked for; say which of these you left and why.
|
|
35
|
+
|
|
36
|
+
## Giving a review
|
|
37
|
+
|
|
38
|
+
### What you are given, and what you are not
|
|
39
|
+
|
|
40
|
+
The requirement, the change, and the criteria it has to meet. Not the author's
|
|
41
|
+
session, not its reasoning, and not its conclusion: handed a conclusion, a
|
|
42
|
+
reader tends to come back agreeing with it. If you are the one asking for the
|
|
43
|
+
review, pass the artefact and the contract, and keep your verdict to yourself.
|
|
44
|
+
|
|
45
|
+
State the intent in one paragraph before you read the diff, taken from the
|
|
46
|
+
requirement rather than from the author's summary. You are judging whether the
|
|
47
|
+
change achieves that intent, not whether the intent was right. Solving the
|
|
48
|
+
wrong problem is still a finding. That is the change failing the requirement,
|
|
49
|
+
not you re-arguing it. A breakage the change sets out to make (an interface
|
|
50
|
+
retired on purpose, a behaviour deliberately dropped) is not a defect; do not
|
|
51
|
+
spend the author's time on it.
|
|
52
|
+
|
|
53
|
+
Pin what you are reading: the range, and that it resolves and is not empty.
|
|
54
|
+
Work that out before you start rather than half way through.
|
|
55
|
+
|
|
56
|
+
Read the change before you read what anyone else said about it. Other people's
|
|
57
|
+
comments, and any automated review, come after your own pass, so your eyes are
|
|
58
|
+
your own.
|
|
59
|
+
|
|
60
|
+
### The author's report is a claim
|
|
61
|
+
|
|
62
|
+
Treat it as a claim about the code, not as evidence. It may be incomplete,
|
|
63
|
+
optimistic, or simply wrong. Check what it says against the change itself. A
|
|
64
|
+
rationale in the report ("left out deliberately", "kept simple on purpose")
|
|
65
|
+
is the author grading its own work and never lowers the severity of anything
|
|
66
|
+
you find.
|
|
67
|
+
|
|
68
|
+
The other way round holds too: evidence you cannot see is not evidence that
|
|
69
|
+
does not exist. When you cannot check something, say that you could not, and
|
|
70
|
+
say what would settle it.
|
|
71
|
+
|
|
72
|
+
### Two questions, kept apart
|
|
73
|
+
|
|
74
|
+
Does the change do what was asked, and is it well made? A change can pass one
|
|
75
|
+
and fail the other: correct in every detail and solving the wrong problem, or
|
|
76
|
+
exactly what was wanted and a mess in the codebase. Answer them separately and
|
|
77
|
+
report them separately. Merged into one ranked list, the loud one hides the
|
|
78
|
+
other.
|
|
79
|
+
|
|
80
|
+
For the first, go through the requirement and sort what you find into three:
|
|
81
|
+
|
|
82
|
+
- **Missing.** Asked for and not there, or claimed and not implemented.
|
|
83
|
+
- **Not asked for.** Behaviour, options or generality nobody wanted.
|
|
84
|
+
- **Misunderstood.** The right thing built the wrong way, or the wrong
|
|
85
|
+
problem solved.
|
|
86
|
+
|
|
87
|
+
Quote the line of the requirement for each. Where settling one means reading
|
|
88
|
+
code the change does not touch (the function it delegates to, the contract it
|
|
89
|
+
relies on), read it: that is evidence about this change, not a review of
|
|
90
|
+
something else. And the requirement is not a list of everything that matters:
|
|
91
|
+
what a reasonable person would expect is part of it, and silence about an input
|
|
92
|
+
is not permission for that input to break things.
|
|
93
|
+
|
|
94
|
+
### Where to look
|
|
95
|
+
|
|
96
|
+
The second question. What you report is the change: what it adds or alters, and
|
|
97
|
+
a defect in an untouched line of a function it touched. Not a survey of
|
|
98
|
+
everything around it.
|
|
99
|
+
|
|
100
|
+
What you read to get there is a different matter. Follow a question you can
|
|
101
|
+
name (where does this value come from, what did the old contract promise, who
|
|
102
|
+
calls this) until it is settled or you are genuinely stuck, and say in the
|
|
103
|
+
report what you followed and what you found. Do not report a half-answer you
|
|
104
|
+
could have finished: "this breaks unless the caller handles it" is not a
|
|
105
|
+
finding when the caller is there to be read. What you must not do is wander:
|
|
106
|
+
reading with no question in hand turns a review of this change into a review of
|
|
107
|
+
the codebase, and that is the thing to stay out of.
|
|
108
|
+
|
|
109
|
+
These are questions, not a list to complete. A one-line fix does not need
|
|
110
|
+
paragraphs about the architecture.
|
|
111
|
+
|
|
112
|
+
- **Every line.** What input, state, timing or platform makes this line wrong?
|
|
113
|
+
Empty input, a boundary, a value that is absent, two of these at once, the
|
|
114
|
+
second time it runs.
|
|
115
|
+
- **The second run, and the half-finished one.** What happens if this runs
|
|
116
|
+
twice, or if the last attempt died partway through? If the answer depends on
|
|
117
|
+
what was left behind, something is missing that puts it back in order.
|
|
118
|
+
- **Two at once.** Where more than one actor can touch the same file, branch or
|
|
119
|
+
shared value, is the access made safe by the structure (a lock, a sequence,
|
|
120
|
+
one owner) or by a convention that will not hold?
|
|
121
|
+
- **Checked against the real thing.** Does the code establish what it claims,
|
|
122
|
+
or does it read a stand-in for it: a timestamp instead of the value, a cached
|
|
123
|
+
flag instead of the state, a helper's summary instead of what the helper
|
|
124
|
+
produced?
|
|
125
|
+
- **What the change took away.** For each line deleted or replaced, name the
|
|
126
|
+
behaviour it was holding up, then find where that behaviour is held up now.
|
|
127
|
+
This is the one most reviews miss.
|
|
128
|
+
- **The callers.** A changed function reaches its call sites: a new
|
|
129
|
+
precondition, a different return shape, an error that did not use to come
|
|
130
|
+
out, a new dependency on ordering or timing.
|
|
131
|
+
- **The cause, not the symptom.** A guard that hides a broken invariant, a
|
|
132
|
+
retry that covers a broken contract, a cast that silences a modelling
|
|
133
|
+
mistake. A special case layered onto shared machinery usually means the fix
|
|
134
|
+
went in at the wrong depth. If the fix is a comment telling the next person
|
|
135
|
+
not to do something, ask what would make the wrong thing impossible instead.
|
|
136
|
+
- **The shape.** Does the change read as though the design always allowed for
|
|
137
|
+
it, or as though it was pushed in from outside? Does the data match how it is
|
|
138
|
+
actually used? Is a second path being kept alive for callers that do not
|
|
139
|
+
exist?
|
|
140
|
+
- **What could be less.** An abstraction with one caller, an option for a case
|
|
141
|
+
nobody has, a parameter nothing passes, a compatibility path whose migration
|
|
142
|
+
is over, a helper the codebase already has written out again by hand. Do
|
|
143
|
+
not mark simple code down for not being abstract: a few lines repeated beat
|
|
144
|
+
an abstraction invented too early.
|
|
145
|
+
- **The tests.** Is there a test for what changed, and would it fail if the
|
|
146
|
+
code were wrong? Where a separate author wrote them, is every test the
|
|
147
|
+
hand-over names in the revision being handed on, as the author wrote it?
|
|
148
|
+
Look at the revision, not only the diff, since the tests may have landed in
|
|
149
|
+
an earlier change this one builds on. A named test that is not there, or is
|
|
150
|
+
there with its assertions softened, is a finding. For a bug, is there a test that
|
|
151
|
+
reproduces it? Was there a failing run before the code, or only a green one
|
|
152
|
+
after? Do the tests observe behaviour or repeat the implementation? And look
|
|
153
|
+
for green that was bought: a threshold moved, a test skipped or deleted,
|
|
154
|
+
assertions taken out of a test that stayed, a check switched off by a
|
|
155
|
+
comment, a value hard-coded to match one test's input. Tightening the bar is
|
|
156
|
+
quiet; loosening it should not be.
|
|
157
|
+
- **The repo's own rules.** Flag a breach only when you can quote the rule and
|
|
158
|
+
the line that breaks it. Not a style you prefer, and not the spirit of a
|
|
159
|
+
document. Skip anything the project's own tooling already enforces.
|
|
160
|
+
- **Security**, only where you can follow it: an input, the path it takes, and
|
|
161
|
+
the place it lands. "This could be an injection" without that path is not a
|
|
162
|
+
finding. Worth following: a new way in with no check on who may use it; a
|
|
163
|
+
secret that reaches a log, an error or a message; a check made at one moment
|
|
164
|
+
and relied on at a later one, when the answer can change in between; and
|
|
165
|
+
whether a value is checked once where it enters and trusted after, or checked
|
|
166
|
+
again and again in the middle and never at the edge.
|
|
167
|
+
- **What it breaks for the people working on it.** A change to where a secret
|
|
168
|
+
is read from, the name of a setting, a port, or a step that now has to be run
|
|
169
|
+
before anything works, will stop other people's machines. So will a feature
|
|
170
|
+
reaching someone it was meant to be hidden from, which is usually a quiet
|
|
171
|
+
change to a condition rather than a loud one.
|
|
172
|
+
|
|
173
|
+
### A baseline when the repo documents nothing
|
|
174
|
+
|
|
175
|
+
What the project writes down about how code should be written is the standard,
|
|
176
|
+
and it wins. On top of it, this set carries where nothing is written down. Each
|
|
177
|
+
one reads as what it is, then what to do about it, and each is a label you
|
|
178
|
+
apply with judgement: "possible feature envy", never a violation. A documented
|
|
179
|
+
repo standard that endorses something here suppresses it, and anything the
|
|
180
|
+
project's tooling already enforces is not a finding.
|
|
181
|
+
|
|
182
|
+
- **Mysterious name.** A function, variable or type whose name does not say
|
|
183
|
+
what it does or holds. → Rename it; if no honest name comes, the design is
|
|
184
|
+
the murky part.
|
|
185
|
+
- **Duplicated code.** The same shape of logic in more than one place in the
|
|
186
|
+
change. → Pull the shape out and call it from both.
|
|
187
|
+
- **Feature envy.** A function that reaches into another object's data more
|
|
188
|
+
than its own. → Move it onto the data it envies.
|
|
189
|
+
- **Data clumps.** The same few fields or parameters keep travelling together,
|
|
190
|
+
a type waiting to be born. → Bundle them and pass the one thing.
|
|
191
|
+
- **Primitive obsession.** A string or a number standing in for a domain idea
|
|
192
|
+
that deserves its own type. → Give the idea its own small type.
|
|
193
|
+
- **Repeated switches.** The same branch on the same kind of thing recurring
|
|
194
|
+
across the change. → One map both sites share, or let the type decide.
|
|
195
|
+
- **Shotgun surgery.** One logical change forcing scattered edits across many
|
|
196
|
+
files. → Gather what changes together into one place.
|
|
197
|
+
- **Divergent change.** One file edited for several unrelated reasons. → Split
|
|
198
|
+
it, so each part changes for one reason.
|
|
199
|
+
- **Speculative generality.** Abstraction, parameters or hooks for needs the
|
|
200
|
+
requirement does not have. → Delete it; inline it back until a real need
|
|
201
|
+
turns up.
|
|
202
|
+
- **Message chains.** Long `a.b().c().d()` navigation the caller should not
|
|
203
|
+
have to know about. → Hide the walk behind one method on the first object.
|
|
204
|
+
- **Middle man.** A class or function that mostly passes calls onward. → Cut
|
|
205
|
+
it out and call the real target.
|
|
206
|
+
- **Refused bequest.** Something that inherits and then ignores or overrides
|
|
207
|
+
most of what it got. → Drop the inheritance and compose instead.
|
|
208
|
+
|
|
209
|
+
### Before you write a finding
|
|
210
|
+
|
|
211
|
+
Four questions. If any answer is no or unsure, the finding drops or its
|
|
212
|
+
severity does.
|
|
213
|
+
|
|
214
|
+
1. Can you name the file and the line? "Somewhere in the parsing" is not
|
|
215
|
+
something anyone can act on.
|
|
216
|
+
2. Can you state the failure concretely: this input, in this state, gives that
|
|
217
|
+
wrong outcome? If you cannot name the trigger, you are matching a pattern,
|
|
218
|
+
not reviewing. A cleanup finding (a smell, a breached rule, something that
|
|
219
|
+
could be less) has no trigger; it names its concrete cost instead: what is
|
|
220
|
+
duplicated, wasted or harder to change, or which rule it breaks.
|
|
221
|
+
3. Have you read what is around it: the callers, the types, the tests? Much of
|
|
222
|
+
what looks wrong is already handled one frame up.
|
|
223
|
+
4. Is the severity one you could defend? A missing comment is never urgent.
|
|
224
|
+
Inflated severity costs you the next review as well as this one.
|
|
225
|
+
|
|
226
|
+
Trace it before you flag it. "This could be nil" becomes a finding when you can
|
|
227
|
+
show the call that makes it nil. Where a type or a validated boundary already
|
|
228
|
+
rules it out, it is not one.
|
|
229
|
+
|
|
230
|
+
Put each candidate in one of three states and say which:
|
|
231
|
+
|
|
232
|
+
- **Confirmed.** You can name the input and the wrong result, and quote the
|
|
233
|
+
line.
|
|
234
|
+
- **Plausible.** The mechanism is real but you cannot reach the trigger from
|
|
235
|
+
here. Say what would settle it. A realistic state is not a reason to refute:
|
|
236
|
+
two things running at once, an absent value on a rare path that can still be
|
|
237
|
+
reached (an error handler, a cold cache, an optional field), zero read as
|
|
238
|
+
missing, a boundary the code does not exclude, a retry after a partial
|
|
239
|
+
failure, a pattern that lost its anchor.
|
|
240
|
+
- **Refuted.** Drop it, and only call it that when the code proves it: the
|
|
241
|
+
line says otherwise, a type or constant makes it impossible, or a guard in
|
|
242
|
+
the change already handles it.
|
|
243
|
+
|
|
244
|
+
Finding and judging are two steps, and collapsing them is how real defects get
|
|
245
|
+
lost. While you are looking, keep anything you can name a failure for. Judge
|
|
246
|
+
afterwards. What reaches the report is what survived.
|
|
247
|
+
|
|
248
|
+
### What a report says
|
|
249
|
+
|
|
250
|
+
Every line is a verdict, a finding, or a check you ran. Start with the answer.
|
|
251
|
+
No preamble, no narration of your process, no closing summary.
|
|
252
|
+
|
|
253
|
+
A finding gives its location, what is wrong, and the evidence for it: why you
|
|
254
|
+
believe it, not just that you do. A concrete alternative if you have one, and
|
|
255
|
+
nothing if you do not. Fold repeats together: "five handlers swallow the error"
|
|
256
|
+
is one finding, not five.
|
|
257
|
+
|
|
258
|
+
- No findings is a real result. A clean review is a valid review, and
|
|
259
|
+
manufacturing findings to justify having looked is the failure that makes
|
|
260
|
+
reviewers worth ignoring.
|
|
261
|
+
- Do not restate what the code does, suggest rewriting working code because you
|
|
262
|
+
would have written it differently, raise a case you cannot reach, or pad with
|
|
263
|
+
small points to look thorough. Do not praise it either; that is not what the
|
|
264
|
+
reader needs.
|
|
265
|
+
- Say what severity means where you are writing, and keep to it. A useful
|
|
266
|
+
line: it matters when the work cannot be trusted until it is fixed (wrong
|
|
267
|
+
or fragile behaviour, a requirement missed, the same block of logic copied
|
|
268
|
+
verbatim, an error swallowed, a test that asserts nothing). "The coverage
|
|
269
|
+
could be broader" and polish are the other kind.
|
|
270
|
+
- Severity never exceeds what you showed, and it does not fall below it
|
|
271
|
+
either: a real defect written up as a suggestion is lost as surely as one
|
|
272
|
+
left out. If you demonstrated a way to read a
|
|
273
|
+
value that should not be read, that is what it is worth; it does not become
|
|
274
|
+
urgent because of what someone might do next with it.
|
|
275
|
+
- One structural problem and ten small ones: the structural problem is the
|
|
276
|
+
review. Correctness outranks cleanup when something has to be cut.
|
|
277
|
+
- If the list of things to act on runs past about five, you have probably not
|
|
278
|
+
finished filtering.
|
|
279
|
+
- List what you considered and set aside, one line each with the reason, so
|
|
280
|
+
nothing is dropped silently. An empty list is fine and means you set nothing
|
|
281
|
+
aside.
|
|
282
|
+
- Say what you did not check. If you looked less thoroughly than you were asked
|
|
283
|
+
to (one pass where more was wanted, a part of the change you could not read),
|
|
284
|
+
say that plainly, so nobody takes the review for more than it is.
|
|
285
|
+
- A review reads the change. Whether the whole of it runs is a separate check;
|
|
286
|
+
where one focused test would settle a doubt and changes nothing, run it and
|
|
287
|
+
say so.
|
|
288
|
+
|
|
289
|
+
### Findings that are usually wrong
|
|
290
|
+
|
|
291
|
+
Before writing one of these, do the thing in brackets.
|
|
292
|
+
|
|
293
|
+
- "Add error handling here" [check whether the caller or the framework already
|
|
294
|
+
does].
|
|
295
|
+
- "This input is not validated" on something internal [follow one caller and
|
|
296
|
+
see what reaches it].
|
|
297
|
+
- "Magic number" for a number everyone knows [ask whether naming it helps a
|
|
298
|
+
reader who already knows it].
|
|
299
|
+
- "This function is too long" for a table, a switch or a list of cases [length
|
|
300
|
+
is not the same as complexity].
|
|
301
|
+
- "Possible null" where a guard or a type is in scope [read the scope].
|
|
302
|
+
- "This is N+1" over a fixed, small set [count it].
|
|
303
|
+
- "Missing await" where not waiting is the point [check whether the result is
|
|
304
|
+
wanted].
|
|
305
|
+
- "Hard-coded value" in a test [a test is supposed to hard-code what it
|
|
306
|
+
expects].
|
|
307
|
+
|
|
308
|
+
The question that settles most of them: would someone who knows this codebase
|
|
309
|
+
actually change the code because of this comment?
|
|
310
|
+
|
|
311
|
+
### One reviewer
|
|
312
|
+
|
|
313
|
+
Do the review yourself rather than handing parts of it on. If the change really
|
|
314
|
+
is too large to hold in one reading, that is itself worth saying.
|
|
315
|
+
|
|
316
|
+
Reviewing is read-only. Do not change the working tree, the index, or which
|
|
317
|
+
branch or commit is checked out. Look with the commands that only read. If you
|
|
318
|
+
need another revision to compare, take a separate copy of it somewhere else.
|
|
319
|
+
|
|
320
|
+
## Receiving a review
|
|
321
|
+
|
|
322
|
+
Read all of it before you react. Then take the items one at a time.
|
|
323
|
+
|
|
324
|
+
**Restate each in your own words.** Go through the whole review first and ask
|
|
325
|
+
about every item you are unsure of, in one go, before you start changing
|
|
326
|
+
anything. Never guess at an unclear item and never act on a half-understood
|
|
327
|
+
one: that produces the wrong change, and then a second wrong change when the
|
|
328
|
+
answer arrives.
|
|
329
|
+
|
|
330
|
+
Items are related more often than they look, so assume the answer to one bears
|
|
331
|
+
on the others until you have checked. Where you have checked and an item plainly
|
|
332
|
+
stands alone (a crash with a reproduction, while the unclear item is a vague
|
|
333
|
+
note about tidying something up), that one can go ahead. Anything the answer
|
|
334
|
+
could change waits for it.
|
|
335
|
+
|
|
336
|
+
**Check it against the code before you act on it.** Is it right for this
|
|
337
|
+
codebase? Does it break something that works? Is there a reason the code is the
|
|
338
|
+
way it is? A fresh reader has less context, not more. That is the point of it,
|
|
339
|
+
and it is also its weakness. Do not defer to a finding because it is fresh, and
|
|
340
|
+
do not dismiss one because it is uncomfortable.
|
|
341
|
+
|
|
342
|
+
**Sort each item**, in this order. Misread: the reader flagged it because what
|
|
343
|
+
you gave them was unclear or incomplete, so fix the brief first and look at the
|
|
344
|
+
item again. Valid: it stands, and gets a change. A trade-off: real, but fixing
|
|
345
|
+
it costs more than living with it, so write it down where the user will see
|
|
346
|
+
it. Or noise: correct under context the reader did not have, and the useful
|
|
347
|
+
question is whether the brief should have said something that would have
|
|
348
|
+
prevented it.
|
|
349
|
+
|
|
350
|
+
Some findings carry a sign that the reader was working without something you
|
|
351
|
+
have: a change asked for in code you did not touch, a pattern flagged that the
|
|
352
|
+
rest of the codebase already uses, an approach recommended that a constraint
|
|
353
|
+
you know about rules out. Treat that as a reason to look, not as an answer. It
|
|
354
|
+
is often an honest mistake from someone with less context, and it is just as
|
|
355
|
+
often the finding that matters most: a caller you did not touch is exactly
|
|
356
|
+
where a changed return shape breaks, and the same unsafe pattern elsewhere says
|
|
357
|
+
nothing about whether this use of it is safe.
|
|
358
|
+
|
|
359
|
+
So check it out, and dismiss it only on what the code, the contract or a
|
|
360
|
+
decision you can point to actually shows. "The reviewer did not know about X"
|
|
361
|
+
dismisses the finding once you have said what X is and why it settles this
|
|
362
|
+
case; on its own it is not a reason. Say that much, and move on without making
|
|
363
|
+
a point of it.
|
|
364
|
+
|
|
365
|
+
A plausible finding about correctness, security, privacy, lost data, who is
|
|
366
|
+
allowed to do what, money, a data migration, or whether something can safely
|
|
367
|
+
run twice is fixed; it needs nobody's leave. Ask rather than decide when such a
|
|
368
|
+
finding is one you would dismiss and it is novel, or when you cannot tell.
|
|
369
|
+
Passing over a noisy remark about style costs little; passing over one of
|
|
370
|
+
those costs a great deal. When in doubt about dismissing one, ask.
|
|
371
|
+
|
|
372
|
+
Where someone suggests building something out "properly", look first for who
|
|
373
|
+
calls it. If nothing does, say so and ask whether it should exist at all.
|
|
374
|
+
|
|
375
|
+
Where you cannot check a point, say so: "I cannot settle this without X" is an
|
|
376
|
+
answer, with what you would do next.
|
|
377
|
+
|
|
378
|
+
**Push back with evidence.** Name what you checked and what it showed. Where a
|
|
379
|
+
finding conflicts with a decision the user already made, raise it rather than
|
|
380
|
+
quietly following one or the other.
|
|
381
|
+
|
|
382
|
+
A finding that asks for a new test, or for an existing one to assert more, is
|
|
383
|
+
not yours to satisfy. It goes to the author, with the finding attached, for the
|
|
384
|
+
same reason the first tests did: a test written by the person whose code was
|
|
385
|
+
just criticised tends to be a test that passes. Answering the reviewer with a
|
|
386
|
+
test you wrote yourself closes the thread and loses the check.
|
|
387
|
+
|
|
388
|
+
**Then fix, in this order:** what is broken or unsafe, then the small certain
|
|
389
|
+
things, then the structural ones. One at a time, running the check after each,
|
|
390
|
+
so you know which change did what.
|
|
391
|
+
|
|
392
|
+
**Answer plainly.** No performative agreement, no thanks, no apology: state the
|
|
393
|
+
fix or state the pushback. If you pushed back and turned out to be wrong, say
|
|
394
|
+
what you checked, what it showed, and carry on. The correction is one line,
|
|
395
|
+
not a paragraph about how it happened.
|
|
396
|
+
|
|
397
|
+
When the changes are in, the check is run again and the result reported. The
|
|
398
|
+
review is answered when every point has a fix, a reason it does not hold, or a
|
|
399
|
+
question back, not when the list has been read.
|
|
400
|
+
|
|
401
|
+
## Reviewing something that is not code
|
|
402
|
+
|
|
403
|
+
The same shape holds for a document, a configuration, a prompt or a plan: what
|
|
404
|
+
was asked for, what the thing does, and the difference between them. The
|
|
405
|
+
questions change, the discipline does not: cite the place, name the concrete
|
|
406
|
+
consequence, and say plainly when there is nothing to report.
|
|
407
|
+
|
|
408
|
+
Sources and licences: [NOTICE.md](NOTICE.md).
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!-- The licences of the sources this skill was consolidated from. They travel
|
|
2
|
+
with the skill directory because the licences require it of anyone who
|
|
3
|
+
distributes the material. NOTICE.md says what was taken from each source;
|
|
4
|
+
this file carries the permission notices themselves. -->
|
|
5
|
+
|
|
6
|
+
# Licences of the sources
|
|
7
|
+
|
|
8
|
+
`obk-tdd` consolidates material from the sources named in
|
|
9
|
+
[NOTICE.md](NOTICE.md). Their licences are reproduced below in full.
|
|
10
|
+
|
|
11
|
+
## MIT
|
|
12
|
+
|
|
13
|
+
The MIT permission notice below applies to the work of each of these copyright
|
|
14
|
+
holders, and is reproduced with each of their notices. The path after each one
|
|
15
|
+
is the licence file it was read from, in the research pack's source clones.
|
|
16
|
+
|
|
17
|
+
- **`mattpocock/skills`**, Copyright (c) 2026 Matt Pocock
|
|
18
|
+
(`mattpocock_skills/LICENSE`)
|
|
19
|
+
- **`obra/superpowers`**, Copyright (c) 2025 Jesse Vincent
|
|
20
|
+
(`obra_superpowers/LICENSE`)
|
|
21
|
+
- **Cursor `plugins`, the pstack plugin**, Copyright (c) 2026 Lauren Tan
|
|
22
|
+
(`cursor_plugins/pstack/LICENSE`)
|
|
23
|
+
- **`addyosmani/agent-skills`**, Copyright (c) 2025 Addy Osmani
|
|
24
|
+
(`addyosmani_agent-skills/LICENSE`)
|
|
25
|
+
- **`citypaul/.dotfiles`; the `tdd` and `mutation-testing` skills carry no
|
|
26
|
+
nested notice, so the repository licence governs them**, Copyright (c) 2024 Paul Hammond
|
|
27
|
+
(`citypaul_.dotfiles/LICENSE`)
|
|
28
|
+
- **`KentBeck/BPlusTree3`, for his own rules file**, Copyright (c) 2025 Kent Beck
|
|
29
|
+
(`KentBeck_BPlusTree3/LICENSE`)
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
MIT License
|
|
33
|
+
|
|
34
|
+
Copyright (c) 2026 Matt Pocock
|
|
35
|
+
Copyright (c) 2025 Jesse Vincent
|
|
36
|
+
Copyright (c) 2026 Lauren Tan
|
|
37
|
+
Copyright (c) 2025 Addy Osmani
|
|
38
|
+
Copyright (c) 2024 Paul Hammond
|
|
39
|
+
Copyright (c) 2025 Kent Beck
|
|
40
|
+
|
|
41
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
42
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
43
|
+
in the Software without restriction, including without limitation the rights
|
|
44
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
45
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
46
|
+
furnished to do so, subject to the following conditions:
|
|
47
|
+
|
|
48
|
+
The above copyright notice and this permission notice shall be included in all
|
|
49
|
+
copies or substantial portions of the Software.
|
|
50
|
+
|
|
51
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
52
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
53
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
54
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
55
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
56
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
57
|
+
SOFTWARE.
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Sources that could not be read
|
|
61
|
+
|
|
62
|
+
- **`nizos/tdd-guard`** is not among the clones in the research pack. What this
|
|
63
|
+
skill takes from it is the idea of a check that refuses work which skipped
|
|
64
|
+
the failing test, described in our own words.
|
|
65
|
+
|
|
66
|
+
These are named in NOTICE.md for honesty about where the material came from.
|
|
67
|
+
No text of theirs is reproduced in this skill, and their licence files were not
|
|
68
|
+
available here to reproduce.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<!-- Attribution for the sources this skill was built from. Kept out of
|
|
2
|
+
SKILL.md so it is not read into context on every use; it travels with
|
|
3
|
+
the skill directory, which is what the licences require. -->
|
|
4
|
+
|
|
5
|
+
# Sources and licences
|
|
6
|
+
|
|
7
|
+
The skill `obk-tdd` was consolidated for this kit from these, all MIT, with
|
|
8
|
+
thanks:
|
|
9
|
+
|
|
10
|
+
- **mattpocock/skills**, `engineering/tdd`: seams and where tests go, vertical
|
|
11
|
+
slices against bulk testing, the tautological and implementation-coupled
|
|
12
|
+
shapes, refactoring outside the loop, standing in only at system boundaries,
|
|
13
|
+
and not testing everything so the effort lands on the paths that matter. Its
|
|
14
|
+
`to-spec`: the existing seam preferred, the highest one, and the fewer the
|
|
15
|
+
better. Its `diagnosing-bugs`: the correct seam for a bug test, and no
|
|
16
|
+
correct seam being the finding.
|
|
17
|
+
- **obra/superpowers**, `test-driven-development` and its `writing-good-tests`:
|
|
18
|
+
naming the break a test catches, deriving the expected value by hand, change
|
|
19
|
+
detectors, behaviour rather than text, your contract rather than the
|
|
20
|
+
framework's, the four rules about a stand-in, the list of warning signs, and
|
|
21
|
+
the mutation classes. Its `verification-before-completion`: the
|
|
22
|
+
revert-the-fix proof. Its `writing-plans`: a requirement's silence not being
|
|
23
|
+
permission, and the few uncovered input classes most likely to bite.
|
|
24
|
+
- **Cursor pstack**, `tdd` and `principle-test-behavior-not-implementation`:
|
|
25
|
+
the five shapes that observe no behaviour and the fix for each (asserting
|
|
26
|
+
what a stand-in received rather than that it was called, and the relation
|
|
27
|
+
across rows of data that is kept), "prefer no
|
|
28
|
+
new test over a bad test", the honest exit when a test is impractical, and
|
|
29
|
+
the report that names the failing-before and passing-after runs.
|
|
30
|
+
- **addyosmani/agent-skills**, `test-driven-development` and
|
|
31
|
+
`constraint-driven-development`: finding out how the project tests before
|
|
32
|
+
writing anything, repetition being no fault in a test, a subagent for the
|
|
33
|
+
reproduction test, and the cheap roads to green.
|
|
34
|
+
- **citypaul/.dotfiles**, `tdd` and `mutation-testing` with its
|
|
35
|
+
`mutator-rules`: the mutation loop, survivor triage into killed, equivalent
|
|
36
|
+
or named and deferred, the equivalence question, the high-value logic worth
|
|
37
|
+
breaking, the inputs that tell a break apart (either side of a boundary,
|
|
38
|
+
mixed true and false, no identity values), the tool-run mechanics in
|
|
39
|
+
`mutation-tools.md`, keeping the harness out of the inner loop, triangulating
|
|
40
|
+
after a fake, and refusing to manufacture a red.
|
|
41
|
+
- **Kent Beck's own rules file**: one test at a time, the smallest code that
|
|
42
|
+
passes, structure and behaviour kept apart, and the two-level test for a
|
|
43
|
+
defect.
|
|
44
|
+
- **nizos/tdd-guard**: the ladder to a clean red.
|
|
45
|
+
|
|
46
|
+
Ideas paraphrased, with no text taken: Trail of Bits' mutation-testing skill
|
|
47
|
+
(CC BY-SA 4.0) on equivalent mutants, Anthropic's Claude Code documentation on
|
|
48
|
+
separate test authorship, alexop.dev on why one context cannot hold both
|
|
49
|
+
halves, and the published work on mutation testing at scale.
|
|
50
|
+
|
|
51
|
+
Our own, with no source behind them: the order to break things in, the red
|
|
52
|
+
from an archived baseline for behaviour that already existed, checking that an
|
|
53
|
+
author's hand-back is in the change (from this repo's issues #115 and #119),
|
|
54
|
+
and the part on work away from code.
|