@assuredloop/orca-bot-kit 0.1.0 → 0.3.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 +548 -3
- package/SETUP.md +275 -0
- package/package.json +32 -13
- package/rules/evidence.md +15 -0
- package/rules/finishing.md +23 -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 +22 -0
- package/rules/simple.md +14 -0
- package/rules/talk.md +13 -0
- package/rules/tests-first.md +17 -0
- package/rules/the-ask.md +19 -0
- package/skills/obk-arch/LICENSES.md +52 -0
- package/skills/obk-arch/NOTICE.md +242 -0
- package/skills/obk-arch/SKILL.md +598 -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 +312 -0
- package/skills/obk-debugging/LICENSES.md +67 -0
- package/skills/obk-debugging/NOTICE.md +115 -0
- package/skills/obk-debugging/SKILL.md +434 -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 +148 -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 +256 -0
- package/skills/obk-grilling/LICENSES.md +42 -0
- package/skills/obk-grilling/NOTICE.md +111 -0
- package/skills/obk-grilling/SKILL.md +221 -0
- package/skills/obk-grooming/LICENSES.md +52 -0
- package/skills/obk-grooming/NOTICE.md +111 -0
- package/skills/obk-grooming/SKILL.md +222 -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 +269 -0
- package/skills/obk-reviewing/LICENSES.md +66 -0
- package/skills/obk-reviewing/NOTICE.md +58 -0
- package/skills/obk-reviewing/SKILL.md +411 -0
- package/skills/obk-tdd/LICENSES.md +68 -0
- package/skills/obk-tdd/NOTICE.md +54 -0
- package/skills/obk-tdd/SKILL.md +547 -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 +180 -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 +1169 -0
- package/src/conversations.js +150 -0
- package/src/groom.js +159 -0
- package/src/health.js +309 -0
- package/src/hooks.js +257 -0
- package/src/init.js +314 -0
- package/src/launch.js +299 -0
- package/src/message.js +402 -0
- package/src/orca.js +362 -0
- package/src/pause.js +63 -0
- package/src/record.js +209 -0
- package/src/restart.js +193 -0
- package/src/retire.js +92 -0
- package/src/roster.js +71 -0
- package/src/rules.js +408 -0
- package/src/skills.js +630 -0
- package/src/sources.js +371 -0
- package/src/up.js +500 -0
- package/src/usage.js +401 -0
- package/bin/okb.js +0 -4
- package/src/index.js +0 -11
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: obk-arch
|
|
3
|
+
description: >-
|
|
4
|
+
Shaping a piece of work before building it: a short note of what is wanted
|
|
5
|
+
and what done means, deciding the shape from the usage and the data with
|
|
6
|
+
more than one candidate, keeping a decision record (ADR) and replacing it
|
|
7
|
+
whole when the decision changes, making the thing runnable and testable so
|
|
8
|
+
anyone can find out whether it works, and cutting the work into pieces that
|
|
9
|
+
each end in a check, and handing a piece to someone else by what is wanted
|
|
10
|
+
and its boundary, with only the research that confirms and triages it. Use
|
|
11
|
+
when starting something new, planning a feature, adding a public interface
|
|
12
|
+
or a new data shape, making a choice that is hard to undo, writing or
|
|
13
|
+
changing a decision record, handing work to someone else to build, or when a
|
|
14
|
+
change is big enough that jumping into the code would settle the shape by
|
|
15
|
+
accident.
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Shaping work before you build it
|
|
19
|
+
|
|
20
|
+
Four things: say what is wanted, decide the shape, make sure the thing can be
|
|
21
|
+
started and driven so anyone can tell whether it works, and cut the work into
|
|
22
|
+
pieces that each end in a check. The third is what makes the rest real. A
|
|
23
|
+
decision that will outlast the change gets a record of its own. When a piece
|
|
24
|
+
goes to someone else, it goes by its intention; the how is theirs.
|
|
25
|
+
|
|
26
|
+
None of this needs a particular document, tracker or format. Where a project
|
|
27
|
+
has one, use it; where it does not, a few lines in the right place do the job.
|
|
28
|
+
|
|
29
|
+
Reach for this when there is a shape to get wrong: something new, a public
|
|
30
|
+
interface, a new data shape, a choice that will be expensive to undo. Not for
|
|
31
|
+
work where the pattern is already set, a bug fix with a clear target, or a
|
|
32
|
+
change the constraints leave only one way to make. When it is one or two files
|
|
33
|
+
and the approach is obvious, say so and go and do it. A plan longer than the
|
|
34
|
+
work it plans is a cost with no return.
|
|
35
|
+
|
|
36
|
+
These are defaults for work where nothing says otherwise. A user who asks for
|
|
37
|
+
something else gets what they asked for; say which of these you left and why.
|
|
38
|
+
|
|
39
|
+
## Say what is wanted
|
|
40
|
+
|
|
41
|
+
A very light note: short enough to be read, long enough that someone else could
|
|
42
|
+
act on it. It says:
|
|
43
|
+
|
|
44
|
+
- **The problem.** What is wrong or missing now, not the solution wearing a
|
|
45
|
+
problem's clothes.
|
|
46
|
+
- **Who it is for.** The person who has that problem, which is often not the
|
|
47
|
+
person asking.
|
|
48
|
+
- **What they can do once it is finished**, as behaviour someone could observe
|
|
49
|
+
from outside.
|
|
50
|
+
- **How we will know it works**, written as checkable statements. These are the
|
|
51
|
+
ones that matter most: they become the acceptance tests when the work starts
|
|
52
|
+
and the "what was asked" a reviewer reads it against, so write them as
|
|
53
|
+
something you could be wrong about, and never loosen one to declare victory.
|
|
54
|
+
- **What we are not doing.** The things nobody said aloud are the things that
|
|
55
|
+
get built by accident.
|
|
56
|
+
|
|
57
|
+
No format and no home: an issue, a file, a message, a page in whatever the
|
|
58
|
+
project already uses. And if a proper note already exists, use that one rather
|
|
59
|
+
than writing a second.
|
|
60
|
+
|
|
61
|
+
## Decide the shape
|
|
62
|
+
|
|
63
|
+
### Sharpen the words while you are at it
|
|
64
|
+
|
|
65
|
+
When a term keeps doing heavy lifting ("account", "active", "ready"), say what
|
|
66
|
+
it means here and what it does not; where that stays vague, a concrete scenario
|
|
67
|
+
forces the boundary open. Check a claim about how things work against the code
|
|
68
|
+
rather than accepting it.
|
|
69
|
+
|
|
70
|
+
### Ground it first
|
|
71
|
+
|
|
72
|
+
Before sketching anything, build a real model of what the new code touches: the
|
|
73
|
+
modules it will sit between, how data reaches them now, what already owns the
|
|
74
|
+
rules you are about to write. Naming a file is not grounding. Trace it.
|
|
75
|
+
Skipping this is what produces a design that is elegant and does not fit.
|
|
76
|
+
|
|
77
|
+
Where the design redefines who owns what, find out why the current shape is
|
|
78
|
+
the way it is first, so the reason becomes a constraint you are choosing to
|
|
79
|
+
overrule rather than one you never saw. Greenfield with nothing around it is
|
|
80
|
+
the one case to skip.
|
|
81
|
+
|
|
82
|
+
### What a sketch is
|
|
83
|
+
|
|
84
|
+
Types, signatures and module boundaries with nothing implemented: bodies that
|
|
85
|
+
say "not implemented", a comment where the tricky logic will go, and a line on
|
|
86
|
+
each saying what it is for and what it must keep true. The test of a good one
|
|
87
|
+
is that a reader can follow the data from input to output by reading the
|
|
88
|
+
signatures alone.
|
|
89
|
+
|
|
90
|
+
That is what you compare, argue about and throw away, cheaply, which is the
|
|
91
|
+
point of doing it before the code.
|
|
92
|
+
|
|
93
|
+
### Usage first, then the data, then the types
|
|
94
|
+
|
|
95
|
+
Write the calls before the types: two or three real call sites, and how
|
|
96
|
+
someone would use it if they were reading about it for the first time. The
|
|
97
|
+
usage is the specification. When the sketch and the usage disagree, change the
|
|
98
|
+
sketch.
|
|
99
|
+
|
|
100
|
+
Then the data. Get the shape of it right before the logic, and trace every way
|
|
101
|
+
it will be read and written through the shape you are proposing. If the answer
|
|
102
|
+
to one of those is "we can add an index or a cache for that later", the shape
|
|
103
|
+
is wrong now, not later.
|
|
104
|
+
|
|
105
|
+
Types and data converge. Three similar lines still beat an abstraction
|
|
106
|
+
invented before there was anything to abstract.
|
|
107
|
+
|
|
108
|
+
Five things worth deciding while the shape is still cheap to change:
|
|
109
|
+
|
|
110
|
+
- **Let a structure carry the domain.** A state machine rather than scattered
|
|
111
|
+
flags, a lookup table rather than branches spread across files, a typed
|
|
112
|
+
object rather than loose parameters: the right structure makes invalid
|
|
113
|
+
states impossible to write and deletes branches.
|
|
114
|
+
|
|
115
|
+
- **Put the rules in the types where you can.** A type that cannot be misused
|
|
116
|
+
beats a check at runtime, which beats a comment asking people to be careful.
|
|
117
|
+
- **Check at the edges and trust inside.** Validate where data enters, then let
|
|
118
|
+
the inside assume it is good. Scattering the same check through the middle
|
|
119
|
+
means no one place is responsible for it.
|
|
120
|
+
- **One home per rule.** Derive the rest rather than keeping two copies in
|
|
121
|
+
step; two copies of one fact is a bug with a delay on it.
|
|
122
|
+
- **Ask what happens if it runs twice, or stops halfway.** If the answer
|
|
123
|
+
depends on what the last attempt left behind, something is missing that puts
|
|
124
|
+
it back in order, and that is a design question, not an operational one.
|
|
125
|
+
|
|
126
|
+
### Design it twice
|
|
127
|
+
|
|
128
|
+
Produce at least two structurally different candidates before you choose, even
|
|
129
|
+
when the first looks sufficient. Whole shapes, not variations inside one shape.
|
|
130
|
+
Two ways to arrange the same idea teach you nothing.
|
|
131
|
+
|
|
132
|
+
A cheap way to get real difference is to give each candidate a constraint of
|
|
133
|
+
its own and see what it forces:
|
|
134
|
+
|
|
135
|
+
- the smallest possible interface, one to three ways in, as much behind each as
|
|
136
|
+
will fit;
|
|
137
|
+
- the one that bends to the widest range of uses;
|
|
138
|
+
- the one that makes the most common case trivial and lets the rest be awkward;
|
|
139
|
+
- the one that puts whatever varies behind a port with adapters either side.
|
|
140
|
+
|
|
141
|
+
Keep them genuinely apart while you make them; a safe middle drafted early
|
|
142
|
+
defeats the point. Then compare on how much each hides, prefer the shape that
|
|
143
|
+
puts more behaviour behind a smaller surface (that is what a caller is buying),
|
|
144
|
+
and take the best parts of the others into it where they combine.
|
|
145
|
+
|
|
146
|
+
### Judging an interface
|
|
147
|
+
|
|
148
|
+
The interface is everything a caller has to know to use a piece correctly: not
|
|
149
|
+
only the signature, but the order things must happen in, what errors come out,
|
|
150
|
+
what it needs and what it costs. A good one gives a caller a lot of behaviour
|
|
151
|
+
for a little of that. Three questions do most of the work: can it have fewer
|
|
152
|
+
ways in, can the arguments be simpler, and can more be hidden behind it?
|
|
153
|
+
|
|
154
|
+
### Three tests that settle most of it
|
|
155
|
+
|
|
156
|
+
- **The deletion test.** Imagine the module gone. If the complexity goes with
|
|
157
|
+
it, it was a pass-through. If the complexity reappears in every caller, it
|
|
158
|
+
was earning its place.
|
|
159
|
+
- **The interface is the test surface.** Callers and tests cross at the same
|
|
160
|
+
place. If you find yourself wanting to test past the interface, the shape is
|
|
161
|
+
probably wrong.
|
|
162
|
+
- **One adapter is a hypothetical port; two is a real one.** This one is about
|
|
163
|
+
pluggability, not about whether a module should exist. Before putting an
|
|
164
|
+
interchangeable boundary in (a port with adapters either side), ask what the
|
|
165
|
+
second adapter is; production plus a test double is the usual honest pair. If
|
|
166
|
+
there is only ever one, you have added a layer to swap something that never
|
|
167
|
+
gets swapped. Pure computation needs no adapter at all: merge it and test it
|
|
168
|
+
through its interface.
|
|
169
|
+
|
|
170
|
+
Whether a module earns its place is a different question, answered by the
|
|
171
|
+
deletion test and by how much it hides. A module with one caller can be
|
|
172
|
+
entirely right, hiding an invariant, a rule or a state machine that would
|
|
173
|
+
otherwise sit in the middle of something else. One caller is not one adapter,
|
|
174
|
+
and counting callers is not this test.
|
|
175
|
+
|
|
176
|
+
### Signs the shape is wrong
|
|
177
|
+
|
|
178
|
+
- A caller has to call several things in the right order to do one thing.
|
|
179
|
+
- The options expose the stages inside rather than what the caller wants.
|
|
180
|
+
- Learning the interface does not save you from learning the implementation.
|
|
181
|
+
- Several modules depend on the same decision made inside one of them.
|
|
182
|
+
- Modules named after the order things happen rather than what they know. The
|
|
183
|
+
same rule then gets repeated in each step.
|
|
184
|
+
- A function that passes the same arguments on to something with the same
|
|
185
|
+
shape, adding a layer and hiding nothing.
|
|
186
|
+
|
|
187
|
+
And the other way: do not force it. Boring, local and clear is right where the
|
|
188
|
+
thing is unlikely to grow, and an abstraction that removes no branch, no
|
|
189
|
+
repeated rule and no impossible state is just indirection. The tell that this
|
|
190
|
+
step got skipped is the next feature adding one more branch to an if-else
|
|
191
|
+
chain, or a second flag that has to be kept in step with the first.
|
|
192
|
+
|
|
193
|
+
### Write down what you chose
|
|
194
|
+
|
|
195
|
+
One short paragraph, where the next person will find it: the problem, how it
|
|
196
|
+
is used, the shape, the trade-offs accepted (in the form *we accept X in
|
|
197
|
+
exchange for Y*), at least one other shape you considered with a line on why
|
|
198
|
+
it lost, and anything still open.
|
|
199
|
+
|
|
200
|
+
Where the constraints left only one shape, say that instead: "the only viable
|
|
201
|
+
shape, because...". Name anything a later reader might mistake for an
|
|
202
|
+
oversight.
|
|
203
|
+
|
|
204
|
+
Some decisions need more than the paragraph: a record of their own, kept after
|
|
205
|
+
the change. "Keep a record of a decision" below says which ones and how.
|
|
206
|
+
|
|
207
|
+
### When to build a throwaway instead of arguing
|
|
208
|
+
|
|
209
|
+
A prototype answers one question and is then deleted. No question, no
|
|
210
|
+
prototype: "let's try something" is not a question.
|
|
211
|
+
|
|
212
|
+
Skip the polish deliberately: no tests, no error handling beyond what makes it
|
|
213
|
+
run, no abstractions. Say out loud that it is throwaway, so nobody tries to
|
|
214
|
+
harden it or ship it.
|
|
215
|
+
|
|
216
|
+
Three things make one actually useful. It has to be trivial to start: one
|
|
217
|
+
command, or a file someone double-clicks; anything that needs explaining will
|
|
218
|
+
not get run by the person whose opinion you wanted. It should keep nothing
|
|
219
|
+
between runs, because persistence is usually the thing being questioned rather
|
|
220
|
+
than something to lean on. And it should show its state after every action, so
|
|
221
|
+
what changed is visible rather than inferred.
|
|
222
|
+
|
|
223
|
+
The observation is the result, not the code. Keep the decision it produced,
|
|
224
|
+
throw the prototype away or park it somewhere clearly marked, and write the
|
|
225
|
+
real thing from the beginning, test first.
|
|
226
|
+
|
|
227
|
+
## Keep a record of a decision
|
|
228
|
+
|
|
229
|
+
A decision record (an architecture decision record, ADR) is for someone months
|
|
230
|
+
or years later who meets the decision without its reasons. Without them they
|
|
231
|
+
have two choices: blindly accept it or blindly change it. The record lets them
|
|
232
|
+
do neither. Writing it has a second use: it forces the reasoning into the
|
|
233
|
+
open, where the people involved find out whether they actually agree.
|
|
234
|
+
|
|
235
|
+
### When one earns its place
|
|
236
|
+
|
|
237
|
+
All three are true: it is hard to reverse, so changing your mind later costs
|
|
238
|
+
something real; it is surprising without the context, so a reader will wonder
|
|
239
|
+
why it was done this way; and it came out of a genuine trade-off, with
|
|
240
|
+
alternatives that could have been chosen. Miss one and the paragraph from
|
|
241
|
+
"Write down what you chose" is enough. The ones that usually pass are about
|
|
242
|
+
structure, the qualities the thing must have (speed, security, cost to run),
|
|
243
|
+
dependencies, interfaces and how it is built. A proposal that met all three
|
|
244
|
+
and was turned down is kept too, as rejected, with the reason, so it is not
|
|
245
|
+
argued again.
|
|
246
|
+
|
|
247
|
+
One decision per record. A decision that comes in stages (a stopgap now, the
|
|
248
|
+
real answer later) gets a record for each stage. A record is not a design
|
|
249
|
+
document: component detail, diagrams and code go elsewhere, linked, and the
|
|
250
|
+
record still makes sense without them.
|
|
251
|
+
|
|
252
|
+
### The default format
|
|
253
|
+
|
|
254
|
+
Where the project already has a format for its records, use that one. Where
|
|
255
|
+
it does not, this is the default:
|
|
256
|
+
|
|
257
|
+
```markdown
|
|
258
|
+
# ADR NNNN: <the decision, as a short phrase>
|
|
259
|
+
|
|
260
|
+
Date: YYYY-MM-DD.
|
|
261
|
+
Status: proposed | accepted | rejected | deprecated | superseded by [ADR MMMM](MMMM-slug.md).
|
|
262
|
+
Decided by: <who>. Consulted: <who, if anyone>. A sentence marked (proposed) is not decided yet.
|
|
263
|
+
Supersedes: [ADR KKKK](KKKK-slug.md). <only when it does>
|
|
264
|
+
|
|
265
|
+
## Context
|
|
266
|
+
<The full context: the forces at play and the problem. Date any fact that will change.>
|
|
267
|
+
|
|
268
|
+
## Decision
|
|
269
|
+
<Full sentences: "We will…". All of what holds, including what is carried over
|
|
270
|
+
from a superseded record.>
|
|
271
|
+
|
|
272
|
+
## Alternatives considered
|
|
273
|
+
- <Alternative>: <what it is; why it was not chosen.>
|
|
274
|
+
|
|
275
|
+
## Consequences
|
|
276
|
+
- Good: …
|
|
277
|
+
- Bad: … <the cost accepted>
|
|
278
|
+
- Revisit if: … Confidence: <high or low, and why>.
|
|
279
|
+
- Checked by: <a test, a review point, a command; optional>
|
|
280
|
+
|
|
281
|
+
## History
|
|
282
|
+
- YYYY-MM-DD, [ADR KKKK](KKKK-slug.md): <what it decided or changed, and why>.
|
|
283
|
+
<one line per earlier record, oldest first; "none" for a first decision>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
What each part is for:
|
|
287
|
+
|
|
288
|
+
- **The title** names the decision, not the problem.
|
|
289
|
+
- **Status.** Proposed while it is being discussed; accepted once the people
|
|
290
|
+
who decide agree; rejected when it was turned down, kept with the reason so
|
|
291
|
+
the question is not reopened; deprecated when it no longer applies and
|
|
292
|
+
nothing replaces it; superseded by the record that replaced it. **Decided
|
|
293
|
+
by** names who made the call, so a reader knows whom to ask and whose call it
|
|
294
|
+
was; **Consulted**, whose views were sought.
|
|
295
|
+
- **Context** describes the forces at play: technical, political, social and
|
|
296
|
+
local to the project, usually in tension with each other, and says so. It is
|
|
297
|
+
value-neutral: facts, not a case for any option. It is the full context, as
|
|
298
|
+
a reader of this record alone would need it, not only what changed since the
|
|
299
|
+
last one. Date a fact that will change (a price, a limit, a version, who is
|
|
300
|
+
on the team).
|
|
301
|
+
- **Decision** is the response to those forces, in full sentences and the
|
|
302
|
+
active voice: "We will…". It says all of what now holds, not a repeat of the
|
|
303
|
+
title.
|
|
304
|
+
- **Alternatives considered** lists every alternative that was on the table,
|
|
305
|
+
each with what it is and why it was not chosen. The reasons weigh the
|
|
306
|
+
alternatives against the same forces the chosen one answers. Where the
|
|
307
|
+
constraints left only one, say "the only viable option, because…"; without
|
|
308
|
+
the reason that line is not allowed.
|
|
309
|
+
- **Consequences** lists all of them, not just the good ones: what gets
|
|
310
|
+
easier, what gets harder, the cost accepted, and for everyone the decision
|
|
311
|
+
touches (whoever runs it, tests it, calls it or pays for it), not only the
|
|
312
|
+
code. Revisit if names the change in circumstances that should reopen it.
|
|
313
|
+
The confidence tells a later reader how hard to push. Checked by, where
|
|
314
|
+
there is one, is how anyone can tell the decision is being kept: a test, a
|
|
315
|
+
point a reviewer looks for, a command.
|
|
316
|
+
- **History** is the whole story of the decision: one dated line for every
|
|
317
|
+
earlier record this one replaces, directly or down the chain, oldest first,
|
|
318
|
+
each with what it decided or changed and why. With the context, it lets the
|
|
319
|
+
newest record alone tell the full story.
|
|
320
|
+
|
|
321
|
+
The headings are there to be answered, not filled in. Write in full sentences;
|
|
322
|
+
bullets are for layout, not an excuse for fragments. Keep it short, with what
|
|
323
|
+
matters most first, since a long record goes unread; but short never costs the
|
|
324
|
+
full context, an alternative or a line of the history. What usually makes a
|
|
325
|
+
record long is design detail, and that goes elsewhere, linked.
|
|
326
|
+
|
|
327
|
+
### Changing a decision
|
|
328
|
+
|
|
329
|
+
A change to any part of an accepted record is a new record, and the new record
|
|
330
|
+
replaces the old one whole. It carries everything that still holds from the
|
|
331
|
+
old one, restated rather than pointed at, alongside what changed; the full
|
|
332
|
+
context as it now stands; the alternatives, old and new, with why each lost;
|
|
333
|
+
and the history, with a line for the record it replaces. Where it replaces
|
|
334
|
+
more than one, it names each.
|
|
335
|
+
|
|
336
|
+
The old record keeps its text. Its status alone changes, to superseded by the
|
|
337
|
+
new record, with a link. It stays true to what it says: that this was the
|
|
338
|
+
decision, for that stretch of time, for those reasons.
|
|
339
|
+
|
|
340
|
+
So a reader never has to put a decision together from several records. The
|
|
341
|
+
newest says all of what holds and how it got there; the older ones say what
|
|
342
|
+
governed the work before.
|
|
343
|
+
|
|
344
|
+
Not a change: until a record is accepted it is a draft, and a draft is edited.
|
|
345
|
+
A spelling or a broken link fixed without changing what the record says is not
|
|
346
|
+
a change either.
|
|
347
|
+
|
|
348
|
+
### Where records live
|
|
349
|
+
|
|
350
|
+
Beside what they are about, in version control, in plain text: one file per
|
|
351
|
+
record, named after the decision, numbered in sequence, and never renumbered.
|
|
352
|
+
A number once used is not used again, even for a rejected record. Where the
|
|
353
|
+
project keeps its records somewhere else, use that. Either way, someone who
|
|
354
|
+
needs a record can find it.
|
|
355
|
+
|
|
356
|
+
### Before it is accepted
|
|
357
|
+
|
|
358
|
+
A record is ready to be accepted when:
|
|
359
|
+
|
|
360
|
+
- there is some evidence the choice will work: a spike, a measurement, the
|
|
361
|
+
same thing done before, someone who has run it;
|
|
362
|
+
- the alternatives were compared on the forces named in the context: at least
|
|
363
|
+
two real ones, or the reason there was only one;
|
|
364
|
+
- someone who did not write it has challenged it, and the people who decide
|
|
365
|
+
agree with the outcome and the reasons;
|
|
366
|
+
- it is written and shared with the people it affects;
|
|
367
|
+
- it is known how to tell it is being kept and when to look at it again.
|
|
368
|
+
|
|
369
|
+
### Where records go wrong
|
|
370
|
+
|
|
371
|
+
- **Only upsides.** A reason that only restates the choice ("a queue, because
|
|
372
|
+
queues are reliable"), and the costs left out or played down.
|
|
373
|
+
- **The straw man.** An alternative that could never have worked, listed to
|
|
374
|
+
make the chosen one look good.
|
|
375
|
+
- **The sales tone.** Adjectives nobody could back with evidence. Take each
|
|
376
|
+
one out and see whether the record loses anything.
|
|
377
|
+
- **One option and one time frame.** No real alternative looked for, and only
|
|
378
|
+
the next few weeks' effects considered.
|
|
379
|
+
- **Criteria after the fact.** The forces chosen to fit the answer, or a
|
|
380
|
+
record written afterwards to justify a decision already made.
|
|
381
|
+
- **Everything in one.** A record carrying a whole architecture, or a detailed
|
|
382
|
+
design, instead of one decision.
|
|
383
|
+
- **Only the code's view.** The consequences for the people who run it, test
|
|
384
|
+
it, call it or pay for it missing.
|
|
385
|
+
- **Edited in place.** An accepted record quietly changed, so nobody can tell
|
|
386
|
+
what governed the work before, or when it changed.
|
|
387
|
+
|
|
388
|
+
## Make it runnable and testable
|
|
389
|
+
|
|
390
|
+
This is the part that makes an agent able to check its own work at any size
|
|
391
|
+
above a single function, and it belongs in the design rather than after it.
|
|
392
|
+
When a whole application is designed, or a feature is planned, the end-to-end
|
|
393
|
+
test work is planned at the same time and with the same care, and written, like
|
|
394
|
+
any other test, by someone other than the implementer.
|
|
395
|
+
|
|
396
|
+
Answer these about the thing you are shaping, from the code where you can
|
|
397
|
+
rather than by asking:
|
|
398
|
+
|
|
399
|
+
- **Surface**. What does a person actually touch? A screen, a command, an
|
|
400
|
+
endpoint, a library. If there are several, pick the main one and name the
|
|
401
|
+
rest.
|
|
402
|
+
- **Start**. How does it come up, and how do you know it is ready? A log line,
|
|
403
|
+
a port answering, a prompt appearing. Guessing with a pause is not knowing.
|
|
404
|
+
- **Drive**. How can something interact with it with nobody watching?
|
|
405
|
+
Whatever the project already has first; a general harness only after that.
|
|
406
|
+
- **Observe**. What evidence can be captured? Output, an exit status, a file,
|
|
407
|
+
a stored row, a message sent, a picture of the screen.
|
|
408
|
+
- **Isolate**. Can two of these run side by side, with their own ports and
|
|
409
|
+
data? If not, say so plainly, because refusing to drive a shared instance is
|
|
410
|
+
better than corrupting the one someone is using.
|
|
411
|
+
|
|
412
|
+
If the thing does not build or start as it stands, either fix that first or say
|
|
413
|
+
precisely what stopped it: which command, which failure, what was missing.
|
|
414
|
+
A recipe written against a broken checkout and presented as working teaches the
|
|
415
|
+
next reader the wrong steps, confidently. A recipe written against one and
|
|
416
|
+
marked as not yet run is still worth having: it says what the proof will be
|
|
417
|
+
once someone can get the thing up, which is most of the value. What it must not
|
|
418
|
+
do is claim to have been proven. And repairing whatever is broken is its own
|
|
419
|
+
piece of work, not something to absorb quietly into this one.
|
|
420
|
+
|
|
421
|
+
Prefer handles that survive: the name of a thing, a label, a route, a prompt
|
|
422
|
+
the program prints. Positions, orders and coordinates all drift, and a recipe
|
|
423
|
+
pinned to them fails for reasons that have nothing to do with the code.
|
|
424
|
+
|
|
425
|
+
Worth writing beside the recipe: a short list of what the thing actually does
|
|
426
|
+
for someone, one entry per feature (how to reach it, how to drive it, and what
|
|
427
|
+
state proves it worked). It is the part people find most useful later, because a
|
|
428
|
+
proof that exercises whichever entry point was convenient is incomplete when
|
|
429
|
+
the list names others. Start with the few that matter and let it grow.
|
|
430
|
+
|
|
431
|
+
Worth having beside that: one read-only check that answers "is this instance
|
|
432
|
+
worth driving at all" (is it up, is it the build I think, is that port ours).
|
|
433
|
+
Run it first whenever something looks strange, before debugging the thing
|
|
434
|
+
underneath.
|
|
435
|
+
|
|
436
|
+
What a proof has to do, which is where most of them fail:
|
|
437
|
+
|
|
438
|
+
- drive the path a person would actually take, not an internal setter or a
|
|
439
|
+
door that exists only for tests;
|
|
440
|
+
- capture the action and the state it produced, not only the final screen;
|
|
441
|
+
- check the effects as well as what is visible: what was written, sent,
|
|
442
|
+
recorded;
|
|
443
|
+
- stand in for something only where a real boundary already separates it.
|
|
444
|
+
|
|
445
|
+
Where the safe path is a dry run, find out what it genuinely skips by watching
|
|
446
|
+
what happens (files, network, state) rather than trusting its name.
|
|
447
|
+
|
|
448
|
+
Clean up what a run started, and never by name: stop what you started. Cleanup
|
|
449
|
+
takes the instance away and leaves the evidence where it said it would be.
|
|
450
|
+
|
|
451
|
+
Whatever you write down so that the next agent can do this, run it once, end to
|
|
452
|
+
end, before you hand it over. Instructions nobody has executed are a draft.
|
|
453
|
+
|
|
454
|
+
Where the work is about changing a number rather than adding a behaviour, take
|
|
455
|
+
the measurement before you start, so the check reads as the old value against
|
|
456
|
+
the new one rather than as a number with nothing to compare it to.
|
|
457
|
+
|
|
458
|
+
And be strict about what counts. A check comes back verified, not verified, or
|
|
459
|
+
inconclusive. And inconclusive is not a pass. Read the artefact rather than a
|
|
460
|
+
report about it. When something passes more easily than you expected, suspect
|
|
461
|
+
the way you are observing before you believe the result: that is the shape of a
|
|
462
|
+
check that is not actually looking.
|
|
463
|
+
|
|
464
|
+
### Designing so this is possible
|
|
465
|
+
|
|
466
|
+
Accept what you depend on rather than building it inside. Return results
|
|
467
|
+
instead of reaching out and changing things. Keep the surface small: fewer ways
|
|
468
|
+
in means less to set up.
|
|
469
|
+
|
|
470
|
+
How you test across a boundary follows what is behind it. Pure computation:
|
|
471
|
+
no boundary needed, test through the interface. Something with a good local
|
|
472
|
+
stand-in: use the stand-in and keep the boundary inside. Your own service
|
|
473
|
+
across a network: a port at the boundary, a real adapter for production and an
|
|
474
|
+
in-memory one for tests. Something you do not own at all: a port, and a
|
|
475
|
+
stand-in for it.
|
|
476
|
+
|
|
477
|
+
Once behaviour is covered through the interface above, tests against the pieces
|
|
478
|
+
inside it prove the same thing twice; retiring them, like any change to
|
|
479
|
+
tests, is for whoever wrote them.
|
|
480
|
+
|
|
481
|
+
## Cut the work into pieces
|
|
482
|
+
|
|
483
|
+
Each piece ends in a state you can check, and a piece that depends on it does
|
|
484
|
+
not start until it is green. A break found at the step that caused it is cheap; the
|
|
485
|
+
same break found five steps later is buried under everything built on top of
|
|
486
|
+
it.
|
|
487
|
+
|
|
488
|
+
- **Each piece is a narrow but complete path** through every layer it touches,
|
|
489
|
+
not one layer done across the whole feature. A finished piece can be shown
|
|
490
|
+
or checked on its own.
|
|
491
|
+
- **Sized to what one fresh context can hold**, because a piece that does not
|
|
492
|
+
fit gets done half-remembered.
|
|
493
|
+
- **Ordered by what you will learn.** The riskiest unknown first, so that
|
|
494
|
+
being wrong about it is cheap.
|
|
495
|
+
- **Prefactor where it helps.** Make the change easy, then make the easy
|
|
496
|
+
change. A small reshaping is part of the change; a large one is a piece of
|
|
497
|
+
its own, before the feature.
|
|
498
|
+
- **The first piece gets the thing running and testable as a whole**, even if
|
|
499
|
+
it does almost nothing yet. That is where the end-to-end test work lands, and
|
|
500
|
+
everything after it is checked through what it puts in place.
|
|
501
|
+
- **Each piece names the evidence** that says it is done: a test run, a file, a
|
|
502
|
+
line of output, a command. It is done when the evidence exists, not when it
|
|
503
|
+
feels done.
|
|
504
|
+
- **Say which pieces depend on which, and which can run side by side.** Two
|
|
505
|
+
people, or two sessions, can take independent pieces at once; a dependency
|
|
506
|
+
nobody wrote down turns into two people editing the same thing.
|
|
507
|
+
|
|
508
|
+
The exception is a change that has to happen everywhere at once. Sequence it as
|
|
509
|
+
expand, migrate, contract: add the new form beside the old so nothing breaks,
|
|
510
|
+
move the callers over in batches sized by what each batch touches, then delete
|
|
511
|
+
the old form once nothing calls it. If a piece deliberately leaves something
|
|
512
|
+
broken in between, say which piece and for how long.
|
|
513
|
+
|
|
514
|
+
## Hand a piece over
|
|
515
|
+
|
|
516
|
+
When someone else will build a piece (a person, another session, a
|
|
517
|
+
subagent), hand it over by its intention and leave the how to them. What goes
|
|
518
|
+
with it:
|
|
519
|
+
|
|
520
|
+
- **What is wanted, and why.** The note from "Say what is wanted", or where to
|
|
521
|
+
find it. The why is what lets the builder make the calls you did not
|
|
522
|
+
foresee.
|
|
523
|
+
- **The boundary.** What is in, what is out, and what it must stay compatible
|
|
524
|
+
with. Saying what is out keeps the builder from gold-plating the next thing
|
|
525
|
+
along. A constraint you know of and they could not find belongs here too:
|
|
526
|
+
that is part of the intent, not a step.
|
|
527
|
+
- **What done means**, as checks that can each be confirmed on their own.
|
|
528
|
+
|
|
529
|
+
Describe what the thing should do, not how to make it: behaviour, and the
|
|
530
|
+
names, types and contracts it touches, rather than file paths, line numbers or
|
|
531
|
+
a list of steps. The code moves while a piece waits, so paths go stale. A step
|
|
532
|
+
list settles the design before the builder has looked, carries your guesses as
|
|
533
|
+
if they were decisions, and takes away the judgement you handed the piece over
|
|
534
|
+
for. The design, the deeper research and the how are theirs, and so is
|
|
535
|
+
everything in this skill about deciding the shape. One exception: a snippet
|
|
536
|
+
from a prototype that pins a decision more exactly than words can (a state
|
|
537
|
+
machine, a schema, a type), trimmed to the decision and marked as coming from
|
|
538
|
+
a prototype.
|
|
539
|
+
|
|
540
|
+
Research before handing over goes as far as validating and triaging the
|
|
541
|
+
piece:
|
|
542
|
+
|
|
543
|
+
- **Is it real?** Above all when someone outside reported it. Reproduce a bug
|
|
544
|
+
from their steps, or find the behaviour in the running thing or the code,
|
|
545
|
+
and say what came of it: confirmed and where, not reproduced, or not enough
|
|
546
|
+
to tell. In the last case, ask the reporter for the specific thing that is
|
|
547
|
+
missing rather than passing a guess on. A confirmed problem makes a much
|
|
548
|
+
stronger hand-over than a suspected one.
|
|
549
|
+
- **Is it already there, or already turned down?** Look by what it does, not
|
|
550
|
+
by the reporter's words, and say where you looked.
|
|
551
|
+
- **Enough to place it**: how much it matters, roughly how big it is, what it
|
|
552
|
+
touches, and whether it can be handed over at all or needs a person's
|
|
553
|
+
judgement.
|
|
554
|
+
|
|
555
|
+
Then stop. Findings by file and line, a proposed fix, or a summary of all that
|
|
556
|
+
in the hand-off message is the builder's work done early, without the
|
|
557
|
+
builder's context.
|
|
558
|
+
|
|
559
|
+
## Before you build on it
|
|
560
|
+
|
|
561
|
+
Find out what the shape breaks elsewhere. Listing the callers is not the job;
|
|
562
|
+
the breakage a search does not show is (a changed order, a new precondition, an
|
|
563
|
+
assumption two things shared). Most plans that look risky are safe because of
|
|
564
|
+
one fact: find it, since if it holds most of the risky cases clear at once.
|
|
565
|
+
|
|
566
|
+
Look where a symbol search stops, because that is where the surprises are: the
|
|
567
|
+
library you call, at the version actually pinned; when things run, not only
|
|
568
|
+
what calls what; and what two things agree on without naming each other (the
|
|
569
|
+
shape of what an interface returns, a stored column, a wire format, something
|
|
570
|
+
in another language reading the same bytes, a setting that turns a path on).
|
|
571
|
+
Give each risk you keep a real likelihood and a real cost.
|
|
572
|
+
|
|
573
|
+
Then say how far you proved it: you said so, you pointed at the line, you
|
|
574
|
+
walked the bad case through, you ran something that would have failed if you
|
|
575
|
+
were wrong, or you saw it in the running thing. Short of running it, say so
|
|
576
|
+
rather than writing it up as settled, and list what you checked and cleared as
|
|
577
|
+
well as what you kept.
|
|
578
|
+
|
|
579
|
+
## When the shape turns out to be wrong
|
|
580
|
+
|
|
581
|
+
Deviations from the sketch are signal, not friction to absorb quietly. A
|
|
582
|
+
function that needs a parameter the sketch did not anticipate is asking a
|
|
583
|
+
question: was the sketch wrong, was the requirement missed, or is the
|
|
584
|
+
implementation reaching for something that is not its business?
|
|
585
|
+
|
|
586
|
+
The signal is a pattern rather than a single instance:
|
|
587
|
+
|
|
588
|
+
- the same shape of workaround appearing in unrelated places;
|
|
589
|
+
- several unrelated edge cases that each need their own special branch;
|
|
590
|
+
- types needing escape hatches to compile at all;
|
|
591
|
+
- reaching for a lock where the sketch said nothing was shared;
|
|
592
|
+
- callers having to know the rules inside to use it correctly.
|
|
593
|
+
|
|
594
|
+
A few edge cases do not condemn a design; some problems really are knotty, and
|
|
595
|
+
complexity in the problem is not complexity in the design. But when the pattern
|
|
596
|
+
is there, say so and redesign, rather than paying it off one branch at a time.
|
|
597
|
+
|
|
598
|
+
Sources and licences: [NOTICE.md](NOTICE.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
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-bot-building` names its sources in [NOTICE.md](NOTICE.md).
|
|
9
|
+
|
|
10
|
+
## Sources that need no third-party notice
|
|
11
|
+
|
|
12
|
+
This skill reproduces no third-party text. It was written from this kit's own
|
|
13
|
+
PRD and ADRs, from the owner's own words in the research pack, and from ideas
|
|
14
|
+
restated in our own words.
|
|
15
|
+
|
|
16
|
+
Those ideas came from material that carries no licence: a knowledge base and a
|
|
17
|
+
hosted bot product's own marketplace and documentation pages, gathered in the
|
|
18
|
+
research pack's `grok-bot-lessons.md`. Because no licence is attached to them,
|
|
19
|
+
nothing of theirs is copied here, and there is accordingly no permission notice
|
|
20
|
+
to reproduce. Credit for the ideas is given in NOTICE.md instead, which is
|
|
21
|
+
where it belongs.
|