@sitar_fiercer4c/skills 0.1.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 +5 -0
- package/README.md +75 -0
- package/bin/install.js +45 -0
- package/package.json +29 -0
- package/skills/architecture-walkthrough/SKILL.md +223 -0
- package/skills/architecture-walkthrough/references/sections.md +29 -0
- package/skills/architecture-walkthrough/scripts/check_structure.py +200 -0
- package/skills/autotest-webapp-ui/SKILL.md +58 -0
- package/skills/backend-code-review/SKILL.md +386 -0
- package/skills/backend-code-review/references/report-format.md +333 -0
- package/skills/backend-code-review/scripts/list_routes.py +269 -0
- package/skills/backend-code-review/scripts/sweep.py +550 -0
- package/skills/backend-code-review/scripts/verify_citations.py +201 -0
- package/skills/be-brief/SKILL.md +18 -0
- package/skills/clarke-list-excel/SKILL.md +51 -0
- package/skills/clarke-list-excel/references/output-schema.md +125 -0
- package/skills/clarke-list-excel/scripts/clarke_common.py +251 -0
- package/skills/clarke-list-excel/scripts/clarke_extract.py +487 -0
- package/skills/clarke-list-excel/scripts/load_clarke.py +322 -0
- package/skills/clarke-list-excel/scripts/run_all.py +63 -0
- package/skills/datalab-api/SKILL.md +163 -0
- package/skills/datalab-api/references/parameters-and-payload.md +121 -0
- package/skills/datalab-api/references/table-selection.md +35 -0
- package/skills/datalab-api/scripts/datalab_tables.py +365 -0
- package/skills/find-test-seam/SKILL.md +41 -0
- package/skills/frontend-code-review/SKILL.md +247 -0
- package/skills/frontend-code-review-2/SKILL.md +192 -0
- package/skills/frontend-code-review-2/scripts/fetch_pr_comments.py +65 -0
- package/skills/frontend-code-review-2/scripts/render_report.py +139 -0
- package/skills/murtaza-breif/SKILL.md +143 -0
- package/skills/murtaza-breif/scripts/save_brief.py +128 -0
- package/skills/pdf-to-json/SKILL.md +42 -0
- package/skills/pdf-to-json/references/output-schema.md +168 -0
- package/skills/pdf-to-json/scripts/extract_figures.py +319 -0
- package/skills/pdf-to-json/scripts/load_mongo.py +287 -0
- package/skills/pdf-to-json/scripts/pdf_extract.py +1313 -0
- package/skills/record-api-traffic/SKILL.md +434 -0
- package/skills/record-api-traffic/references/reading-recordings.md +224 -0
- package/skills/record-api-traffic/scripts/check-schema.mjs +184 -0
- package/skills/record-api-traffic/scripts/dump-quotation.mjs +67 -0
- package/skills/record-api-traffic/scripts/dump-source-excel.mjs +75 -0
- package/skills/record-api-traffic/scripts/lib/repo.mjs +109 -0
- package/skills/record-api-traffic/scripts/preflight.py +528 -0
- package/skills/record-api-traffic/scripts/record-api-traffic.py +720 -0
- package/skills/refac-wrt-business-goal/SKILL.md +305 -0
- package/skills/refac-wrt-business-goal/references/critic.md +170 -0
- package/skills/system-resource-triage/SKILL.md +180 -0
- package/skills/system-resource-triage/scripts/reap.sh +116 -0
- package/skills/system-resource-triage/scripts/triage.sh +111 -0
- package/skills/using-git-worktrees/SKILL.md +167 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: refac-wrt-business-goal
|
|
3
|
+
description: Converge on a business model of a codebase — an under-50-word business goal, a node table, an edge list, an ASCII graph, and the input and output test seams a characterization test can be pinned to — from the repo, the user's account of the happy path, and an API recording of it. Use this whenever someone wants a flow modelled before a refactor, or asks where to pin a test for that flow.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Refactor with respect to the business goal
|
|
7
|
+
|
|
8
|
+
## Inputs
|
|
9
|
+
|
|
10
|
+
Three things, all required. Ask for any that is missing and wait — starting without one costs more
|
|
11
|
+
than the wait does.
|
|
12
|
+
|
|
13
|
+
1. **The repo, and which flow in it.** One flow, named by what the user does, not by a file.
|
|
14
|
+
2. **The user's account of the happy path.** What they do, step by step, and where the business
|
|
15
|
+
considers the job done. The finish line especially: it is almost never where the code stops.
|
|
16
|
+
3. **An API recording of that happy path** — the `backend-inbound.log` and `.jsonl` pair
|
|
17
|
+
produced by the `record-api-traffic` skill, landing in that skill's own workspace at
|
|
18
|
+
`skills/record-api-traffic-workspace/recordings/<repo-slug>/run-<stamp>/`. That run folder
|
|
19
|
+
also holds the frontend's two legs and the backend's outbound calls, if you need them.
|
|
20
|
+
|
|
21
|
+
The recording is not a nice-to-have. Without it you are guessing which code runs, and a graph built
|
|
22
|
+
from code that never executes is the expensive failure here — you model a path the business
|
|
23
|
+
abandoned two years ago and hand it back as a blueprint. If the user has no recording, point them at
|
|
24
|
+
`record-api-traffic` to capture one, and wait. Its `references/reading-recordings.md` has the field
|
|
25
|
+
meanings and jq recipes.
|
|
26
|
+
|
|
27
|
+
## Output
|
|
28
|
+
|
|
29
|
+
Exactly one file, at
|
|
30
|
+
`skills/refac-wrt-business-goal-workspace/<target-name>-business-model.md`, with six sections:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
# Business model: <target>
|
|
34
|
+
|
|
35
|
+
## Business goal (under 50 words)
|
|
36
|
+
## Nodes (the workflow's steps: the table, plus external inputs and rule footnotes)
|
|
37
|
+
## Edges (what moves between steps, explicit list)
|
|
38
|
+
## Graph (the workflow drawn, ASCII)
|
|
39
|
+
## Input seam (where a test drives this workflow, in code that exists today)
|
|
40
|
+
## Output seam (where every outcome becomes durable, and which field carries each node)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
There are three things here, not six. The **goal** is what the business is for. The **workflow** is
|
|
44
|
+
how it gets there — the ordered decisions that carry an external input to an outcome — and the
|
|
45
|
+
nodes, edges and graph are that one workflow written three ways: its steps, its transitions, its
|
|
46
|
+
picture. The **seams** are where that workflow touches the code as it stands today.
|
|
47
|
+
|
|
48
|
+
The first two give the chain the whole exercise is built on: **every business goal is achieved by a
|
|
49
|
+
workflow, and the graph represents that workflow.** They are done when an independent critic says
|
|
50
|
+
both links hold — that the workflow achieves the goal, and that the graph is a faithful drawing of
|
|
51
|
+
the workflow.
|
|
52
|
+
|
|
53
|
+
The seams exist because a model that stops at the graph is a claim nobody can check. The refactor it
|
|
54
|
+
is written to guide will move every file it describes, and without two fixed points where the
|
|
55
|
+
current behaviour can be held still, nothing afterwards can show the workflow survived. Naming the
|
|
56
|
+
seams is what turns the model from a description into something falsifiable.
|
|
57
|
+
|
|
58
|
+
**Not an output: any change to the repo. Not one line, not a rename, not a comment.** The artifact is
|
|
59
|
+
the whole deliverable. If the user asks for the refactor too, produce the artifact first and let them
|
|
60
|
+
start the refactor as a separate request. A model written by someone already mid-edit drifts toward
|
|
61
|
+
describing the edits instead of the business.
|
|
62
|
+
|
|
63
|
+
Naming a seam invites writing the test at it. Don't: this skill names seams, it does not write tests,
|
|
64
|
+
and it does not export a helper to make one reachable.
|
|
65
|
+
|
|
66
|
+
## 1. Read the code, against the recording
|
|
67
|
+
|
|
68
|
+
Follow one flow, from the entry point to the business finish line. The recording tells you where
|
|
69
|
+
that flow really goes: every call it made, in order, with bodies. Read it first, then open the code
|
|
70
|
+
the calls land in.
|
|
71
|
+
|
|
72
|
+
Before opening anything, list the files and their sizes and work out which sit past the finish line
|
|
73
|
+
— those you skim only far enough to confirm they are downstream, and then don't model. A quarter of
|
|
74
|
+
a services directory is often export and delivery code that runs after the business considers the
|
|
75
|
+
job done.
|
|
76
|
+
|
|
77
|
+
Read in batches: issue the reads for every file in the current layer in one go, rather than opening
|
|
78
|
+
one, thinking, and opening the next. You are following a flow, not auditing a directory, and the
|
|
79
|
+
thinking that matters happens once you have the layer in front of you.
|
|
80
|
+
|
|
81
|
+
Four things will lie to you, all in the same direction — they describe an older system. The
|
|
82
|
+
recording is what you check each of them against, because it is the only account of the system that
|
|
83
|
+
cannot be out of date:
|
|
84
|
+
|
|
85
|
+
- **the repo's own docs** (architecture notes, code reviews, plans)
|
|
86
|
+
- **comments and names** — a step labelled `fallback` may be the success path
|
|
87
|
+
- **a subagent's narrative** — subagents find files well and summarise flows badly, because they
|
|
88
|
+
read excerpts
|
|
89
|
+
- **your first read** — go back and check what each step *writes*, including mutation of arguments
|
|
90
|
+
|
|
91
|
+
Find what is dead at runtime as well as what runs. Dead code tells you which business rules were
|
|
92
|
+
tried and abandoned, which is exactly the kind of thing the user has stopped noticing. The recording
|
|
93
|
+
makes this cheap: code with no call behind it is a candidate, and grepping the exported names on
|
|
94
|
+
your flow for callers settles the rest.
|
|
95
|
+
|
|
96
|
+
## 2. Say what you think this is for, and wait to be told you're right
|
|
97
|
+
|
|
98
|
+
You have read the code and watched the calls. Now commit to a reading of the business and have the
|
|
99
|
+
user check it — before you write the goal, a node, or an edge.
|
|
100
|
+
|
|
101
|
+
Put three things in front of them with `AskUserQuestion`:
|
|
102
|
+
|
|
103
|
+
- **A short paragraph in plain language.** Who this serves, what they get out of it, where the
|
|
104
|
+
business considers it finished, what it refuses to do. No vocabulary from the repo — if a
|
|
105
|
+
sentence needs a filename to make sense, you are describing the code.
|
|
106
|
+
- **The steps of the workflow you expect, in order. Names only, no descriptions.** Names are cheap
|
|
107
|
+
to throw away; a filled-in node table takes long enough to write that you would defend it rather
|
|
108
|
+
than drop it. The point here is a cheap check on the *shape* of the workflow, while changing it is
|
|
109
|
+
still free.
|
|
110
|
+
- **3–4 questions.** Each one a thing that would change the paragraph or the node list if answered
|
|
111
|
+
the other way. The test of a good question: it is about what the business wants, and a person who
|
|
112
|
+
has never read the code could answer it.
|
|
113
|
+
|
|
114
|
+
Good: *"Is the photo on the customer's inquiry decoration, or part of the requirement?"*
|
|
115
|
+
Bad: *"Should `injectImages` run before or after filtering?"*
|
|
116
|
+
|
|
117
|
+
**Then stop.** No goal sentence, no node table, no graph until the answers land. The finish line, and
|
|
118
|
+
which rules are invariants rather than conveniences somebody added, are not recoverable from code —
|
|
119
|
+
a model built without them is a picture of the code, which is the thing the user is complaining
|
|
120
|
+
about. And a goal drafted before the answers arrive is a goal you will then defend: what comes back
|
|
121
|
+
gets filed as a correction to it, rather than as the thing it should have been built on.
|
|
122
|
+
|
|
123
|
+
If the answers change your understanding, rewrite it and put it back. **Loop until the user confirms
|
|
124
|
+
it, with no cap.** This is the only unbounded loop in the skill, and deliberately so — a human ends
|
|
125
|
+
it. The critic loop later is capped precisely because nothing human is there to stop it.
|
|
126
|
+
|
|
127
|
+
## 3. Write the goal in under 50 words
|
|
128
|
+
|
|
129
|
+
The budget is the mechanism. It has no room for what the system does, only what it is *for*, so it
|
|
130
|
+
forces you to rank the business's concerns. Write it as one sentence about the customer's outcome.
|
|
131
|
+
|
|
132
|
+
If a rule you believe is important won't fit, that is information: either it isn't core, or your
|
|
133
|
+
goal sentence is aimed at the wrong thing.
|
|
134
|
+
|
|
135
|
+
The sentence says what the business is for. It does not say how the business gets there — that is
|
|
136
|
+
the workflow, and it is next.
|
|
137
|
+
|
|
138
|
+
## 4. Write the workflow: nodes, edges and graph
|
|
139
|
+
|
|
140
|
+
A goal is achieved by a workflow: an ordered run of decisions that carries something arriving from
|
|
141
|
+
outside all the way to an outcome the business recognises. Model that, and the three artifacts fall
|
|
142
|
+
out of it — the **nodes** are its steps, the **edges** are what moves between them, the **graph** is
|
|
143
|
+
it drawn.
|
|
144
|
+
|
|
145
|
+
Keeping the workflow in mind is what stops this becoming a taxonomy. A decomposition of a system
|
|
146
|
+
into parts is easy to write and passes a casual read; it has no start, no order, and nothing that
|
|
147
|
+
would let you say a step ran too late. If a node isn't a step on the way from an input to an
|
|
148
|
+
outcome, it is not part of the workflow, however true it may be about the system.
|
|
149
|
+
|
|
150
|
+
Node names are verb phrases in the language of the business, named for the decision the step makes.
|
|
151
|
+
Not for the function that makes it — a workflow rebuilt from the call chain is a picture of the code
|
|
152
|
+
you already have, which is the thing the user is complaining about.
|
|
153
|
+
|
|
154
|
+
List the **external inputs** — the things arriving from outside the workflow — above the table, so
|
|
155
|
+
the first step's `handed` column has somewhere to come from.
|
|
156
|
+
|
|
157
|
+
Then one table, five columns:
|
|
158
|
+
|
|
159
|
+
| node | handed | decides | refuses when | emits |
|
|
160
|
+
|---|---|---|---|---|
|
|
161
|
+
| `carry-quantities-into-the-draft` | the quotable line rows, and which column holds quantity | fills in the quantity the customer asked for, and nothing else (R1, R2) | never — see R2 | draft rows in the customer's order, each naming its inquiry row |
|
|
162
|
+
| `pin-photos-to-their-inquiry-rows` | every photo with the row it sits on | which inquiry line each photo illustrates (R3) | never — strays are discarded | for each row that has one, the photo belonging to it |
|
|
163
|
+
|
|
164
|
+
**Keep cells to a clause each.** A rule that needs a paragraph becomes a numbered footnote under the
|
|
165
|
+
table — `R1`, `R2` — referenced from the cell:
|
|
166
|
+
|
|
167
|
+
> R1. Every other field is left blank for the salesperson deliberately; this is the rule, not an
|
|
168
|
+
> unfinished mapping.
|
|
169
|
+
> R2. A quantity that cannot be read as a number is left empty rather than guessed at, and the line
|
|
170
|
+
> is still created.
|
|
171
|
+
> R3. One photo to a row, first wins a contested row; photos anchored outside the item table are
|
|
172
|
+
> discarded rather than attached to an arbitrary line.
|
|
173
|
+
|
|
174
|
+
The table earns its shape by putting `handed` and `emits` on the same row, so a node whose output
|
|
175
|
+
nothing consumes, or whose input no edge produces, shows up by scanning one column. That is exactly
|
|
176
|
+
what the critic checks under graph integrity. The thing to guard against is not columns but **cells
|
|
177
|
+
that swell into paragraphs** — once they do, the row stops being scannable and the defect hides
|
|
178
|
+
again. That is what the footnotes are for: let the rule run as long as it genuinely needs down
|
|
179
|
+
there, where nothing depends on it staying short.
|
|
180
|
+
|
|
181
|
+
Write the **edge list** out explicitly and separately: `E<n>. <source> -> <target> — <what travels>`.
|
|
182
|
+
The drawing is where mistakes hide; the edge list is what you check it against.
|
|
183
|
+
|
|
184
|
+
Then draw the graph in this shape, every time:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
(A) external input
|
|
188
|
+
(B) external input
|
|
189
|
+
|
|
|
190
|
+
| E1,E2
|
|
191
|
+
v
|
|
192
|
+
first-node ........................ E4 -> [R]
|
|
193
|
+
| E3
|
|
194
|
+
v
|
|
195
|
+
second-node ....................... E8 -> [R]
|
|
196
|
+
| E5
|
|
197
|
+
v
|
|
198
|
+
third-node ........................ E13 -> [R]
|
|
199
|
+
| E9 E10 -> a-later-node
|
|
200
|
+
v E11 -> another-node
|
|
201
|
+
fourth-node ....................... E16 -> [R]
|
|
202
|
+
|
|
203
|
+
[R] refuse-node -> OUTCOME 2: <what the user is told, and can act on>
|
|
204
|
+
commit-node --------------------> OUTCOME 1: <what they get>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
External inputs at the top, the spine down the left one step per line in the order the workflow runs
|
|
208
|
+
them, forward and cross edges as labelled jumps on the right, a single refusal sink `[R]` at the
|
|
209
|
+
bottom, and every path ending in a named outcome. The layout is doing more than looking tidy: read
|
|
210
|
+
top to bottom it is the workflow in sequence, so a step drawn out of order, or one with nothing
|
|
211
|
+
above it and nothing below, is visible without checking anything. One fixed shape also means the
|
|
212
|
+
drawing is comparable run to run and diffable, and that you spend your effort on the model rather
|
|
213
|
+
than on inventing notation.
|
|
214
|
+
|
|
215
|
+
## 5. Loop a critic until it agrees
|
|
216
|
+
|
|
217
|
+
The loop tests the chain: **the workflow achieves the 50-word goal, and the graph represents the
|
|
218
|
+
workflow.** Everything below serves those two links.
|
|
219
|
+
|
|
220
|
+
**Methodology.** Spawn a fresh critic each round — a continuation anchors to its own last verdict.
|
|
221
|
+
Round 1 is three critics in a single message so they run concurrently, each led onto a different part
|
|
222
|
+
of the checklist; round 2 onward is one. Merge by defect, not by critic. Where two critics
|
|
223
|
+
*contradict* each other, don't split the difference — go to the code and the goal and settle it.
|
|
224
|
+
Brief them from `references/critic.md`, which holds the checklist, the emphasis split and the
|
|
225
|
+
response format.
|
|
226
|
+
|
|
227
|
+
**Constraints.** TRUE means every clause of the goal is achieved by a step, every step earns its
|
|
228
|
+
place from the goal, and the drawing is the workflow — not that the model is beyond improvement. Two
|
|
229
|
+
rounds is normal, four is the hard ceiling. Defects still standing at four are reported as open
|
|
230
|
+
questions, not fixed.
|
|
231
|
+
|
|
232
|
+
**Gotchas.** A lone first-round TRUE is an agreeable critic, not a correct graph. Critics may read
|
|
233
|
+
the repo to settle a factual dispute, but the model is what is under review — a critic that starts
|
|
234
|
+
listing what it would change about the code has drifted. Re-submitting a converged model always
|
|
235
|
+
returns a fresh remark — that is oscillation, not a reopened defect.
|
|
236
|
+
|
|
237
|
+
## 6. Find the seams the model can be pinned to
|
|
238
|
+
|
|
239
|
+
Only now, once the critic has converged. A seam mapped against a graph that is still moving gets
|
|
240
|
+
re-mapped every round, and mapping is the expensive part of this step.
|
|
241
|
+
|
|
242
|
+
**Find a seam, don't create one.** A seam you have to export into existence is a change to the repo,
|
|
243
|
+
and this skill makes none. Search only `services/` and `utils/`: a seam above that layer drags HTTP,
|
|
244
|
+
auth and Express into the fixture without adding a single business input.
|
|
245
|
+
|
|
246
|
+
Read the recording again first, filtered to the state-changing 2xx calls — OPTIONS, 304s and polling
|
|
247
|
+
GETs carried nothing. A `202` is worth stopping on: it means the work is fire-and-forget, so the
|
|
248
|
+
response body is not the outcome and the seam does not await it. Name the signal a test polls for
|
|
249
|
+
completion instead, or the test asserts on a workflow that hasn't run yet.
|
|
250
|
+
|
|
251
|
+
- **Input seam** — the narrowest already-exported function with every external input on its input
|
|
252
|
+
side. Count what it fetches, reads and imports, not just its parameters: an env var, a module-level
|
|
253
|
+
client and a database read are all things the test has to control, and they don't appear in a
|
|
254
|
+
signature.
|
|
255
|
+
- **Output seam** — where every outcome becomes durable, refusals included. Read the `catch` block;
|
|
256
|
+
that is usually where the refusal is written, and a seam that only sees OUTCOME 1 can never assert
|
|
257
|
+
OUTCOME 2.
|
|
258
|
+
- **Reject any seam the refactor would dissolve.** Pure helpers die under a refactor — that is what
|
|
259
|
+
the refactor is for. The orchestrator entry and the terminal write survive it, which is exactly
|
|
260
|
+
what makes them seams and a well-named private helper not one.
|
|
261
|
+
- **Grep every call site of the output seam** and say what distinguishes the in-graph ones. A durable
|
|
262
|
+
write is usually shared with unrelated code, and a test asserting that a save happened has proved
|
|
263
|
+
nothing about this workflow.
|
|
264
|
+
- **Read the seam's body before committing to it.** Retry loops and pruning ladders mutate the
|
|
265
|
+
payload between attempts, and they will silently void the assertions you are about to plan.
|
|
266
|
+
|
|
267
|
+
**Then map every node onto the output seam.** Take each node's `emits` and name the field on the
|
|
268
|
+
seam's payload that carries it. This mapping is the check — it is why no critic round is spent here.
|
|
269
|
+
A node that will not map means one of two things, and which one matters: either the seam is in the
|
|
270
|
+
wrong place, or nobody implemented that node. Say which. An unimplemented node is the most valuable
|
|
271
|
+
thing this step turns up, and the graph is the only reason anyone noticed it.
|
|
272
|
+
|
|
273
|
+
Write the two sections tight — the node table is where length is earned, not here. Each seam is
|
|
274
|
+
`name(signature)` with `file:line`, one sentence on why this one and not the runner-up you rejected,
|
|
275
|
+
then bullets: for the input seam one per external input, saying what it is, how it arrives and which
|
|
276
|
+
node it feeds; for the output seam one per node, naming the field that carries its `emits`. Cite
|
|
277
|
+
`file:line` for every claim — a seam named without a line number is a guess, and whoever writes the
|
|
278
|
+
test finds that out the expensive way.
|
|
279
|
+
|
|
280
|
+
## 7. Write the artifact and stop
|
|
281
|
+
|
|
282
|
+
Write the six-section file described under **Output**. Then say in chat — not in the file — how many
|
|
283
|
+
rounds the critic loop ran and anything the last round still noted.
|
|
284
|
+
|
|
285
|
+
Then stop. Don't start the refactor, don't sketch a file layout, don't rename anything, and don't
|
|
286
|
+
write the test.
|
|
287
|
+
|
|
288
|
+
## Anti-patterns
|
|
289
|
+
|
|
290
|
+
- Starting without the recording, and modelling a path that no longer runs.
|
|
291
|
+
- Drafting the goal or the nodes before the user has confirmed your understanding.
|
|
292
|
+
- Building the graph from function names or the call chain.
|
|
293
|
+
- A decomposition rather than a workflow — parts of the system with no order, no start and no
|
|
294
|
+
outcome, so nothing in it could ever be said to happen too late.
|
|
295
|
+
- A node that only moves data from one place to another.
|
|
296
|
+
- Table cells grown into paragraphs, so the row stops being scannable and the rules stop being
|
|
297
|
+
findable.
|
|
298
|
+
- Treating a convenience (dropping noisy rows to save typing) as an invariant.
|
|
299
|
+
- A refusal path that stops without a stated outcome the user can act on.
|
|
300
|
+
- Declaring convergence yourself instead of letting the critic do it.
|
|
301
|
+
- Running a fifth round because the fourth critic had one more thought. Past the ceiling, remaining
|
|
302
|
+
defects get reported, not fixed.
|
|
303
|
+
- Creating a seam — exporting a private helper — rather than finding one that already exists.
|
|
304
|
+
- An output seam that only sees the success path, leaving the refusal outcome unassertable.
|
|
305
|
+
- Hunting for seams before the critic has converged, pinning them to a graph still in motion.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Briefing and running the critic
|
|
2
|
+
|
|
3
|
+
Read this when you reach step 5. It covers what to hand a critic, how many to run, what to ask them
|
|
4
|
+
for, and why the loop is capped.
|
|
5
|
+
|
|
6
|
+
## What the loop is for
|
|
7
|
+
|
|
8
|
+
**Every business goal is achieved by a workflow, and the graph represents that workflow.** The
|
|
9
|
+
critic certifies both links:
|
|
10
|
+
|
|
11
|
+
- **goal → workflow.** Every clause of the 50-word sentence is achieved by a step; every step earns
|
|
12
|
+
its place from that sentence. Checklist item 1.
|
|
13
|
+
- **workflow → graph.** The drawing and the edge list are a faithful, ordered picture of that
|
|
14
|
+
workflow, with a start, a run and an outcome. Checklist item 5.
|
|
15
|
+
|
|
16
|
+
The nodes, edges and graph are not three things — they are one workflow written three ways. The
|
|
17
|
+
remaining checks exist because a workflow that is mis-scoped, at the wrong granularity, or made of
|
|
18
|
+
mechanism cannot be judged against a business goal in the first place.
|
|
19
|
+
|
|
20
|
+
Say this to the critic in as many words. A critic that is not told what it is deciding falls back on
|
|
21
|
+
generic code-review instincts and returns a list of things it would have written differently.
|
|
22
|
+
|
|
23
|
+
## What the critic gets
|
|
24
|
+
|
|
25
|
+
Give it:
|
|
26
|
+
|
|
27
|
+
- the business goal
|
|
28
|
+
- the node table, **including the rule footnotes** (`R1`, `R2`…)
|
|
29
|
+
- the edge list
|
|
30
|
+
- the graph
|
|
31
|
+
- one paragraph of domain background, so it can make judgment calls about the business
|
|
32
|
+
- the repo, to check a claim against
|
|
33
|
+
|
|
34
|
+
The critic may read the code. It should not review it. The distinction is the whole job: it is
|
|
35
|
+
deciding whether this model represents the business, and a claim it cannot check is a claim it can
|
|
36
|
+
only test for internal tidiness. A critic that starts listing what it would change about the code has
|
|
37
|
+
drifted — the model is the subject, the code is the evidence.
|
|
38
|
+
|
|
39
|
+
Be aware that the paragraph of background is written by you, the author of the model under review, so
|
|
40
|
+
it can smuggle in the assumption being tested. That is a second reason the critic needs the repo.
|
|
41
|
+
|
|
42
|
+
Spawn a **fresh** critic each round. Continuing the previous one anchors it to its own last verdict;
|
|
43
|
+
a new one re-reads with clean eyes and finds different defects.
|
|
44
|
+
|
|
45
|
+
## Where the rules live
|
|
46
|
+
|
|
47
|
+
Node cells carry a clause; the rule itself lives in the footnote the cell points at. So a cell
|
|
48
|
+
reading "fills in the quantity the customer asked for, and nothing else (R1, R2)" is judged by R1 and
|
|
49
|
+
R2, not by the cell alone. Footnotes are in scope for every checklist item, and a critic names one by
|
|
50
|
+
its id when the defect is there.
|
|
51
|
+
|
|
52
|
+
## Round 1: three critics, concurrently
|
|
53
|
+
|
|
54
|
+
Different critics find different defects. This used to cost five rounds; buy the variety all at once
|
|
55
|
+
instead. **Spawn three critics in a single message containing three tool calls, so they run
|
|
56
|
+
concurrently.**
|
|
57
|
+
|
|
58
|
+
Give each the whole checklist, but tell each to lead with a different part:
|
|
59
|
+
|
|
60
|
+
| critic | leads with | checklist items |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| A | coverage and scope | 1, 6 |
|
|
63
|
+
| B | self-contradiction and mechanism leaks | 2, 3 |
|
|
64
|
+
| C | granularity, graph integrity, hidden assumptions | 4, 5, 7 |
|
|
65
|
+
|
|
66
|
+
Splitting the emphasis is what stops all three sharing a blind spot, which three identically-prompted
|
|
67
|
+
critics would.
|
|
68
|
+
|
|
69
|
+
Merge their findings **by defect, not by critic**: two critics naming the same node is one entry, not
|
|
70
|
+
two. The one-line defect format below is what makes this a deduplication rather than a second act of
|
|
71
|
+
synthesis.
|
|
72
|
+
|
|
73
|
+
**When two critics contradict each other** — one says a node is a mechanism leak, another says it
|
|
74
|
+
carries a real business rule — that is not a merge, and it is not yours to average. Go to the code
|
|
75
|
+
and to the goal sentence and settle which is true. A contradiction between two readers of the same
|
|
76
|
+
model is the loop working: it has found a place where the model is ambiguous enough to support both
|
|
77
|
+
readings, and the resolution belongs in the text so the next reader cannot make the same mistake.
|
|
78
|
+
|
|
79
|
+
**Check you actually have concurrency.** If you have no subagent tool and are emulating critics with
|
|
80
|
+
separate shell invocations, they will run one after another — and three critics back to back cost
|
|
81
|
+
what three rounds cost while telling you less. In that case spawn **one critic per round**, not
|
|
82
|
+
three.
|
|
83
|
+
|
|
84
|
+
Round 2 onward is a single critic with no seeded emphasis, judging the whole checklist against your
|
|
85
|
+
revision.
|
|
86
|
+
|
|
87
|
+
## The checklist
|
|
88
|
+
|
|
89
|
+
Have the critic work through all seven, whatever it was told to lead with:
|
|
90
|
+
|
|
91
|
+
1. **Coverage, both ways — does the workflow achieve the goal?** Every clause of the goal is *done*
|
|
92
|
+
by a step — and no step asserts a rule the goal gives no support for. Check the clause against the
|
|
93
|
+
step's `decides` and `refuses when` cells and the footnotes they point at, **never against its
|
|
94
|
+
name**. A step named for a goal clause whose decision does something else passes a name check and
|
|
95
|
+
fails the business; that is the defect this item exists to catch.
|
|
96
|
+
2. **Self-contradiction.** Does any node's stated invariant survive the inputs it is actually handed?
|
|
97
|
+
This catches the most valuable class of defect: a commitment step that promises "every line, with
|
|
98
|
+
its photo" when an upstream filter already removed some.
|
|
99
|
+
3. **Mechanism leaks.** Any node that is really storage, transport, authorization, a vendor, or a
|
|
100
|
+
file format wearing a business hat.
|
|
101
|
+
4. **Granularity.** One node bundling three rules while another splits one rule across two.
|
|
102
|
+
5. **Graph integrity — is the drawing the workflow?** Every declared input produced by an incoming
|
|
103
|
+
edge; every step reachable from an external input; every path ending in a stated outcome; the
|
|
104
|
+
drawing matching the edge list exactly. And is this a workflow at all, or a decomposition wearing
|
|
105
|
+
arrows — steps with no order between them, or a set of parts of the system rather than a run from
|
|
106
|
+
input to outcome?
|
|
107
|
+
6. **Scope.** Nothing straying past the stated finish line, nothing stopping short of it.
|
|
108
|
+
7. **Hidden assumptions** a reader would need told.
|
|
109
|
+
|
|
110
|
+
## What the verdict means
|
|
111
|
+
|
|
112
|
+
Tell the critic this, or it will never give you one. The bar for TRUE is that **every clause of the
|
|
113
|
+
goal is achieved by a step, every step earns its place from the goal, and the drawing is that
|
|
114
|
+
workflow** — *not* that the model is beyond improvement. Every model is beyond improvement; a critic holding out for that answers FALSE
|
|
115
|
+
forever, and you find yourself on round nine of a loop that was right at round three.
|
|
116
|
+
|
|
117
|
+
So: if the remaining remarks are things the critic would mention in review but merge anyway, that is
|
|
118
|
+
`VERDICT: TRUE` with the remarks listed under it.
|
|
119
|
+
|
|
120
|
+
## Response format
|
|
121
|
+
|
|
122
|
+
Ask for exactly this, and nothing else:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
HOLDS: <checklist numbers that pass, and the nodes already right — names only, no explanation>
|
|
126
|
+
|
|
127
|
+
<checklist#> <subject> — <the defect>
|
|
128
|
+
<checklist#> <subject> — <the defect>
|
|
129
|
+
...
|
|
130
|
+
|
|
131
|
+
VERDICT: TRUE
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`<subject>` is a node name, an edge id (`E4`), a rule footnote id (`R2`), or **`GOAL`** for a defect
|
|
135
|
+
in the goal sentence itself — a clause with no home in any node, a clause the graph contradicts, or a
|
|
136
|
+
rule the graph enforces that the sentence never licenses. Given what this loop is for, `GOAL` defects
|
|
137
|
+
are the most important ones available, and without a subject to file them under they get quietly
|
|
138
|
+
rewritten as complaints about whichever node happened to be nearest.
|
|
139
|
+
|
|
140
|
+
No preamble, no summary, no restating your model back to you. You wrote it; you don't need it read
|
|
141
|
+
aloud. The verdict is a bare final line.
|
|
142
|
+
|
|
143
|
+
Two instructions matter as much as the checklist itself:
|
|
144
|
+
|
|
145
|
+
- **Don't manufacture defects to appear rigorous.**
|
|
146
|
+
- **Name what already passes**, so the next revision doesn't break it. Without the `HOLDS:` line,
|
|
147
|
+
revisions oscillate and you fix defect 3 while reintroducing defect 1.
|
|
148
|
+
|
|
149
|
+
## Why the loop is capped
|
|
150
|
+
|
|
151
|
+
A competent critic can always find *something* to say about a ten-node graph, so "loop until a round
|
|
152
|
+
comes back clean" is a loop with no reliable exit. Runs left open-ended have gone ten rounds and
|
|
153
|
+
taken an hour to land where round three already was.
|
|
154
|
+
|
|
155
|
+
Two rounds is the normal case; four is the hard ceiling. Don't stop at one — a lone TRUE is as likely
|
|
156
|
+
to mean an agreeable critic as a correct graph, and that holds even when all three round-1 critics
|
|
157
|
+
return TRUE: run round 2 against the merged revision anyway, then take the verdict.
|
|
158
|
+
|
|
159
|
+
If defects remain when round four ends, that is a genuine finding: report them to the user as open
|
|
160
|
+
questions. It is not an instruction to keep going. Three honestly-recorded open questions are worth
|
|
161
|
+
far more than an hour of polish.
|
|
162
|
+
|
|
163
|
+
Between the floor and the ceiling, stop as soon as a round raises no defect that would change a node,
|
|
164
|
+
an edge, or a clause of the goal. Wording preferences and "you could also mention" notes are not
|
|
165
|
+
defects.
|
|
166
|
+
|
|
167
|
+
On FALSE, revise the goal, node and edge text. Most of what a critic finds are internal-consistency
|
|
168
|
+
defects your own notes already answer, and those never need the repo. When it disputes a specific
|
|
169
|
+
factual claim you can't settle from memory, go back — to that one function, not to the codebase.
|
|
170
|
+
Re-reading everything once per round is the most expensive habit available here and it buys nothing.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: system-resource-triage
|
|
3
|
+
description: Diagnose why a Linux box is slow, out of memory, or showing high load, explain the cause in two or three lines, propose a fix, offer to apply it, and report a before/after table. Use this whenever the user asks about CPU or memory utilisation, says the machine or dev box feels slow, sluggish or laggy, asks what is eating their RAM or CPU, mentions high load average, full swap, OOM kills, runaway or leaked processes, too many open processes, or zombies — and also when they simply paste top/htop/free/ps output and ask what is going on. It exists because the obvious readings mislead — ps %CPU is a lifetime average rather than current usage, load average is not the same as CPU busy, and per-process views hide problems that only show up in aggregate.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# System resource triage
|
|
7
|
+
|
|
8
|
+
## What this is for
|
|
9
|
+
|
|
10
|
+
Someone says "my machine is slow" or "check my CPU and memory". The naive answer is to run `top`,
|
|
11
|
+
read off the first row, and name whatever sits at the top. That answer is usually wrong, and
|
|
12
|
+
confidently wrong, because the default readings on a long-uptime box are averages over the life of
|
|
13
|
+
the process rather than a description of now.
|
|
14
|
+
|
|
15
|
+
This skill produces a short honest diagnosis, a proposed fix, and — if the user accepts — a
|
|
16
|
+
measured before/after. The value is mostly in not being fooled during the measurement, and in not
|
|
17
|
+
destroying something the user still needs during the fix.
|
|
18
|
+
|
|
19
|
+
## Shape of the interaction
|
|
20
|
+
|
|
21
|
+
Five beats, in order. Don't merge them and don't skip the pause.
|
|
22
|
+
|
|
23
|
+
1. **Measure** — one pass, cheap, read-only.
|
|
24
|
+
2. **Explain** — two or three lines. Not a report.
|
|
25
|
+
3. **Suggest** — the specific fix, and what it will reclaim.
|
|
26
|
+
4. **Offer** — stop and wait for a yes before touching anything.
|
|
27
|
+
5. **Before/after** — a table, from numbers you captured *before* you acted.
|
|
28
|
+
|
|
29
|
+
The pause at step 4 is the point. Freeing memory means killing processes, and the user is the only
|
|
30
|
+
one who knows whether the thing you're about to kill matters.
|
|
31
|
+
|
|
32
|
+
## Step 1: Measure
|
|
33
|
+
|
|
34
|
+
Run `scripts/triage.sh`. It's read-only and takes a few seconds. It gathers everything below in one
|
|
35
|
+
pass, which matters for a reason explained in the next section.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
bash scripts/triage.sh # group memory by process name
|
|
39
|
+
bash scripts/triage.sh claude node # or group by patterns matched against full command line
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Pass patterns when process names are uninformative — VS Code's server processes are all called
|
|
43
|
+
`MainThread`, so grouping by name tells you nothing and grouping by `vscode-server` tells you
|
|
44
|
+
everything.
|
|
45
|
+
|
|
46
|
+
## Reading the numbers without being fooled
|
|
47
|
+
|
|
48
|
+
These are the traps. Each has bitten a real diagnosis.
|
|
49
|
+
|
|
50
|
+
**`ps %CPU` is a lifetime average, not current usage.** It is total CPU consumed divided by process
|
|
51
|
+
age. On a box up 64 days, long-lived daemons like `containerd` and `dockerd` routinely show 60-80%
|
|
52
|
+
while using nothing at all right now. If you name them as the culprit you will be wrong. Take
|
|
53
|
+
instantaneous CPU from the *second* sample of `top -bn2`.
|
|
54
|
+
|
|
55
|
+
**The first row of `vmstat` is also a since-boot average.** Discard it. Always read row two onward.
|
|
56
|
+
|
|
57
|
+
**Load average is not "CPU busy".** It counts runnable *and* uninterruptible processes. High load
|
|
58
|
+
with high idle means the load is coming from somewhere other than CPU work. Decompose it before
|
|
59
|
+
concluding anything:
|
|
60
|
+
|
|
61
|
+
- `wa` high, processes in `D` state → I/O or swap thrashing.
|
|
62
|
+
- `r` persistently above core count → genuine CPU contention.
|
|
63
|
+
- both low, `cs` very high → scheduler churn, often just many idle pollers. Frequently harmless.
|
|
64
|
+
- Load average is a decaying 1/5/15-minute mean, so it lags a fix by minutes. Don't judge a fix by
|
|
65
|
+
it immediately; `free` and `r` respond right away.
|
|
66
|
+
|
|
67
|
+
**Aggregate before you conclude.** This is the single highest-value move. Forty-five processes at
|
|
68
|
+
340 MB each never appear in `top`'s top ten, but they are 15 GB. Problems that live in the count
|
|
69
|
+
rather than the size are invisible per-process and obvious in aggregate. The script does this
|
|
70
|
+
grouping for you.
|
|
71
|
+
|
|
72
|
+
**Read swap per process, not just in total.** `free` says swap is full; `/proc/PID/status`'s
|
|
73
|
+
`VmSwap` says who put it there. A process swapped fully out shows near-zero RSS and looks innocent.
|
|
74
|
+
|
|
75
|
+
**Your own measuring can create the symptom.** A loop that spawns a subprocess per PID across 1500
|
|
76
|
+
PIDs generates tens of thousands of context switches and inflates the run queue — you then read
|
|
77
|
+
that back and diagnose it as the problem. Prefer one `awk` pass over `/proc/*/status` to a shell
|
|
78
|
+
loop, and if you see a run queue spike only while your own diagnostic runs, that's you. Re-measure
|
|
79
|
+
with nothing else running before you believe a churn number.
|
|
80
|
+
|
|
81
|
+
**Check zombies.** They cost no RAM or CPU, so they never surface in a memory hunt, but a large
|
|
82
|
+
count means a parent isn't reaping and PID slots are leaking. The classic cause is a container
|
|
83
|
+
whose PID 1 is `sleep infinity`, which never calls `wait()`. Group zombies by PPID to find the
|
|
84
|
+
offender; the fix is giving that container a real init (`init: true`), not killing anything.
|
|
85
|
+
|
|
86
|
+
## Step 2: Explain, in two or three lines
|
|
87
|
+
|
|
88
|
+
Lead with which resource is actually constrained, name the cause, and give the number that proves
|
|
89
|
+
it. If CPU is fine, say so first — it stops the user chasing it.
|
|
90
|
+
|
|
91
|
+
> CPU is fine — 63% idle, no iowait. The problem is memory: 26 of 30 GB used and swap completely
|
|
92
|
+
> full. 45 abandoned `claude` sessions, 2-21 days old with no terminal attached, account for
|
|
93
|
+
> 15.5 GB of it.
|
|
94
|
+
|
|
95
|
+
Resist expanding this. The evidence goes in the table later; anything you cut here the user can ask
|
|
96
|
+
for. If you found something real but off-topic — leaked zombies, a container misconfiguration —
|
|
97
|
+
hold it until after the main fix rather than diluting the headline.
|
|
98
|
+
|
|
99
|
+
## Step 3: Suggest
|
|
100
|
+
|
|
101
|
+
Name the specific action and what it reclaims. Prefer the smallest action with the largest return,
|
|
102
|
+
and say what you are deliberately *not* touching, so the user can object.
|
|
103
|
+
|
|
104
|
+
> Suggest SIGTERM on those 28 detached sessions — should return ~12 GB and drain most of swap. I'd
|
|
105
|
+
> leave the VS Code servers alone since those are likely your live editor windows.
|
|
106
|
+
|
|
107
|
+
If there are stages, order them most-reclaim-for-least-risk and plan to stop as soon as enough is
|
|
108
|
+
free. Running stage 3 when stage 1 sufficed is how a routine cleanup becomes an outage.
|
|
109
|
+
|
|
110
|
+
## Step 4: Offer, then act safely
|
|
111
|
+
|
|
112
|
+
Ask, and wait. Once the user agrees:
|
|
113
|
+
|
|
114
|
+
**Capture the "before" numbers first.** You cannot reconstruct them afterwards and the table is
|
|
115
|
+
part of the deliverable. `scripts/triage.sh --snapshot /tmp/before.txt` saves them.
|
|
116
|
+
|
|
117
|
+
**Dry run and show the list.** `scripts/reap.sh --name <pattern>` prints candidates and totals;
|
|
118
|
+
nothing dies without `--confirm`. Let the user see actual PIDs and ages first.
|
|
119
|
+
|
|
120
|
+
It only ever selects processes that are detached, older than `--min-age-days` (default 2), and
|
|
121
|
+
owned by the current user. Kernel threads, init, other users' daemons, and zombies are excluded —
|
|
122
|
+
a candidate list containing `dockerd` or `systemd` is a bug, and zombies are worth excluding
|
|
123
|
+
because they hold no memory, so counting them inflates the reclaim estimate for no gain.
|
|
124
|
+
|
|
125
|
+
**Kill the list you showed, verbatim.** Recomputing the candidate set at kill time reintroduces
|
|
126
|
+
everything the review was meant to catch. Paste the reviewed PIDs.
|
|
127
|
+
|
|
128
|
+
**Never kill your own session.** Walk `/proc/PID/status`'s `PPid` up from `$$` and exclude every
|
|
129
|
+
ancestor. `reap.sh` does this and refuses to run if a protected PID appears in the list. Processes
|
|
130
|
+
with a controlling terminal are attached to something a human is using — exclude those too.
|
|
131
|
+
|
|
132
|
+
**SIGTERM, wait, then reconsider.** TERM lets sessions flush state to disk. Wait ~10 seconds and
|
|
133
|
+
re-check. `kill -9` only for genuine stragglers, and it's worth asking again first.
|
|
134
|
+
|
|
135
|
+
**In zsh, `kill $PIDS` fails.** zsh doesn't word-split unquoted variables, so a space-separated PID
|
|
136
|
+
list is passed as one argument and the whole kill is rejected — easy to misread as success if you
|
|
137
|
+
echo a count afterwards. Loop over the list, or use `${=PIDS}`. The scripts here use `bash`
|
|
138
|
+
explicitly to sidestep this.
|
|
139
|
+
|
|
140
|
+
**Reclaim swap last, and only with headroom.** Swap usually drains on its own as processes exit.
|
|
141
|
+
If stale pages remain, `swapoff -a && swapon -a` forces them back to RAM — which OOMs the box if
|
|
142
|
+
RAM isn't free yet. Verify free RAM exceeds used swap before running it, and skip it entirely if
|
|
143
|
+
swap is already comfortable.
|
|
144
|
+
|
|
145
|
+
## Step 5: Before/after table
|
|
146
|
+
|
|
147
|
+
Re-measure and report. Keep it to the metrics that moved.
|
|
148
|
+
|
|
149
|
+
```markdown
|
|
150
|
+
| | Before | After |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| RAM used | 26 Gi / 30 Gi | 14 Gi / 30 Gi |
|
|
153
|
+
| Available | 4.6 Gi | 15 Gi |
|
|
154
|
+
| Swap | 4.0 Gi (100%) | 815 Mi (20%) |
|
|
155
|
+
| Load (1m) | 8.30 | 5.91 |
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Add one line on what you skipped and why ("swap drained on its own, so I didn't need `swapoff`"),
|
|
159
|
+
and surface any secondary finding you held back.
|
|
160
|
+
|
|
161
|
+
## Say so when a prediction misses
|
|
162
|
+
|
|
163
|
+
If you predicted a number would move and it didn't, lead with that rather than letting the table
|
|
164
|
+
quietly omit it. Concretely: context switches staying at 60-80k/s after removing 28 processes
|
|
165
|
+
falsifies "idle pollers cause the churn", and the honest follow-up is a quick check of
|
|
166
|
+
`/proc/interrupts` — high `CAL` and `TLB` on a KVM guest is normal hypervisor overhead, not
|
|
167
|
+
something to chase.
|
|
168
|
+
|
|
169
|
+
A fix that worked for a reason you got wrong is worth flagging, because the user will otherwise
|
|
170
|
+
apply the wrong lesson next time. It also stops you from proposing the same wrong fix again.
|
|
171
|
+
|
|
172
|
+
## Scope
|
|
173
|
+
|
|
174
|
+
This covers diagnosis and reclaiming resources on a machine the user controls. Application-level
|
|
175
|
+
memory profiling (heap dumps, leak hunting inside one process) is a different job — say so and
|
|
176
|
+
stop rather than stretching this to fit.
|
|
177
|
+
|
|
178
|
+
Two things are worth naming as out of scope even when they'd help, because they change the
|
|
179
|
+
machine's configuration rather than its current state: restarting containers and editing service
|
|
180
|
+
definitions. Report them as findings with the specific fix, and let the user decide.
|