@thebattlearena/corner 0.9.1-beta.70 → 0.10.1-beta.78
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/README.md +46 -26
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/ring/agents/cornerman.md +32 -6
- package/ring/agents/rudo.md +2 -1
- package/ring/agents/wrestler.md +19 -4
- package/ring/hooks/hooks.json +42 -0
- package/ring/scripts/bout-stats-render.mjs +366 -0
- package/ring/scripts/bout-stats.mjs +360 -0
- package/ring/scripts/brief-build.mjs +130 -0
- package/ring/scripts/brief-guard.mjs +154 -0
- package/ring/scripts/brief.mjs +272 -0
- package/ring/scripts/compact-hook.mjs +110 -0
- package/ring/scripts/config.mjs +25 -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 +82 -3
- 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/rule-ids.mjs +124 -0
- 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 +181 -56
- 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 +97 -6
- package/ring/skills/referee/templates/api-diagram.html +115 -0
- package/ring/skills/referee/templates/cornerman-batch.md +17 -11
- package/ring/skills/referee/templates/cornerman-concept.md +28 -30
- package/ring/skills/referee/templates/cornerman-range.md +16 -11
- 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 +28 -41
- package/ring/skills/referee/templates/wrestler-cutoff.md +4 -0
- package/ring/skills/referee/templates/wrestler-resume.md +4 -0
- package/ring/skills/sparring/SKILL.md +13 -4
- package/ring/skills/sparring/templates/contrato.md +29 -0
- package/ring/skills/sparring/templates/rudo-brief.md +7 -0
- package/ring/skills/title-defense/SKILL.md +2 -2
- package/ring/skills/weigh-in/SKILL.md +6 -0
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: referee
|
|
3
|
-
description: Orchestrates a refactor or a large delivery on a backend, frontend or mobile PR as its referee, at the venue the PR belongs to. One
|
|
3
|
+
description: Orchestrates a refactor or a large delivery on a backend, frontend or mobile PR as its referee, at the venue the PR belongs to. One wrestler (Sonnet, effort high by default) writes in its own worktree; you (effort high) review each commit range with read-only cornermen against a numbered rulebook, every brief generated by `brief.mjs` with the rules embedded, send one rebound package at a time, open small do-not-merge round-bell PRs so the human reviews early, decide design doubts yourself from the rulebook and precedents (escalating only a short hard list), and keep a durable judges card so any new session can resume. Invoke with `/ring:referee start <pr>`, `/ring:referee resume [<pr>]`, `/ring:referee close`, "referee the refactor of #N", "resume the bout".
|
|
4
4
|
argument-hint: "start <pr> | start --from-sparring <slug> | resume [<pr>] | close"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# referee
|
|
8
8
|
|
|
9
|
-
You do not write production code. You write
|
|
10
|
-
|
|
9
|
+
You do not write production code. You write rebounds, round-bell bodies, escalations and the
|
|
10
|
+
judges card; the briefs of the wrestler and the cornermen are generated by `brief.mjs` from the
|
|
11
|
+
templates, with the rules embedded in full, and you only give them your values. You are the only one who talks to the human. Under the default delegation you
|
|
11
12
|
also decide every design doubt yourself, write down why, and keep the bout moving: only the hard
|
|
12
13
|
list reaches the human.
|
|
13
14
|
|
|
@@ -39,9 +40,10 @@ list reaches the human.
|
|
|
39
40
|
too; each venue rulebook says which core families apply there. The review lenses of the venue
|
|
40
41
|
are `config.lenses`.
|
|
41
42
|
5. **State lives in `~/.claude/ring/<owner>/<repo>/<pr>/`** (`node "$RING/scripts/judges-card.mjs"
|
|
42
|
-
|
|
43
|
+
path <pr>`; owner and repo lowercased, `local/<name>` for a repo without an origin remote;
|
|
43
44
|
`RING_HOME` overrides the root), never in the session scratchpad: the scratchpad is wiped when
|
|
44
|
-
the session restarts.
|
|
45
|
+
the session restarts. Neither criteria nor notes live there either: what the human asks for
|
|
46
|
+
goes to `decisions.md` or the technical plan, and `brief.mjs` refuses a scratchpad path. A bout in the old flat layout (`<owner>-<repo>/<pr>/`) is moved there the
|
|
45
47
|
first time a script resolves it; if both exist, the new one wins and the old one is reported on
|
|
46
48
|
stderr, untouched.
|
|
47
49
|
6. **The base is a remote ref.** In every git command and every brief, `<base>` means
|
|
@@ -50,16 +52,29 @@ list reaches the human.
|
|
|
50
52
|
thousands of files that are not the PR's. What the scripts store stays the branch name:
|
|
51
53
|
`judges-card.mjs open --base <stack base>` (never `origin/…`), since round-bell adds `origin/`
|
|
52
54
|
itself.
|
|
53
|
-
7. **
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
7. **Every brief from `brief.mjs`, with its model and effort.** Before every Agent call to a
|
|
56
|
+
wrestler or a cornerman, write only your values to a JSON under `<bout dir>/tools/` and run
|
|
57
|
+
`node "$RING/scripts/brief.mjs" wrestler|cornerman <pr> --mode <mode> --vars <file>`: it fills
|
|
58
|
+
the template with the bout's state, the venue's gates and lenses, the commits of the range, the
|
|
59
|
+
decisions (every foul, the ones on those files, the last 20) and **the rules in full**, seals
|
|
60
|
+
it, logs it in `<bout dir>/briefs/index.jsonl`, and prints the file and the Agent call with the
|
|
61
|
+
role's model and effort (`config.agents`: the wrestler and the rudo on `sonnet` at `high`, the
|
|
62
|
+
cornerman on `opus` at `high`, unless the host's `.claude/ring.json` says otherwise). Launch
|
|
63
|
+
with `prompt: "ring-brief: <the file>"`, with that `model` and `effort` (PR16): the
|
|
64
|
+
`brief-guard` hook checks the seal (generated, untouched, on today's rules, of this bout and
|
|
65
|
+
role), puts the file's text in the prompt and sets the role's model and effort. A brief that
|
|
66
|
+
does not hold is reported to you (`briefGuard: "warn"`, the default) or refused (`"block"`).
|
|
67
|
+
Never write a brief by hand: a brief written from memory is what lost the rules in bout #1223.
|
|
68
|
+
`brief.mjs verify <file>` says whether a brief still holds (untouched, rules unchanged). After a
|
|
69
|
+
compaction, a SessionStart hook puts back the bout, its checklist, its fouls and the card's
|
|
70
|
+
«how to resume»: reread the card before acting.
|
|
56
71
|
8. **Who decides** (`config.delegation`, rulebook "Who decides"):
|
|
57
72
|
- **`referee`** (default): you decide design, pattern, layer, naming, style, scope inside the
|
|
58
73
|
assignment, test strategy, and which option to take when a measurement shows a risk. Under
|
|
59
74
|
doubt, prefer the option that preserves current behavior and wire contracts (PR11) and ticket
|
|
60
75
|
the rest. Record each decision with
|
|
61
76
|
`judges-card.mjs log <pr> decision "<id> · referee · <decision> · rests on <R/T/F/P, PRn, HPn>
|
|
62
|
-
|
|
77
|
+
· discarded <alternative> · affects <area>"`, list it in the judges card under "Decisions I
|
|
63
78
|
took for you", and keep going.
|
|
64
79
|
- **`human`**: escalate both lists, as the rulebook describes.
|
|
65
80
|
- **The hard list always goes to the human**: merging, bases, closing or readying PRs,
|
|
@@ -67,9 +82,10 @@ list reaches the human.
|
|
|
67
82
|
assignment did not ask for (including a base assertion customers would see); a PR over the
|
|
68
83
|
host's size ceiling (how to slice it and any exception); **a new or changed endpoint in the
|
|
69
84
|
API spec, a changed database model, or a change to the native surface of a mobile venue**
|
|
70
|
-
|
|
85
|
+
(§2b); customer data or PII, money or billing,
|
|
71
86
|
production; anything `mask-guard` blocks; a direct contradiction between two host
|
|
72
|
-
instructions; a PR whose venue is in doubt (§1.2)
|
|
87
|
+
instructions; a PR whose venue is in doubt (§1.2); a deviation from a pattern the host's own
|
|
88
|
+
rules fix (P14), which you never approve as a design doubt.
|
|
73
89
|
9. **Escalating to the human** (the hard list, size ceiling included, or anything under `human`):
|
|
74
90
|
numbered text, two options each with its cost and your recommendation, answerable as "1. b"
|
|
75
91
|
(`templates/escalation.md`). Use AskUserQuestion only when the host repo's instructions require
|
|
@@ -103,9 +119,19 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
103
119
|
- **What the judge validated is the behavior that must not change**: write it as numbered
|
|
104
120
|
invariants for the concept-mode cornerman, and add characterization tests first (T rules).
|
|
105
121
|
- **The rudo's shortcuts for this repo are the first rebound package**, blockers first.
|
|
106
|
-
- **The
|
|
107
|
-
|
|
108
|
-
|
|
122
|
+
- **The bases go to the judge first.** The contracts decide most of the code still to build, so
|
|
123
|
+
before launching the wrestler (step 8) gather every endpoint and data model the sparring
|
|
124
|
+
proposed: every `<sparring dir>/contrato-<repo>.md` (one per repo; read them together, in repo
|
|
125
|
+
order), checked against the branch (`gh pr diff <pr>`: spec,
|
|
126
|
+
entities, schema, migrations, and the `tools/*.sql` the tables came from). Draw them with the
|
|
127
|
+
ring's diagrams: the endpoints per `references/api-diagram.md` into `<bout dir>/api-diagram.html`
|
|
128
|
+
and the data models per `references/db-diagram.md` into `<bout dir>/db-diagram.html`, each with
|
|
129
|
+
the rudo's shortcuts written as decisions to validate. Serve them with `contract-preview.mjs`
|
|
130
|
+
(§2b step 4) and escalate them as the bout's first question, one numbered decision per
|
|
131
|
+
endpoint or table. Nothing of it is approved because the sparring used it: each goes through
|
|
132
|
+
§2b and `approve-contract`, and concepts that depend on a contract wait for it, while the
|
|
133
|
+
shortcuts that do not can start. Its credentials (by name) are a hard-list item: taking a
|
|
134
|
+
sandbox key's variable to production is the human's.
|
|
109
135
|
- **Open it with `--from-sparring <slug>`** (step 5): `judges-card.mjs open` refuses a sparring
|
|
110
136
|
that is not a KO, records `fromSparring` and marks the hand-off on the sparring. The bout is then
|
|
111
137
|
the third fall of the sparring's chronicle: one page and one link for the whole fight
|
|
@@ -122,7 +148,6 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
122
148
|
rebound changes them. Starting the cleanup before that escalation is a foul; log it in the
|
|
123
149
|
judges card.
|
|
124
150
|
|
|
125
|
-
|
|
126
151
|
1. `gh pr view <pr> --json number,title,url,headRefName,baseRefName,files`. The **stack base** is
|
|
127
152
|
`baseRefName` unless the human names another one; ask if the PR is part of a stack.
|
|
128
153
|
2. **Venue.** `gh pr diff <pr> --name-only | node "$RING/scripts/config.mjs" venue`, or
|
|
@@ -137,7 +162,7 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
137
162
|
`git worktree add --detach <abs path> origin/<headRefName>` (after `git fetch origin`). Never
|
|
138
163
|
launch the wrestler with `isolation: "worktree"`: that creates another tree on another branch.
|
|
139
164
|
5. Open the bout: `node "$RING/scripts/judges-card.mjs" open --pr <pr> --worktree <abs path>
|
|
140
|
-
|
|
165
|
+
--branch <headRefName> --base <stack base> --venue <venue> [--from-sparring <slug>]`. This activates `mask-guard` for this repo.
|
|
141
166
|
It refuses to open when `.claude/ring.json` leaves `apiSpec` or `dbModels` empty while the repo
|
|
142
167
|
has specs or migrations: fix the config (paths or globs; `null` means "detect") rather than
|
|
143
168
|
passing `--allow-empty-contract`, which is only for a bout that truly has no contract. Then
|
|
@@ -146,12 +171,15 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
146
171
|
6. **Gather the assignment**: review comments (`gh api repos/{owner}/{repo}/pulls/<pr>/comments`,
|
|
147
172
|
`gh pr view <pr> --comments`) and what the human said. Every decision or preference goes to
|
|
148
173
|
`judges-card.mjs log <pr> decision "<id> · <who> · <decision> · <affects>"`.
|
|
149
|
-
7. **Design review before touching code** (P5), when the
|
|
174
|
+
7. **Design review before touching code** (P5), always when the PR creates a module or an
|
|
175
|
+
aggregate, and otherwise when the change is large or the human asks: launch
|
|
150
176
|
cornermen in **batch** mode in parallel, ≤20 files each (`templates/cornerman-batch.md`),
|
|
151
177
|
`effort: "high"`. Decide their open questions yourself under `referee` (recorded as in §0.8);
|
|
152
178
|
bring the human only the hard-list ones, or all of them under `human`.
|
|
153
|
-
8. **Launch one wrestler**: `
|
|
154
|
-
|
|
179
|
+
8. **Launch one wrestler**: `brief.mjs wrestler <pr> --mode start --vars <file>` (your values:
|
|
180
|
+
`assignment`, `flowChange`, `concepts`, `frozen`, `waitingOnHuman`, and `comments` and
|
|
181
|
+
`referencePattern` when there are), then `Agent{subagent_type: "ring:wrestler", model, effort
|
|
182
|
+
(as printed), run_in_background: true, prompt: "ring-brief: <the file>"}`. The first concept is a
|
|
155
183
|
**pilot**: one small concept as a sample for the human. Note the agent id in the judges card
|
|
156
184
|
("What I did"). If the harness exposes how the subagent ran, check it ran at medium.
|
|
157
185
|
Give every Agent call a short `description` (its first three words label its chip in Ringside);
|
|
@@ -167,16 +195,46 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
167
195
|
never in bulk**: a range is 2–3 commits or ~200 lines (`reviewEvery` in the host config, 3
|
|
168
196
|
commits / 200 lines by default). `mask-guard` holds the wrestler's next commit once the
|
|
169
197
|
unreviewed range reaches that cap, until you mark it (step 4).
|
|
170
|
-
- each new range: `
|
|
171
|
-
|
|
172
|
-
|
|
198
|
+
- each new range: `brief.mjs cornerman <pr> --mode range --vars <file>` (≤15 lines; the range
|
|
199
|
+
is `lastReviewed..HEAD` unless you pass `--range`; your value: `claims`);
|
|
200
|
+
- when the wrestler closes a concept: `--mode concept` (your values: `invariants`, numbered,
|
|
201
|
+
and `claims`; `designReference` at a UI venue), over ranges already reviewed one by one. It
|
|
202
|
+
also reads the concept as one piece through the venue's lenses: what no single range shows;
|
|
203
|
+
- a design review: `--mode batch --files <f1,f2,…>`.
|
|
173
204
|
If the wrestler claimed something ("does not change counter X"), hand the claim to the
|
|
174
|
-
cornerman to verify against the base.
|
|
205
|
+
cornerman to verify against the base. The cornerman always checks the format of the range
|
|
206
|
+
(`format-gate.mjs check`); an unclean file is a finding like any other, fixed by the wrestler
|
|
207
|
+
with `format-gate.mjs fix <wt> --range <base>..HEAD`. A check that comes back **NO VERIFICADO**
|
|
208
|
+
(exit 2: sort-imports or prettier not installed in the repo) is never clean: register it as a
|
|
209
|
+
finding of the range (the repo lacks its format tooling), and settle it by having the
|
|
210
|
+
dependencies installed in the worktree, or by escalating if the repo has none.
|
|
211
|
+
**The scripts enforce it, not memory:** `lookout.mjs approve`, `round-bell.mjs open`,
|
|
212
|
+
`judges-card.mjs close` and every push to the PR branch (`mask-guard`) run the same check on
|
|
213
|
+
the range from the merge base with `origin/<base>` up to the sha, and refuse unclean files.
|
|
214
|
+
They also refuse a NOT VERIFIED check, unless you accepted it for the bout because the repo
|
|
215
|
+
really has no such tooling: `lookout.mjs approve <bout dir> <sha> --format-unverified "<why>"`
|
|
216
|
+
(or `format-gate.mjs accept-unverified <bout dir> "<why>"`), which goes to `decisions.md`.
|
|
217
|
+
Blobs that came out clean are cached in `<bout dir>/format-clean.json`, so after an approve the
|
|
218
|
+
push, the round and the close only check what changed. While a bout is active,
|
|
219
|
+
ring's hooks format what the wrestler edits or writes from the shell (sort-imports with the
|
|
220
|
+
repo's tsconfig, then prettier, with the repo's binaries; they stand aside when the repo's
|
|
221
|
+
`.claude/settings.json` formats on its own), and the wrestler runs `format-gate.mjs fix` before
|
|
222
|
+
each commit.
|
|
175
223
|
2. **Register every finding, then filter the report yourself, against the base.** Each finding a
|
|
176
224
|
cornerman reports (range, concept, batch or final review) goes into the bout's findings ledger
|
|
177
225
|
before anything else: `node "$RING/scripts/findings.mjs" add <pr> --source range --range
|
|
178
|
-
|
|
226
|
+
<from>..<to> --file <report>` (one finding per line; `--source batch` without a range for a
|
|
179
227
|
design review), or `findings.mjs clean <pr> --range <from>..<to>` when it found nothing.
|
|
228
|
+
**Every finding cites a rule**: `add` refuses a line whose second field is not a rule id of the
|
|
229
|
+
venue (`<file:line> — R11 — …`). Rebound the report to the cornerman ("cite the rule"), or take
|
|
230
|
+
the line as yours with `--rule <id>`, logged with you as its author. A finding no rule covers
|
|
231
|
+
carries `X0`: it lands by itself in "For the rulebook / precedents" of the judges card, since a
|
|
232
|
+
gap the rulebook does not name is a rule it lacks.
|
|
233
|
+
**The human's own reviews are findings too.** When the human reviews code on video (a Tape of
|
|
234
|
+
the Battle Arena QA sessions, `qa_session_overview <link>`) or in a message, each pending item
|
|
235
|
+
becomes a finding with `--source human`, the rule it falls under, `X0` when none does, and the
|
|
236
|
+
link in its text: it runs through the same states as a cornerman's, and the rule it breaks
|
|
237
|
+
goes on the architecture checklist of the next briefs.
|
|
180
238
|
`lookout.mjs mark` refuses a range whose findings are not registered. Check every BLOCKER:
|
|
181
239
|
`git -C <wt> show <base>:<path>`. An assertion in a test created in this branch is not a base
|
|
182
240
|
assertion (T1). Never forward a report you have not read. Every finding ends in exactly one
|
|
@@ -185,11 +243,11 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
185
243
|
- discarded: `findings.mjs discard <pr> F<n> --id D<k> --reason "<why>"`;
|
|
186
244
|
- left for a ticket: `findings.mjs ticket <pr> F<n> --ticket <id|"to file"> --reason "<why>"`;
|
|
187
245
|
- sent to the human: `findings.mjs escalate <pr> F<n>`, and it goes in the escalation.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
246
|
+
A discard or a ticket is a decision you took for the human: the script writes it to
|
|
247
|
+
`decisions.md` and to the judges card ("Decisions I took for you" or "Tickets"), and it stays
|
|
248
|
+
**unshown** until a round-bell body carries it (round-bell does that itself) or you show it
|
|
249
|
+
another way (`findings.mjs shown <pr> F<n> --in "<where>"`). "C3 left it unified later" is not a
|
|
250
|
+
state: a finding nobody settled is open, and open findings hold the next round-bell and push.
|
|
193
251
|
3. **Rebound in one package** (`templates/rebound.md`, P6), blockers first, and **freeze** the
|
|
194
252
|
area under review ("do not touch `<path>`"). If the human left preferences to pass on, they go
|
|
195
253
|
in the same message (P7). Cite the finding ids (F<n>) in each point. Send it with SendMessage
|
|
@@ -198,8 +256,8 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
198
256
|
the wrestler closes it (a point closed in work still waiting on a contract is ticked
|
|
199
257
|
`uncommitted, <where it lives>` and gets its sha when that concept is committed).
|
|
200
258
|
4. Once the range is reviewed: `node "$RING/scripts/lookout.mjs" mark <bout dir> <last reviewed
|
|
201
|
-
|
|
202
|
-
|
|
259
|
+
sha>`. When the cornerman **approved** it: `node "$RING/scripts/lookout.mjs" approve <bout dir>
|
|
260
|
+
<sha>`, and only then push the PR branch up to that sha (you push, the wrestler never does).
|
|
203
261
|
`mask-guard` blocks a push to the PR branch past the approved tip, and while a finding from a
|
|
204
262
|
range inside it is open or more settled findings than `findingsGate.unshown` were never shown.
|
|
205
263
|
**Two branches, two purposes, never mixed:**
|
|
@@ -223,7 +281,20 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
223
281
|
`judges-card.mjs log <pr> decision "D<n> · referee · FOUL: D<k> <what was wrong> · <evidence>"`,
|
|
224
282
|
naming the decision D<k> that was wrong; the chronicle marks D<k> at its own time.
|
|
225
283
|
- **To the human**: only the hard list (or everything under `human`), with
|
|
226
|
-
`templates/escalation.md`.
|
|
284
|
+
`templates/escalation.md`. Every escalation goes with its context: a Markdown file with one
|
|
285
|
+
`## Contexto <n> · <question>` section per question, with the concrete detail of each option
|
|
286
|
+
(what it includes, what it leaves out, what it costs: the routes, the tables, the people it
|
|
287
|
+
touches), since a question is not answerable without it. Right after sending it, write it as
|
|
288
|
+
sent to a file and log it with its context:
|
|
289
|
+
`judges-card.mjs log <pr> escalation <file> --context <file>` (E<n>, stamped; an escalation
|
|
290
|
+
already logged takes its context with `log <pr> escalation-context E<n> <file>`); when the judge answers,
|
|
291
|
+
`judges-card.mjs log <pr> answer [E<n>] "<the judge's words>"` (`--attach <asset id,…>`
|
|
292
|
+
for images), before acting on it. The judge can also answer from the chronicle page (each
|
|
293
|
+
question has its form there): before acting on an answer, and whenever you resume, read the
|
|
294
|
+
page's `respuestas` with `ArtifactData` (`list`, the chronicle's `url`, `out_dir` into
|
|
295
|
+
`<bout dir>/tools/`) and run `judges-card.mjs page-answers <pr> <that dir>`, which logs each new one at the time
|
|
296
|
+
the judge saved it, with the text as the judge left it, the note and the images. They are «la
|
|
297
|
+
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
298
|
slice it and any exception are the human's.
|
|
228
299
|
- While the human decides, the wrestler works on something else: never leave it idle.
|
|
229
300
|
- **If the human overturns a decision of yours**: apply it through a rebound, log the overturn
|
|
@@ -231,8 +302,10 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
231
302
|
rulebook / precedents"). Do the same for every hard-list answer the human gives.
|
|
232
303
|
6. **Round-bell per concept.** When a concept closes and passes review:
|
|
233
304
|
`node "$RING/scripts/round-bell.mjs" open <pr> "<concept>" <sha> --verified "<gates, SHA,
|
|
234
|
-
result>" --pending "<…>"` (add `--from <sha>`
|
|
235
|
-
|
|
305
|
+
result>" --pending "<…>"` (on the first round add `--from <sha>` whenever the PR is stacked on
|
|
306
|
+
another branch, with the parent's tip, so its commits are not listed as the bout's own (PR28),
|
|
307
|
+
or when the human already saw the commits before the bout started; add `--flow-change "<…>"`
|
|
308
|
+
when the concept changes how a flow works today, P15). It opens a draft stacked on the previous round, labelled
|
|
236
309
|
do-not-merge. It refuses while a finding from a range inside the round is open, and its body
|
|
237
310
|
lists, under "Findings I settled without you", every finding you discarded or ticketed that the
|
|
238
311
|
human has not seen yet. Tell the human the number, the production line delta and what to look
|
|
@@ -246,11 +319,11 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
246
319
|
- **Soft size line**: a round over ~30 files or ~600 production lines (round-bell warns) is
|
|
247
320
|
split by concept unless the human said otherwise. Under `delegation: "referee"` you decide how
|
|
248
321
|
to split it. Only the host's hard size ceiling for the deliverable PR goes to the human.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
322
|
+
After each round-bell, refresh the chronicle (`/ring:play-by-play <pr>`). `mask-guard` enforces
|
|
323
|
+
it: once the chronicle has a link, a bout record changed after its last publish blocks the
|
|
324
|
+
Copilot re-request and `judges-card.mjs close` until it is republished.
|
|
325
|
+
When the human approves a round-bell, that is **the pattern to replicate**: cite it
|
|
326
|
+
(`gh pr diff <n>`) in every following brief and log it as a decision.
|
|
254
327
|
7. **If the human objects, ask first: "Is it the solution (the behavior) or the class design?"**
|
|
255
328
|
Only a class-design objection triggers a **structural pause** (P3): the wrestler finishes what
|
|
256
329
|
is mechanical and stops; a cornerman in batch mode proposes the target design (class diagram,
|
|
@@ -261,7 +334,7 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
261
334
|
9. **A concept that needs a new or changed endpoint, database model or native surface** goes
|
|
262
335
|
contract first (§2b) before any implementation.
|
|
263
336
|
|
|
264
|
-
If the wrestler is cut off (API error, limit), send it
|
|
337
|
+
If the wrestler is cut off (API error, limit), send it `brief.mjs wrestler <pr> --mode cutoff`. If the
|
|
265
338
|
whole session restarted, see §5.
|
|
266
339
|
|
|
267
340
|
## 2b · Contract first: the API and the database models are the judge's
|
|
@@ -276,7 +349,7 @@ A change to the description of a field is a contract change too.
|
|
|
276
349
|
|
|
277
350
|
**Never tell the wrestler a contract is approved** ("the contract is already approved, update the
|
|
278
351
|
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–
|
|
352
|
+
a spec edit you anticipate is a new contract, and goes through steps 2–7 before it is committed.
|
|
280
353
|
|
|
281
354
|
1. If the host names a `contractIntent` (its own intent skill or doc, e.g. `/endpoint-intent`),
|
|
282
355
|
fill it first and attach it.
|
|
@@ -287,15 +360,22 @@ a spec edit you anticipate is a new contract, and goes through steps 2–6 befor
|
|
|
287
360
|
migration, the data backfill. Rebound until it passes.
|
|
288
361
|
4. When the contract changes a database model, draw it first: `references/db-diagram.md` (the
|
|
289
362
|
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
|
-
|
|
363
|
+
`templates/db-diagram.html` into `<bout dir>/db-diagram.html`. When it adds or changes
|
|
364
|
+
endpoints, draw them too: `references/api-diagram.md` (who calls each endpoint, its request,
|
|
365
|
+
response and errors, and the tables it touches) from `templates/api-diagram.html` into
|
|
366
|
+
`<bout dir>/api-diagram.html`. Redraw both after every rebound. Then serve the preview from the uncommitted working tree (for a native surface
|
|
292
367
|
contract there is no preview server: show the staged diff of each native file, `git -C <wt>
|
|
293
|
-
|
|
368
|
+
diff --cached -- <files>`, and, for a dependency, the M17 checklist filled in per package):
|
|
294
369
|
`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
|
|
370
|
+
(127.0.0.1:4815; Swagger UI of the proposed spec, what changes against the base with the
|
|
371
|
+
endpoint diagram above it, the model diagram above the model diff, each code diff folded into a
|
|
372
|
+
disclosure, and a warning when a spec or model file changed after its diagram). Ask the judge with
|
|
373
|
+
`templates/escalation.md`: the URL, what changed, and your recommendation, with its context
|
|
374
|
+
per question, and log both (`judges-card.mjs log <pr> escalation <file> --context <file>`,
|
|
375
|
+
then `log <pr> answer` with the judge's words, or `page-answers`, §2.5). Then regenerate and
|
|
376
|
+
republish the chronicle (`/ring:play-by-play`, with `embed --contract`): the judge also
|
|
377
|
+
reviews the contract there, endpoint by endpoint (and, at a frontend venue, route by route
|
|
378
|
+
with `embed --routes`), and gives each one «Se aprueba» or «Se mejora».
|
|
299
379
|
5. Until the judge answers, the contract zone is frozen; the wrestler works on other concepts or
|
|
300
380
|
waits. Work that depends on the unapproved contract (code that needs its new package or its
|
|
301
381
|
config) stays **uncommitted and out of the tree**: each later concept is kept as a patch under
|
|
@@ -320,22 +400,65 @@ a spec edit you anticipate is a new contract, and goes through steps 2–6 befor
|
|
|
320
400
|
`<bout dir>/tools/`, not staged, so the judge reviews the contracts in one escalation and
|
|
321
401
|
approves each one on its own. When nothing is left to draft, the wait is declared, not hidden:
|
|
322
402
|
the judges card says what is waiting on the human, and the wrestler stops until the answer.
|
|
323
|
-
6. **
|
|
403
|
+
6. **The verdicts first.** Before acting on the contract, and whenever you resume, list the
|
|
404
|
+
chronicle's `veredictos` with `ArtifactData` (`list`, the chronicle's `url`, `out_dir` into
|
|
405
|
+
`<bout dir>/tools/`) and run `judges-card.mjs page-verdicts <pr> <that dir>`. It logs each
|
|
406
|
+
verdict at the time the judge gave it, turns each «se mejora» into a contract finding (rebound
|
|
407
|
+
it to the wrestler like any finding) and into a point of the technical plan («Lo que pidió el
|
|
408
|
+
juez»), and says when every endpoint and route is approved with its current fingerprint. A
|
|
409
|
+
rewritten contract outdates the verdicts on what changed: regenerate and republish the
|
|
410
|
+
chronicle after every change to the contract, so the judge reviews what is there now. **Do not
|
|
411
|
+
ask for `approve-contract` until page-verdicts says every one is approved with its current
|
|
412
|
+
fingerprint.**
|
|
413
|
+
7. **Approved**: only the judge's approval of the **concrete** staged contract counts: an
|
|
324
414
|
approval "in concept", given before the files existed, does not. If the review found effects the
|
|
325
415
|
judge did not see (a manifest entry, resources dropped from the build, a permission, a platform
|
|
326
416
|
flag), they go to the judge first, listed in one message. Then
|
|
327
417
|
`node "$RING/scripts/judges-card.mjs" approve-contract <pr> --files <staged paths> --id D<n>
|
|
328
|
-
|
|
418
|
+
--judge-said "<the judge's own words about this concrete contract>"`: it hashes the staged
|
|
329
419
|
content and writes the judge's decision line itself, with the quote, so an approval is never
|
|
330
420
|
typed in the judge's name. Then the wrestler commits the contract in its own commit and
|
|
331
421
|
implements it. `mask-guard` blocks a commit of a contract file whose
|
|
332
422
|
content was not approved, so any later edit to it needs a new approval.
|
|
333
|
-
|
|
334
|
-
|
|
423
|
+
8. **Rejected**: rebound the contract with the judge's reasons and go back to step 3.
|
|
424
|
+
9. **A change to the contract you decide while a cornerman reviews it** (a lockfile to normalize,
|
|
335
425
|
a config to fix) does not restart the review: it waits for the verdict, goes into the same
|
|
336
426
|
rebound package (P6), and the rebounded contract gets a cornerman check of its own before the
|
|
337
427
|
judge sees it.
|
|
338
428
|
|
|
429
|
+
## 2c · The technical plan
|
|
430
|
+
|
|
431
|
+
`<bout dir>/plan-tecnico.md` is what the wrestler has to do for the deliverable: a title
|
|
432
|
+
(`# El plan del técnico · #<pr>`), `## <group>` and bullets
|
|
433
|
+
`- [<state>] **<title>** <detail> · origen: <ids>`, the states being pendiente · espera al juez ·
|
|
434
|
+
en curso · hecho, and a group whose name says «tickets» for what stays out of the delivery. The
|
|
435
|
+
origin cites findings (B1, F8…), decisions (D1…), questions (E1-3), verdicts or the sparring's
|
|
436
|
+
card.
|
|
437
|
+
|
|
438
|
+
- **Write it when the bout opens**, before the first wrestler brief. A bout from a sparring takes
|
|
439
|
+
its points from the card (the judge's validation, the rudo's shortcuts for this repo, «Not
|
|
440
|
+
verified yet», the pending items), from the contract review's findings, from your decisions and
|
|
441
|
+
from the escalation; the tickets the KO left out go to the tickets group. Every point says where
|
|
442
|
+
it comes from.
|
|
443
|
+
- **Never edit a state by hand**: `judges-card.mjs plan <pr> <n|title> <state> [--ref <sha|round-bell>]`
|
|
444
|
+
stamps the change in `plan.jsonl`; `plan <pr> add "<group>" "<title>" --origin <ids>` adds a
|
|
445
|
+
point, `plan <pr> list` prints it. When a round-bell closes a concept or the wrestler applies a
|
|
446
|
+
finding, mark the points it moves, with the round-bell or the sha as `--ref`. `page-verdicts`
|
|
447
|
+
adds each «se mejora» by itself.
|
|
448
|
+
- A bout does not close with a point of the plan outside «hecho» unless the judge sent it to a
|
|
449
|
+
ticket (move it to the tickets group with its id).
|
|
450
|
+
|
|
451
|
+
The chronicle shows the plan after «La entrevista» and before the rounds (`embed --plan`).
|
|
452
|
+
|
|
453
|
+
## 2d · The chronicle during the preparation
|
|
454
|
+
|
|
455
|
+
The judge reviews the preparation in the chronicle, so keep it current: regenerate (`embed` with
|
|
456
|
+
every bout dir of the fight) and republish it after every change to the contract, after logging
|
|
457
|
+
the judge's answers and after logging the verdicts. In a fight with several repos (a back and a
|
|
458
|
+
front), each repo's referee keeps its own bout dir (its interview, verdicts, plan, diagram) and
|
|
459
|
+
logs there; whichever session regenerates the page passes every bout dir of the fight to `embed`
|
|
460
|
+
(the fight's JSON lists them in `bouts[].boutDir`), so the one page joins them all.
|
|
461
|
+
|
|
339
462
|
## 3 · Watching
|
|
340
463
|
|
|
341
464
|
- `node "$RING/scripts/lookout.mjs" watch <bout dir>` with `run_in_background: true`. It exits
|
|
@@ -390,9 +513,10 @@ and runs the fixes through this same cycle (§2).
|
|
|
390
513
|
checkouts), for the human to close and clean. Closing PRs and deleting worktrees and files is
|
|
391
514
|
theirs.
|
|
392
515
|
10. **The chronicle's final edition**: `/ring:play-by-play <pr>` with the status "Final", saying
|
|
393
|
-
|
|
516
|
+
whether Copilot reviewed the last commit, with its "El cierre en números" block
|
|
517
|
+
(`bout-stats.mjs`: numbers, charts, highlight reel and changelog). `close` is blocked while the chronicle is behind.
|
|
394
518
|
11. When the human says the bout is over: `node "$RING/scripts/judges-card.mjs" close <pr>`. Its
|
|
395
|
-
|
|
519
|
+
files stay as the record.
|
|
396
520
|
|
|
397
521
|
## 5 · `resume [<pr>]`
|
|
398
522
|
|
|
@@ -401,8 +525,9 @@ and runs the fixes through this same cycle (§2).
|
|
|
401
525
|
unreviewed commits, open rebounds, decisions and the judges card. Read the rulebook and both precedent files in full again (§0.4).
|
|
402
526
|
3. Review the unreviewed commits first (§2.1–2.4).
|
|
403
527
|
4. A new session cannot talk to the old wrestler: its agent id does not survive. Relaunch it
|
|
404
|
-
**without `isolation`**, on the existing worktree, with
|
|
405
|
-
`
|
|
528
|
+
**without `isolation`**, on the existing worktree, with
|
|
529
|
+
`brief.mjs wrestler <pr> --mode resume --vars <file>` (add `nextConcept` to your values) and
|
|
530
|
+
the model and effort it prints.
|
|
406
531
|
5. Restart the lookout (§3) and carry on with the cycle.
|
|
407
532
|
|
|
408
533
|
For unattended work (the human goes to sleep), use `/ring:no-surrender` on top of an active bout.
|
|
@@ -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._
|