@thebattlearena/corner 0.9.1-beta.70 → 0.10.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/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/ring/agents/cornerman.md +20 -3
- package/ring/agents/wrestler.md +11 -0
- package/ring/hooks/hooks.json +20 -0
- package/ring/scripts/bout-stats-render.mjs +366 -0
- package/ring/scripts/bout-stats.mjs +360 -0
- package/ring/scripts/config.mjs +1 -1
- package/ring/scripts/contract-endpoints.mjs +163 -0
- package/ring/scripts/contract-preview.mjs +34 -14
- package/ring/scripts/fight.mjs +27 -0
- package/ring/scripts/findings.mjs +3 -1
- package/ring/scripts/format-gate.mjs +723 -0
- package/ring/scripts/format-worker.mjs +120 -0
- package/ring/scripts/front-routes.mjs +345 -0
- package/ring/scripts/judges-card.mjs +324 -3
- package/ring/scripts/lookout.mjs +22 -4
- package/ring/scripts/mask-guard.mjs +34 -1
- package/ring/scripts/page-embed.mjs +112 -0
- package/ring/scripts/play-by-play.mjs +155 -7
- package/ring/scripts/preparation-collect.mjs +177 -0
- package/ring/scripts/preparation.mjs +547 -0
- package/ring/scripts/round-bell.mjs +9 -2
- package/ring/scripts/tech-plan-log.mjs +81 -0
- package/ring/scripts/tech-plan.mjs +191 -0
- package/ring/scripts/verdicts-log.mjs +75 -0
- package/ring/scripts/verdicts.mjs +205 -0
- package/ring/skills/play-by-play/SKILL.md +235 -33
- package/ring/skills/play-by-play/templates/blocks.css +196 -0
- package/ring/skills/play-by-play/templates/chronicle.html +358 -55
- package/ring/skills/play-by-play/templates/endpoints-view.js +1153 -0
- package/ring/skills/play-by-play/templates/interview-form.js +516 -0
- package/ring/skills/play-by-play/templates/now-panel.js +719 -0
- package/ring/skills/referee/SKILL.md +136 -42
- package/ring/skills/referee/references/api-diagram.md +56 -0
- package/ring/skills/referee/references/precedents.md +11 -0
- package/ring/skills/referee/references/rulebook.md +65 -4
- package/ring/skills/referee/templates/api-diagram.html +115 -0
- package/ring/skills/referee/templates/escalation.md +7 -1
- package/ring/skills/referee/templates/round-bell-body.md +4 -0
- package/ring/skills/referee/templates/wrestler-brief.md +3 -0
- package/ring/skills/sparring/SKILL.md +10 -2
- package/ring/skills/sparring/templates/contrato.md +29 -0
- package/ring/skills/sparring/templates/rudo-brief.md +7 -0
- package/ring/skills/weigh-in/SKILL.md +6 -0
|
@@ -39,7 +39,7 @@ list reaches the human.
|
|
|
39
39
|
too; each venue rulebook says which core families apply there. The review lenses of the venue
|
|
40
40
|
are `config.lenses`.
|
|
41
41
|
5. **State lives in `~/.claude/ring/<owner>/<repo>/<pr>/`** (`node "$RING/scripts/judges-card.mjs"
|
|
42
|
-
|
|
42
|
+
path <pr>`; owner and repo lowercased, `local/<name>` for a repo without an origin remote;
|
|
43
43
|
`RING_HOME` overrides the root), never in the session scratchpad: the scratchpad is wiped when
|
|
44
44
|
the session restarts. A bout in the old flat layout (`<owner>-<repo>/<pr>/`) is moved there the
|
|
45
45
|
first time a script resolves it; if both exist, the new one wins and the old one is reported on
|
|
@@ -59,7 +59,7 @@ list reaches the human.
|
|
|
59
59
|
doubt, prefer the option that preserves current behavior and wire contracts (PR11) and ticket
|
|
60
60
|
the rest. Record each decision with
|
|
61
61
|
`judges-card.mjs log <pr> decision "<id> · referee · <decision> · rests on <R/T/F/P, PRn, HPn>
|
|
62
|
-
|
|
62
|
+
· discarded <alternative> · affects <area>"`, list it in the judges card under "Decisions I
|
|
63
63
|
took for you", and keep going.
|
|
64
64
|
- **`human`**: escalate both lists, as the rulebook describes.
|
|
65
65
|
- **The hard list always goes to the human**: merging, bases, closing or readying PRs,
|
|
@@ -67,9 +67,10 @@ list reaches the human.
|
|
|
67
67
|
assignment did not ask for (including a base assertion customers would see); a PR over the
|
|
68
68
|
host's size ceiling (how to slice it and any exception); **a new or changed endpoint in the
|
|
69
69
|
API spec, a changed database model, or a change to the native surface of a mobile venue**
|
|
70
|
-
|
|
70
|
+
(§2b); customer data or PII, money or billing,
|
|
71
71
|
production; anything `mask-guard` blocks; a direct contradiction between two host
|
|
72
|
-
instructions; a PR whose venue is in doubt (§1.2)
|
|
72
|
+
instructions; a PR whose venue is in doubt (§1.2); a deviation from a pattern the host's own
|
|
73
|
+
rules fix (P14), which you never approve as a design doubt.
|
|
73
74
|
9. **Escalating to the human** (the hard list, size ceiling included, or anything under `human`):
|
|
74
75
|
numbered text, two options each with its cost and your recommendation, answerable as "1. b"
|
|
75
76
|
(`templates/escalation.md`). Use AskUserQuestion only when the host repo's instructions require
|
|
@@ -103,9 +104,19 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
103
104
|
- **What the judge validated is the behavior that must not change**: write it as numbered
|
|
104
105
|
invariants for the concept-mode cornerman, and add characterization tests first (T rules).
|
|
105
106
|
- **The rudo's shortcuts for this repo are the first rebound package**, blockers first.
|
|
106
|
-
- **The
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
- **The bases go to the judge first.** The contracts decide most of the code still to build, so
|
|
108
|
+
before launching the wrestler (step 8) gather every endpoint and data model the sparring
|
|
109
|
+
proposed: every `<sparring dir>/contrato-<repo>.md` (one per repo; read them together, in repo
|
|
110
|
+
order), checked against the branch (`gh pr diff <pr>`: spec,
|
|
111
|
+
entities, schema, migrations, and the `tools/*.sql` the tables came from). Draw them with the
|
|
112
|
+
ring's diagrams: the endpoints per `references/api-diagram.md` into `<bout dir>/api-diagram.html`
|
|
113
|
+
and the data models per `references/db-diagram.md` into `<bout dir>/db-diagram.html`, each with
|
|
114
|
+
the rudo's shortcuts written as decisions to validate. Serve them with `contract-preview.mjs`
|
|
115
|
+
(§2b step 4) and escalate them as the bout's first question, one numbered decision per
|
|
116
|
+
endpoint or table. Nothing of it is approved because the sparring used it: each goes through
|
|
117
|
+
§2b and `approve-contract`, and concepts that depend on a contract wait for it, while the
|
|
118
|
+
shortcuts that do not can start. Its credentials (by name) are a hard-list item: taking a
|
|
119
|
+
sandbox key's variable to production is the human's.
|
|
109
120
|
- **Open it with `--from-sparring <slug>`** (step 5): `judges-card.mjs open` refuses a sparring
|
|
110
121
|
that is not a KO, records `fromSparring` and marks the hand-off on the sparring. The bout is then
|
|
111
122
|
the third fall of the sparring's chronicle: one page and one link for the whole fight
|
|
@@ -122,7 +133,6 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
122
133
|
rebound changes them. Starting the cleanup before that escalation is a foul; log it in the
|
|
123
134
|
judges card.
|
|
124
135
|
|
|
125
|
-
|
|
126
136
|
1. `gh pr view <pr> --json number,title,url,headRefName,baseRefName,files`. The **stack base** is
|
|
127
137
|
`baseRefName` unless the human names another one; ask if the PR is part of a stack.
|
|
128
138
|
2. **Venue.** `gh pr diff <pr> --name-only | node "$RING/scripts/config.mjs" venue`, or
|
|
@@ -137,7 +147,7 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
137
147
|
`git worktree add --detach <abs path> origin/<headRefName>` (after `git fetch origin`). Never
|
|
138
148
|
launch the wrestler with `isolation: "worktree"`: that creates another tree on another branch.
|
|
139
149
|
5. Open the bout: `node "$RING/scripts/judges-card.mjs" open --pr <pr> --worktree <abs path>
|
|
140
|
-
|
|
150
|
+
--branch <headRefName> --base <stack base> --venue <venue> [--from-sparring <slug>]`. This activates `mask-guard` for this repo.
|
|
141
151
|
It refuses to open when `.claude/ring.json` leaves `apiSpec` or `dbModels` empty while the repo
|
|
142
152
|
has specs or migrations: fix the config (paths or globs; `null` means "detect") rather than
|
|
143
153
|
passing `--allow-empty-contract`, which is only for a bout that truly has no contract. Then
|
|
@@ -146,12 +156,13 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
146
156
|
6. **Gather the assignment**: review comments (`gh api repos/{owner}/{repo}/pulls/<pr>/comments`,
|
|
147
157
|
`gh pr view <pr> --comments`) and what the human said. Every decision or preference goes to
|
|
148
158
|
`judges-card.mjs log <pr> decision "<id> · <who> · <decision> · <affects>"`.
|
|
149
|
-
7. **Design review before touching code** (P5), when the
|
|
159
|
+
7. **Design review before touching code** (P5), always when the PR creates a module or an
|
|
160
|
+
aggregate, and otherwise when the change is large or the human asks: launch
|
|
150
161
|
cornermen in **batch** mode in parallel, ≤20 files each (`templates/cornerman-batch.md`),
|
|
151
162
|
`effort: "high"`. Decide their open questions yourself under `referee` (recorded as in §0.8);
|
|
152
163
|
bring the human only the hard-list ones, or all of them under `human`.
|
|
153
164
|
8. **Launch one wrestler**: `Agent{subagent_type: "ring:wrestler", effort: "medium",
|
|
154
|
-
|
|
165
|
+
run_in_background: true, prompt: <templates/wrestler-brief.md filled>}`. The first concept is a
|
|
155
166
|
**pilot**: one small concept as a sample for the human. Note the agent id in the judges card
|
|
156
167
|
("What I did"). If the harness exposes how the subagent ran, check it ran at medium.
|
|
157
168
|
Give every Agent call a short `description` (its first three words label its chip in Ringside);
|
|
@@ -171,11 +182,28 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
171
182
|
- when the wrestler closes a concept: `templates/cornerman-concept.md` (numbered behavior
|
|
172
183
|
invariants, tests on a `git archive` copy), over ranges already reviewed one by one.
|
|
173
184
|
If the wrestler claimed something ("does not change counter X"), hand the claim to the
|
|
174
|
-
cornerman to verify against the base.
|
|
185
|
+
cornerman to verify against the base. The cornerman always checks the format of the range
|
|
186
|
+
(`format-gate.mjs check`); an unclean file is a finding like any other, fixed by the wrestler
|
|
187
|
+
with `format-gate.mjs fix <wt> --range <base>..HEAD`. A check that comes back **NO VERIFICADO**
|
|
188
|
+
(exit 2: sort-imports or prettier not installed in the repo) is never clean: register it as a
|
|
189
|
+
finding of the range (the repo lacks its format tooling), and settle it by having the
|
|
190
|
+
dependencies installed in the worktree, or by escalating if the repo has none.
|
|
191
|
+
**The scripts enforce it, not memory:** `lookout.mjs approve`, `round-bell.mjs open`,
|
|
192
|
+
`judges-card.mjs close` and every push to the PR branch (`mask-guard`) run the same check on
|
|
193
|
+
the range from the merge base with `origin/<base>` up to the sha, and refuse unclean files.
|
|
194
|
+
They also refuse a NOT VERIFIED check, unless you accepted it for the bout because the repo
|
|
195
|
+
really has no such tooling: `lookout.mjs approve <bout dir> <sha> --format-unverified "<why>"`
|
|
196
|
+
(or `format-gate.mjs accept-unverified <bout dir> "<why>"`), which goes to `decisions.md`.
|
|
197
|
+
Blobs that came out clean are cached in `<bout dir>/format-clean.json`, so after an approve the
|
|
198
|
+
push, the round and the close only check what changed. While a bout is active,
|
|
199
|
+
ring's hooks format what the wrestler edits or writes from the shell (sort-imports with the
|
|
200
|
+
repo's tsconfig, then prettier, with the repo's binaries; they stand aside when the repo's
|
|
201
|
+
`.claude/settings.json` formats on its own), and the wrestler runs `format-gate.mjs fix` before
|
|
202
|
+
each commit.
|
|
175
203
|
2. **Register every finding, then filter the report yourself, against the base.** Each finding a
|
|
176
204
|
cornerman reports (range, concept, batch or final review) goes into the bout's findings ledger
|
|
177
205
|
before anything else: `node "$RING/scripts/findings.mjs" add <pr> --source range --range
|
|
178
|
-
|
|
206
|
+
<from>..<to> --file <report>` (one finding per line; `--source batch` without a range for a
|
|
179
207
|
design review), or `findings.mjs clean <pr> --range <from>..<to>` when it found nothing.
|
|
180
208
|
`lookout.mjs mark` refuses a range whose findings are not registered. Check every BLOCKER:
|
|
181
209
|
`git -C <wt> show <base>:<path>`. An assertion in a test created in this branch is not a base
|
|
@@ -185,11 +213,11 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
185
213
|
- discarded: `findings.mjs discard <pr> F<n> --id D<k> --reason "<why>"`;
|
|
186
214
|
- left for a ticket: `findings.mjs ticket <pr> F<n> --ticket <id|"to file"> --reason "<why>"`;
|
|
187
215
|
- sent to the human: `findings.mjs escalate <pr> F<n>`, and it goes in the escalation.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
216
|
+
A discard or a ticket is a decision you took for the human: the script writes it to
|
|
217
|
+
`decisions.md` and to the judges card ("Decisions I took for you" or "Tickets"), and it stays
|
|
218
|
+
**unshown** until a round-bell body carries it (round-bell does that itself) or you show it
|
|
219
|
+
another way (`findings.mjs shown <pr> F<n> --in "<where>"`). "C3 left it unified later" is not a
|
|
220
|
+
state: a finding nobody settled is open, and open findings hold the next round-bell and push.
|
|
193
221
|
3. **Rebound in one package** (`templates/rebound.md`, P6), blockers first, and **freeze** the
|
|
194
222
|
area under review ("do not touch `<path>`"). If the human left preferences to pass on, they go
|
|
195
223
|
in the same message (P7). Cite the finding ids (F<n>) in each point. Send it with SendMessage
|
|
@@ -198,8 +226,8 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
198
226
|
the wrestler closes it (a point closed in work still waiting on a contract is ticked
|
|
199
227
|
`uncommitted, <where it lives>` and gets its sha when that concept is committed).
|
|
200
228
|
4. Once the range is reviewed: `node "$RING/scripts/lookout.mjs" mark <bout dir> <last reviewed
|
|
201
|
-
|
|
202
|
-
|
|
229
|
+
sha>`. When the cornerman **approved** it: `node "$RING/scripts/lookout.mjs" approve <bout dir>
|
|
230
|
+
<sha>`, and only then push the PR branch up to that sha (you push, the wrestler never does).
|
|
203
231
|
`mask-guard` blocks a push to the PR branch past the approved tip, and while a finding from a
|
|
204
232
|
range inside it is open or more settled findings than `findingsGate.unshown` were never shown.
|
|
205
233
|
**Two branches, two purposes, never mixed:**
|
|
@@ -223,7 +251,20 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
223
251
|
`judges-card.mjs log <pr> decision "D<n> · referee · FOUL: D<k> <what was wrong> · <evidence>"`,
|
|
224
252
|
naming the decision D<k> that was wrong; the chronicle marks D<k> at its own time.
|
|
225
253
|
- **To the human**: only the hard list (or everything under `human`), with
|
|
226
|
-
`templates/escalation.md`.
|
|
254
|
+
`templates/escalation.md`. Every escalation goes with its context: a Markdown file with one
|
|
255
|
+
`## Contexto <n> · <question>` section per question, with the concrete detail of each option
|
|
256
|
+
(what it includes, what it leaves out, what it costs: the routes, the tables, the people it
|
|
257
|
+
touches), since a question is not answerable without it. Right after sending it, write it as
|
|
258
|
+
sent to a file and log it with its context:
|
|
259
|
+
`judges-card.mjs log <pr> escalation <file> --context <file>` (E<n>, stamped; an escalation
|
|
260
|
+
already logged takes its context with `log <pr> escalation-context E<n> <file>`); when the judge answers,
|
|
261
|
+
`judges-card.mjs log <pr> answer [E<n>] "<the judge's words>"` (`--attach <asset id,…>`
|
|
262
|
+
for images), before acting on it. The judge can also answer from the chronicle page (each
|
|
263
|
+
question has its form there): before acting on an answer, and whenever you resume, read the
|
|
264
|
+
page's `respuestas` with `ArtifactData` (`list`, the chronicle's `url`, `out_dir` into
|
|
265
|
+
`<bout dir>/tools/`) and run `judges-card.mjs page-answers <pr> <that dir>`, which logs each new one at the time
|
|
266
|
+
the judge saved it, with the text as the judge left it, the note and the images. They are «la
|
|
267
|
+
entrevista» of the chronicle, with the judge's answer next to each question. A PR heading over the host's size ceiling is on that list: how to
|
|
227
268
|
slice it and any exception are the human's.
|
|
228
269
|
- While the human decides, the wrestler works on something else: never leave it idle.
|
|
229
270
|
- **If the human overturns a decision of yours**: apply it through a rebound, log the overturn
|
|
@@ -231,8 +272,10 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
231
272
|
rulebook / precedents"). Do the same for every hard-list answer the human gives.
|
|
232
273
|
6. **Round-bell per concept.** When a concept closes and passes review:
|
|
233
274
|
`node "$RING/scripts/round-bell.mjs" open <pr> "<concept>" <sha> --verified "<gates, SHA,
|
|
234
|
-
result>" --pending "<…>"` (add `--from <sha>`
|
|
235
|
-
|
|
275
|
+
result>" --pending "<…>"` (on the first round add `--from <sha>` whenever the PR is stacked on
|
|
276
|
+
another branch, with the parent's tip, so its commits are not listed as the bout's own (PR28),
|
|
277
|
+
or when the human already saw the commits before the bout started; add `--flow-change "<…>"`
|
|
278
|
+
when the concept changes how a flow works today, P15). It opens a draft stacked on the previous round, labelled
|
|
236
279
|
do-not-merge. It refuses while a finding from a range inside the round is open, and its body
|
|
237
280
|
lists, under "Findings I settled without you", every finding you discarded or ticketed that the
|
|
238
281
|
human has not seen yet. Tell the human the number, the production line delta and what to look
|
|
@@ -246,11 +289,11 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
246
289
|
- **Soft size line**: a round over ~30 files or ~600 production lines (round-bell warns) is
|
|
247
290
|
split by concept unless the human said otherwise. Under `delegation: "referee"` you decide how
|
|
248
291
|
to split it. Only the host's hard size ceiling for the deliverable PR goes to the human.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
292
|
+
After each round-bell, refresh the chronicle (`/ring:play-by-play <pr>`). `mask-guard` enforces
|
|
293
|
+
it: once the chronicle has a link, a bout record changed after its last publish blocks the
|
|
294
|
+
Copilot re-request and `judges-card.mjs close` until it is republished.
|
|
295
|
+
When the human approves a round-bell, that is **the pattern to replicate**: cite it
|
|
296
|
+
(`gh pr diff <n>`) in every following brief and log it as a decision.
|
|
254
297
|
7. **If the human objects, ask first: "Is it the solution (the behavior) or the class design?"**
|
|
255
298
|
Only a class-design objection triggers a **structural pause** (P3): the wrestler finishes what
|
|
256
299
|
is mechanical and stops; a cornerman in batch mode proposes the target design (class diagram,
|
|
@@ -276,7 +319,7 @@ A change to the description of a field is a contract change too.
|
|
|
276
319
|
|
|
277
320
|
**Never tell the wrestler a contract is approved** ("the contract is already approved, update the
|
|
278
321
|
spec") unless `judges-card.mjs approve-contract` recorded the judge's yes for exactly that content:
|
|
279
|
-
a spec edit you anticipate is a new contract, and goes through steps 2–
|
|
322
|
+
a spec edit you anticipate is a new contract, and goes through steps 2–7 before it is committed.
|
|
280
323
|
|
|
281
324
|
1. If the host names a `contractIntent` (its own intent skill or doc, e.g. `/endpoint-intent`),
|
|
282
325
|
fill it first and attach it.
|
|
@@ -287,15 +330,22 @@ a spec edit you anticipate is a new contract, and goes through steps 2–6 befor
|
|
|
287
330
|
migration, the data backfill. Rebound until it passes.
|
|
288
331
|
4. When the contract changes a database model, draw it first: `references/db-diagram.md` (the
|
|
289
332
|
tables as an entity-relationship diagram, the migration DDL and what to validate) from
|
|
290
|
-
`templates/db-diagram.html` into `<bout dir>/db-diagram.html
|
|
291
|
-
|
|
333
|
+
`templates/db-diagram.html` into `<bout dir>/db-diagram.html`. When it adds or changes
|
|
334
|
+
endpoints, draw them too: `references/api-diagram.md` (who calls each endpoint, its request,
|
|
335
|
+
response and errors, and the tables it touches) from `templates/api-diagram.html` into
|
|
336
|
+
`<bout dir>/api-diagram.html`. Redraw both after every rebound. Then serve the preview from the uncommitted working tree (for a native surface
|
|
292
337
|
contract there is no preview server: show the staged diff of each native file, `git -C <wt>
|
|
293
|
-
|
|
338
|
+
diff --cached -- <files>`, and, for a dependency, the M17 checklist filled in per package):
|
|
294
339
|
`node "$RING/scripts/contract-preview.mjs" <bout dir>` with `run_in_background: true`
|
|
295
|
-
(127.0.0.1:4815; Swagger UI of the proposed spec, what changes against the base
|
|
296
|
-
above the model
|
|
297
|
-
after
|
|
298
|
-
`templates/escalation.md`: the URL, what changed, and your recommendation
|
|
340
|
+
(127.0.0.1:4815; Swagger UI of the proposed spec, what changes against the base with the
|
|
341
|
+
endpoint diagram above it, the model diagram above the model diff, each code diff folded into a
|
|
342
|
+
disclosure, and a warning when a spec or model file changed after its diagram). Ask the judge with
|
|
343
|
+
`templates/escalation.md`: the URL, what changed, and your recommendation, with its context
|
|
344
|
+
per question, and log both (`judges-card.mjs log <pr> escalation <file> --context <file>`,
|
|
345
|
+
then `log <pr> answer` with the judge's words, or `page-answers`, §2.5). Then regenerate and
|
|
346
|
+
republish the chronicle (`/ring:play-by-play`, with `embed --contract`): the judge also
|
|
347
|
+
reviews the contract there, endpoint by endpoint (and, at a frontend venue, route by route
|
|
348
|
+
with `embed --routes`), and gives each one «Se aprueba» or «Se mejora».
|
|
299
349
|
5. Until the judge answers, the contract zone is frozen; the wrestler works on other concepts or
|
|
300
350
|
waits. Work that depends on the unapproved contract (code that needs its new package or its
|
|
301
351
|
config) stays **uncommitted and out of the tree**: each later concept is kept as a patch under
|
|
@@ -320,22 +370,65 @@ a spec edit you anticipate is a new contract, and goes through steps 2–6 befor
|
|
|
320
370
|
`<bout dir>/tools/`, not staged, so the judge reviews the contracts in one escalation and
|
|
321
371
|
approves each one on its own. When nothing is left to draft, the wait is declared, not hidden:
|
|
322
372
|
the judges card says what is waiting on the human, and the wrestler stops until the answer.
|
|
323
|
-
6. **
|
|
373
|
+
6. **The verdicts first.** Before acting on the contract, and whenever you resume, list the
|
|
374
|
+
chronicle's `veredictos` with `ArtifactData` (`list`, the chronicle's `url`, `out_dir` into
|
|
375
|
+
`<bout dir>/tools/`) and run `judges-card.mjs page-verdicts <pr> <that dir>`. It logs each
|
|
376
|
+
verdict at the time the judge gave it, turns each «se mejora» into a contract finding (rebound
|
|
377
|
+
it to the wrestler like any finding) and into a point of the technical plan («Lo que pidió el
|
|
378
|
+
juez»), and says when every endpoint and route is approved with its current fingerprint. A
|
|
379
|
+
rewritten contract outdates the verdicts on what changed: regenerate and republish the
|
|
380
|
+
chronicle after every change to the contract, so the judge reviews what is there now. **Do not
|
|
381
|
+
ask for `approve-contract` until page-verdicts says every one is approved with its current
|
|
382
|
+
fingerprint.**
|
|
383
|
+
7. **Approved**: only the judge's approval of the **concrete** staged contract counts: an
|
|
324
384
|
approval "in concept", given before the files existed, does not. If the review found effects the
|
|
325
385
|
judge did not see (a manifest entry, resources dropped from the build, a permission, a platform
|
|
326
386
|
flag), they go to the judge first, listed in one message. Then
|
|
327
387
|
`node "$RING/scripts/judges-card.mjs" approve-contract <pr> --files <staged paths> --id D<n>
|
|
328
|
-
|
|
388
|
+
--judge-said "<the judge's own words about this concrete contract>"`: it hashes the staged
|
|
329
389
|
content and writes the judge's decision line itself, with the quote, so an approval is never
|
|
330
390
|
typed in the judge's name. Then the wrestler commits the contract in its own commit and
|
|
331
391
|
implements it. `mask-guard` blocks a commit of a contract file whose
|
|
332
392
|
content was not approved, so any later edit to it needs a new approval.
|
|
333
|
-
|
|
334
|
-
|
|
393
|
+
8. **Rejected**: rebound the contract with the judge's reasons and go back to step 3.
|
|
394
|
+
9. **A change to the contract you decide while a cornerman reviews it** (a lockfile to normalize,
|
|
335
395
|
a config to fix) does not restart the review: it waits for the verdict, goes into the same
|
|
336
396
|
rebound package (P6), and the rebounded contract gets a cornerman check of its own before the
|
|
337
397
|
judge sees it.
|
|
338
398
|
|
|
399
|
+
## 2c · The technical plan
|
|
400
|
+
|
|
401
|
+
`<bout dir>/plan-tecnico.md` is what the wrestler has to do for the deliverable: a title
|
|
402
|
+
(`# El plan del técnico · #<pr>`), `## <group>` and bullets
|
|
403
|
+
`- [<state>] **<title>** <detail> · origen: <ids>`, the states being pendiente · espera al juez ·
|
|
404
|
+
en curso · hecho, and a group whose name says «tickets» for what stays out of the delivery. The
|
|
405
|
+
origin cites findings (B1, F8…), decisions (D1…), questions (E1-3), verdicts or the sparring's
|
|
406
|
+
card.
|
|
407
|
+
|
|
408
|
+
- **Write it when the bout opens**, before the first wrestler brief. A bout from a sparring takes
|
|
409
|
+
its points from the card (the judge's validation, the rudo's shortcuts for this repo, «Not
|
|
410
|
+
verified yet», the pending items), from the contract review's findings, from your decisions and
|
|
411
|
+
from the escalation; the tickets the KO left out go to the tickets group. Every point says where
|
|
412
|
+
it comes from.
|
|
413
|
+
- **Never edit a state by hand**: `judges-card.mjs plan <pr> <n|title> <state> [--ref <sha|round-bell>]`
|
|
414
|
+
stamps the change in `plan.jsonl`; `plan <pr> add "<group>" "<title>" --origin <ids>` adds a
|
|
415
|
+
point, `plan <pr> list` prints it. When a round-bell closes a concept or the wrestler applies a
|
|
416
|
+
finding, mark the points it moves, with the round-bell or the sha as `--ref`. `page-verdicts`
|
|
417
|
+
adds each «se mejora» by itself.
|
|
418
|
+
- A bout does not close with a point of the plan outside «hecho» unless the judge sent it to a
|
|
419
|
+
ticket (move it to the tickets group with its id).
|
|
420
|
+
|
|
421
|
+
The chronicle shows the plan after «La entrevista» and before the rounds (`embed --plan`).
|
|
422
|
+
|
|
423
|
+
## 2d · The chronicle during the preparation
|
|
424
|
+
|
|
425
|
+
The judge reviews the preparation in the chronicle, so keep it current: regenerate (`embed` with
|
|
426
|
+
every bout dir of the fight) and republish it after every change to the contract, after logging
|
|
427
|
+
the judge's answers and after logging the verdicts. In a fight with several repos (a back and a
|
|
428
|
+
front), each repo's referee keeps its own bout dir (its interview, verdicts, plan, diagram) and
|
|
429
|
+
logs there; whichever session regenerates the page passes every bout dir of the fight to `embed`
|
|
430
|
+
(the fight's JSON lists them in `bouts[].boutDir`), so the one page joins them all.
|
|
431
|
+
|
|
339
432
|
## 3 · Watching
|
|
340
433
|
|
|
341
434
|
- `node "$RING/scripts/lookout.mjs" watch <bout dir>` with `run_in_background: true`. It exits
|
|
@@ -390,9 +483,10 @@ and runs the fixes through this same cycle (§2).
|
|
|
390
483
|
checkouts), for the human to close and clean. Closing PRs and deleting worktrees and files is
|
|
391
484
|
theirs.
|
|
392
485
|
10. **The chronicle's final edition**: `/ring:play-by-play <pr>` with the status "Final", saying
|
|
393
|
-
|
|
486
|
+
whether Copilot reviewed the last commit, with its "El cierre en números" block
|
|
487
|
+
(`bout-stats.mjs`: numbers, charts, highlight reel and changelog). `close` is blocked while the chronicle is behind.
|
|
394
488
|
11. When the human says the bout is over: `node "$RING/scripts/judges-card.mjs" close <pr>`. Its
|
|
395
|
-
|
|
489
|
+
files stay as the record.
|
|
396
490
|
|
|
397
491
|
## 5 · `resume [<pr>]`
|
|
398
492
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# The endpoints of the contract as a diagram
|
|
2
|
+
|
|
3
|
+
When a contract (§2b) adds or changes endpoints, and always at the opening of a bout that comes
|
|
4
|
+
from a sparring, the judge approves a picture of the API, not a YAML diff. The referee draws it in
|
|
5
|
+
`<bout dir>/api-diagram.html` from `templates/api-diagram.html`; `contract-preview.mjs` shows it
|
|
6
|
+
above "What changes" (the spec text diff folds below it) and warns when a spec file changed after
|
|
7
|
+
it was drawn: redraw it after every rebound of the contract. The tables the endpoints touch are
|
|
8
|
+
drawn in detail in the model diagram (`references/db-diagram.md`); here they are only named.
|
|
9
|
+
|
|
10
|
+
Adapted from the architecture type of diagram-design by Cathryn Lavery (MIT,
|
|
11
|
+
`diagram-design-LICENSE.md` next to this file): its layout conventions, connectors, palette and
|
|
12
|
+
fonts.
|
|
13
|
+
|
|
14
|
+
## What goes in
|
|
15
|
+
|
|
16
|
+
Read the spec on the branch and, after a sparring, every `<sparring dir>/contrato-<repo>.md`, not memory. One
|
|
17
|
+
page with three parts:
|
|
18
|
+
|
|
19
|
+
1. **The diagram** (inline SVG), left to right in three columns:
|
|
20
|
+
- **Who calls**: the screen or action that calls each endpoint (`Tira de métricas`, `botón
|
|
21
|
+
Pausar`), grey, tag `CALLER`.
|
|
22
|
+
- **The endpoints**: one box each with its method tag (`GET`, `POST`, `PATCH`, `DELETE`), the
|
|
23
|
+
path in mono, then one line per part: `in ·` the params and body fields that matter, `out ·`
|
|
24
|
+
the status and the shape, `err ·` the error statuses with their code. **New or changed**:
|
|
25
|
+
accent stroke and tint, tag `NEW` or `CHANGED`; an existing endpoint the change only reuses
|
|
26
|
+
is grey with tag `EXISTING`; a dropped one is dashed with tag `DROPPED`.
|
|
27
|
+
- **The tables** each endpoint reads or writes: a small box with the table name, in the accent
|
|
28
|
+
when the model diagram shows it as new or changed.
|
|
29
|
+
- **Connectors**: caller → endpoint → table, orthogonal with rounded elbows (r = 8), arrows drawn
|
|
30
|
+
before the boxes, never diagonal. A write is a solid arrow labelled `writes`, a read a dashed one
|
|
31
|
+
labelled `reads`, the label on a paper patch 6 px above the line.
|
|
32
|
+
- Group endpoints by resource when there are more than four; above eight, split into one
|
|
33
|
+
diagram per resource.
|
|
34
|
+
2. **The contract per endpoint**: a table with method and path, request, response, errors and
|
|
35
|
+
scoping (tenant, workspace or user), in the judge's language.
|
|
36
|
+
3. **What to validate**: the decisions the judge is really approving, one per line, bold lead:
|
|
37
|
+
naming and REST semantics, pagination and sorting of lists, the error codes the front
|
|
38
|
+
handles, tenant scoping, idempotency of writes, what is computed in the back versus the front,
|
|
39
|
+
breaking changes for existing callers, and, after a sparring, **each shortcut the rudo took**
|
|
40
|
+
(no DTO, no auth check, a JSON column instead of a table, a mock) as its own decision: keep,
|
|
41
|
+
fix in this bout, or ticket.
|
|
42
|
+
|
|
43
|
+
A footer names the sources (spec paths and branch, the `contrato-<repo>.md` files). Write the copy in the judge's
|
|
44
|
+
language.
|
|
45
|
+
|
|
46
|
+
## Form
|
|
47
|
+
|
|
48
|
+
- One self-contained HTML file: the template's CSS, fonts from Google Fonts only, no scripts (the
|
|
49
|
+
preview frames it without scripts).
|
|
50
|
+
- Palette of the template, the same as the model diagram: paper `#f5f5f5`, ink `#2d3142`, muted
|
|
51
|
+
`#4f5d75`, soft `#7a8399`, accent `#eb6c36` only on what changes. Geist for names, Geist Mono for
|
|
52
|
+
methods, paths and fields, Instrument Serif italic for notes.
|
|
53
|
+
- Size the `viewBox` to the boxes; text never touches a box edge (12 px in) and a path that does
|
|
54
|
+
not fit is wrapped at a `/`.
|
|
55
|
+
- Before serving, open it once: no overlapping text, no connector crossing a box that is not its
|
|
56
|
+
end, every endpoint has its `in`, `out` and `err` lines.
|
|
@@ -106,6 +106,17 @@ there; it had to be reopened._
|
|
|
106
106
|
|
|
107
107
|
**PR27. Never link into a checkout the bout does not own, not even for a moment.** A measurement
|
|
108
108
|
that needs another tree's files works on a copy or a fresh install under `<bout dir>/tools/`.
|
|
109
|
+
The same holds for cornermen and for `git archive` copies: they install their own dependencies,
|
|
110
|
+
never a link to another checkout's `node_modules`.
|
|
109
111
|
_Why: a wrestler linked the main checkout's `node_modules` into its worktree to measure a bundler's
|
|
110
112
|
isolation; any install or cleanup run through that link writes in the checkout every session
|
|
111
113
|
shares._
|
|
114
|
+
|
|
115
|
+
**PR28. A round of a PR born from another branch always opens with `--from`.** Without it the
|
|
116
|
+
round-bell lists the parent branch's commits as the bout's own. _Why: a stacked PR's first round
|
|
117
|
+
showed the human dozens of commits that were not part of the bout._
|
|
118
|
+
|
|
119
|
+
**PR29. When the host regenerates artifacts from the working tree, no concept starts with
|
|
120
|
+
uncommitted changes.** A hook that rebuilds a wiki or generated files from the worktree sweeps
|
|
121
|
+
whatever is pending into the next commit. _Why: leftovers of one concept slipped into another
|
|
122
|
+
concept's commit through a regenerated wiki._
|
|
@@ -22,7 +22,7 @@ expression.
|
|
|
22
22
|
`if (existing) { …; return } create(...)`. Lookups that may legitimately find nothing return a
|
|
23
23
|
list or a null object, not a hidden null from a finder that should have failed.
|
|
24
24
|
|
|
25
|
-
**R4. Very few comments.** Only a non-obvious
|
|
25
|
+
**R4. Very few comments.** Only a non-obvious _why_, in one line. Remove comments that narrate
|
|
26
26
|
what or how, repeat the name, tell the history of the refactor, or describe another layer. Keep the
|
|
27
27
|
comment that guards a measured incident ("a 400 from the provider does not burn the key, measured
|
|
28
28
|
on <date>"): deleting it invites the bug back.
|
|
@@ -57,7 +57,8 @@ a large block becomes a helper or its own function.
|
|
|
57
57
|
identical methods (merge them unless the difference means something to the caller). Dependencies
|
|
58
58
|
point inward: the domain imports nothing from application or infrastructure; adapters implement
|
|
59
59
|
the ports the consumer owns, translate foreign errors and types at the border, and live by
|
|
60
|
-
technology.
|
|
60
|
+
technology. The same condition repeated across files is a finding even when every piece works on
|
|
61
|
+
its own: it lives in one place (a value object, a rule, a specification) and the rest call it.
|
|
61
62
|
|
|
62
63
|
**R12. Every value object is a class**, with a private constructor, named static factories and
|
|
63
64
|
methods with its behavior; never an interface plus a frozen object plus loose functions. A plain
|
|
@@ -71,6 +72,42 @@ existing value object when there is one. Constructors used for dependency inject
|
|
|
71
72
|
methods, a named option, a value object or polymorphism. The same for optional callbacks whose mere
|
|
72
73
|
presence changes the semantics: use a discriminated result.
|
|
73
74
|
|
|
75
|
+
**R15. Every new file earns its place with one business sentence**: in the language of the
|
|
76
|
+
domain, which fact of the customer it serves and what it will be used for next. A file without
|
|
77
|
+
that sentence does not enter.
|
|
78
|
+
|
|
79
|
+
**R16. The backend follows the business narrative, not the screen.** A field, filter or query that
|
|
80
|
+
exists only to paint a view, or only to validate before another action (a "preview"), is a
|
|
81
|
+
finding: the view composes what the business already exposes.
|
|
82
|
+
|
|
83
|
+
**R17. Every optional carries its reason.** Each new `?`, nullable or optional field in a DTO,
|
|
84
|
+
command, event or entity is justified in one sentence; otherwise it is required or has a default.
|
|
85
|
+
A union like `X | null` where null means "a different operation" becomes two commands.
|
|
86
|
+
|
|
87
|
+
**R18. An aggregate is born valid.** What gives it meaning exists from its factory; no aggregate
|
|
88
|
+
is created empty and completed later by setters or a second call.
|
|
89
|
+
|
|
90
|
+
**R19. Primitives do not cross boundaries.** Commands, events and ports carry value objects
|
|
91
|
+
(R12), not `string | null` or loose ids; the primitive is parsed once at the edge.
|
|
92
|
+
|
|
93
|
+
**R20. Before a new endpoint or command, list the existing ones that could do it** and why they do
|
|
94
|
+
not serve. A new route that duplicates an existing one under another verb (a PATCH where
|
|
95
|
+
`POST`/`DELETE` on the same resource already exists) is a finding.
|
|
96
|
+
|
|
97
|
+
**R21. Names come from the ubiquitous language and do not collide with another context.** Before
|
|
98
|
+
naming a module, aggregate or resource, search the repo: a name another bounded context already
|
|
99
|
+
owns (a `catalog` next to an existing `catalogs`) is renamed.
|
|
100
|
+
|
|
101
|
+
**R22. Design patterns where they fit, and only where they fit.** Conditionals repeated by type,
|
|
102
|
+
state or provider are replaced by the pattern that removes them (a chain of rules or a composed
|
|
103
|
+
specification, Strategy, polymorphism in the value object, Observer for effects between modules,
|
|
104
|
+
Factory Method for creation invariants, polymorphic errors instead of a map of codes; catalog:
|
|
105
|
+
https://refactoring.guru/design-patterns), citing the measured `file:line`. A pattern enters only
|
|
106
|
+
when it is simpler than the conditional it removes; a discarded pattern is written down with its
|
|
107
|
+
reason so it is not proposed again. Example: five chained `if`s assigning a number, with the
|
|
108
|
+
exclusivity rule repeated in three files, become one `AssignmentRule` per rule, reused by the
|
|
109
|
+
backfill.
|
|
110
|
+
|
|
74
111
|
## T · Tests as a contract
|
|
75
112
|
|
|
76
113
|
**T1. In a refactor, no assertion of a test that exists in the base changes.** Moving or renaming a
|
|
@@ -142,6 +179,12 @@ purpose, short and clear, and are listed in the PR.
|
|
|
142
179
|
**F12. A quiet linter is not an approval.** No orphan entries in baselines or allowlists, and the
|
|
143
180
|
gates run clean against the stack base and against the default branch.
|
|
144
181
|
|
|
182
|
+
**F13. A provider's hard limits count against the base, not the diff.** On a new infrastructure
|
|
183
|
+
resource (metric filters, rules, indexes, queues, alarms), count how many the base already has
|
|
184
|
+
against the provider's quota before approving. _Example: AWS allows 100 metric filters per log
|
|
185
|
+
group; main already had 100 and the PR added 2, so the alarms would not have been created in
|
|
186
|
+
production._
|
|
187
|
+
|
|
145
188
|
## P · Review process
|
|
146
189
|
|
|
147
190
|
**P1. One PR per category.** Business logic and its tests apart from harness, mocks, tooling,
|
|
@@ -151,7 +194,7 @@ skills and docs. The deliverable PR carries only code and tests.
|
|
|
151
194
|
practice is stopped in time, with the approved pattern already applied.
|
|
152
195
|
|
|
153
196
|
**P3. If the human dislikes the class design, a structural pause.** First ask whether the
|
|
154
|
-
objection is to the
|
|
197
|
+
objection is to the _solution_ (the behavior) or to the _class design_; a validated solution is not
|
|
155
198
|
redesigned. On a design objection, finish what is mechanical, agree a target architecture with the
|
|
156
199
|
human and resume with a single sample concept.
|
|
157
200
|
|
|
@@ -160,7 +203,10 @@ per concept by a read-only reviewer on a fixed range of commits.
|
|
|
160
203
|
|
|
161
204
|
**P5. File-by-file design review in batches** of at most 20 files through 8 lenses: layer and
|
|
162
205
|
dependencies, coupling, duplication, SOLID, domain model, errors (fail open or closed),
|
|
163
|
-
expressiveness, production risk.
|
|
206
|
+
expressiveness, production risk. Each new file brings its business sentence (R15) and repeated
|
|
207
|
+
conditionals bring their pattern proposal or the reason none fits (R22). **It is mandatory before
|
|
208
|
+
the first commit when the PR creates a module or an aggregate**, not only when the change is
|
|
209
|
+
large or the human asks: a design review that arrives after the cleanup started arrives late.
|
|
164
210
|
|
|
165
211
|
**P6. One rebound package per review**: `file:line — rule — what is wrong — how it must be`,
|
|
166
212
|
blockers first (base assertion changed, event renamed, behavior changed). What is not applied is
|
|
@@ -189,6 +235,20 @@ battery runs once when everything converged.** The targeted reproduction (a dire
|
|
|
189
235
|
one e2e spec, minutes) must be green on the exact tip that ships before the finding's thread is
|
|
190
236
|
replied to as fixed or resolved; the full validation (hours) runs once, on the final tip.
|
|
191
237
|
|
|
238
|
+
**P14. The host's rules are not the referee's decisions.** When the host fixes a pattern (a
|
|
239
|
+
repository only through specifications, a layer that may not import another), a deviation is a
|
|
240
|
+
cornerman BLOCKER or goes to the hard list; under `delegation: "referee"` the referee may not
|
|
241
|
+
approve it as a design doubt.
|
|
242
|
+
|
|
243
|
+
**P15. A PR that changes how a flow works today explains it in plain words before the code**:
|
|
244
|
+
what happens today, what will happen, and who notices. It goes in the wrestler's brief ("Flow
|
|
245
|
+
change" line of `templates/wrestler-brief.md`) and in the round-bell body (`round-bell.mjs open …
|
|
246
|
+
--flow-change "<today …; after …; who notices …>"`, rendered under "What changes for whom").
|
|
247
|
+
|
|
248
|
+
**P16. Read the execution path before claiming "today it goes through X".** Where a value is
|
|
249
|
+
stored does not say which path uses it; a claim about current behavior cites the call chain that
|
|
250
|
+
runs, not the column or the config that exists.
|
|
251
|
+
|
|
192
252
|
## Who decides
|
|
193
253
|
|
|
194
254
|
The host's `delegation` (`.claude/ring.json`) sets who decides design doubts. With `"referee"`
|
|
@@ -208,6 +268,7 @@ bout moving; with `"human"` the referee escalates both lists, as before.
|
|
|
208
268
|
writes, data deletion).
|
|
209
269
|
- Anything `mask-guard` blocks.
|
|
210
270
|
- A direct contradiction between two instructions of the host repo: it is written down and waits.
|
|
271
|
+
- A deviation from a pattern the host's own rules fix (P14).
|
|
211
272
|
|
|
212
273
|
### The referee's under `delegation: "referee"`
|
|
213
274
|
|