@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.
Files changed (58) hide show
  1. package/README.md +46 -26
  2. package/package.json +1 -1
  3. package/plugin/.claude-plugin/plugin.json +1 -1
  4. package/ring/agents/cornerman.md +32 -6
  5. package/ring/agents/rudo.md +2 -1
  6. package/ring/agents/wrestler.md +19 -4
  7. package/ring/hooks/hooks.json +42 -0
  8. package/ring/scripts/bout-stats-render.mjs +366 -0
  9. package/ring/scripts/bout-stats.mjs +360 -0
  10. package/ring/scripts/brief-build.mjs +130 -0
  11. package/ring/scripts/brief-guard.mjs +154 -0
  12. package/ring/scripts/brief.mjs +272 -0
  13. package/ring/scripts/compact-hook.mjs +110 -0
  14. package/ring/scripts/config.mjs +25 -1
  15. package/ring/scripts/contract-endpoints.mjs +163 -0
  16. package/ring/scripts/contract-preview.mjs +34 -14
  17. package/ring/scripts/fight.mjs +27 -0
  18. package/ring/scripts/findings.mjs +82 -3
  19. package/ring/scripts/format-gate.mjs +723 -0
  20. package/ring/scripts/format-worker.mjs +120 -0
  21. package/ring/scripts/front-routes.mjs +345 -0
  22. package/ring/scripts/judges-card.mjs +324 -3
  23. package/ring/scripts/lookout.mjs +22 -4
  24. package/ring/scripts/mask-guard.mjs +34 -1
  25. package/ring/scripts/page-embed.mjs +112 -0
  26. package/ring/scripts/play-by-play.mjs +155 -7
  27. package/ring/scripts/preparation-collect.mjs +177 -0
  28. package/ring/scripts/preparation.mjs +547 -0
  29. package/ring/scripts/round-bell.mjs +9 -2
  30. package/ring/scripts/rule-ids.mjs +124 -0
  31. package/ring/scripts/tech-plan-log.mjs +81 -0
  32. package/ring/scripts/tech-plan.mjs +191 -0
  33. package/ring/scripts/verdicts-log.mjs +75 -0
  34. package/ring/scripts/verdicts.mjs +205 -0
  35. package/ring/skills/play-by-play/SKILL.md +235 -33
  36. package/ring/skills/play-by-play/templates/blocks.css +196 -0
  37. package/ring/skills/play-by-play/templates/chronicle.html +358 -55
  38. package/ring/skills/play-by-play/templates/endpoints-view.js +1153 -0
  39. package/ring/skills/play-by-play/templates/interview-form.js +516 -0
  40. package/ring/skills/play-by-play/templates/now-panel.js +719 -0
  41. package/ring/skills/referee/SKILL.md +181 -56
  42. package/ring/skills/referee/references/api-diagram.md +56 -0
  43. package/ring/skills/referee/references/precedents.md +11 -0
  44. package/ring/skills/referee/references/rulebook.md +97 -6
  45. package/ring/skills/referee/templates/api-diagram.html +115 -0
  46. package/ring/skills/referee/templates/cornerman-batch.md +17 -11
  47. package/ring/skills/referee/templates/cornerman-concept.md +28 -30
  48. package/ring/skills/referee/templates/cornerman-range.md +16 -11
  49. package/ring/skills/referee/templates/escalation.md +7 -1
  50. package/ring/skills/referee/templates/round-bell-body.md +4 -0
  51. package/ring/skills/referee/templates/wrestler-brief.md +28 -41
  52. package/ring/skills/referee/templates/wrestler-cutoff.md +4 -0
  53. package/ring/skills/referee/templates/wrestler-resume.md +4 -0
  54. package/ring/skills/sparring/SKILL.md +13 -4
  55. package/ring/skills/sparring/templates/contrato.md +29 -0
  56. package/ring/skills/sparring/templates/rudo-brief.md +7 -0
  57. package/ring/skills/title-defense/SKILL.md +2 -2
  58. package/ring/skills/weigh-in/SKILL.md +6 -0
@@ -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 *why*, in one line. Remove comments that narrate
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,70 @@ 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. The same for code that names each channel, provider or flavor it serves (`if chat … if
110
+ voice … if whatsapp`): the core does not know which ones exist; each one is a strategy it delegates
111
+ to, and effects between them travel as events (publish and subscribe).
112
+
113
+ **R23. A ternary that fills a gap means the gap should not exist.** `x ? x : []`, `x ?? []` repeated
114
+ downstream or a `map` guarded against `undefined` say the value was born optional when it has a
115
+ default: the default lives where the value is born (an empty list, not an optional list), and the
116
+ code downstream stops asking. Every ternary that stays names its two business cases; one that
117
+ cannot is replaced by a named function or a strategy (R22).
118
+
119
+ **R24. Types come from their source.** A shape the SDK, the API spec or a validation schema already
120
+ defines is imported or derived from it (generated types, the schema's inferred type, the SDK's own
121
+ enums), never rewritten by hand, so it follows the source when the source changes. Closed sets of
122
+ strings (statuses, operations, channels) are those constants or value objects (R6), never loose
123
+ literals compared in an `if`.
124
+
125
+ **R25. What a provider returns crosses an anti-corruption layer.** A provider's response is
126
+ validated and transformed at the edge, by a schema, into our own model; neither the domain nor the
127
+ client ever receives the raw response. An optional field of the provider is optional only with the
128
+ evidence of when it does not arrive (the provider's docs, a captured response), never by
129
+ assumption.
130
+
131
+ **R26. Business metrics are not monitoring.** Product analytics records business events, each one
132
+ naming the business question it answers; errors go to the monitoring tool (error tracking,
133
+ alarms, F4). A failed operation is not a business event, and an error is never tracked as one.
134
+
135
+ **R27. A cross-cutting precondition is checked once, where it is born.** The selected workspace,
136
+ the session, the tenant: validated at one global point (a guard, a provider, a resolver), not in
137
+ every component, hook or handler that uses it (R8).
138
+
74
139
  ## T · Tests as a contract
75
140
 
76
141
  **T1. In a refactor, no assertion of a test that exists in the base changes.** Moving or renaming a
@@ -142,6 +207,12 @@ purpose, short and clear, and are listed in the PR.
142
207
  **F12. A quiet linter is not an approval.** No orphan entries in baselines or allowlists, and the
143
208
  gates run clean against the stack base and against the default branch.
144
209
 
210
+ **F13. A provider's hard limits count against the base, not the diff.** On a new infrastructure
211
+ resource (metric filters, rules, indexes, queues, alarms), count how many the base already has
212
+ against the provider's quota before approving. _Example: AWS allows 100 metric filters per log
213
+ group; main already had 100 and the PR added 2, so the alarms would not have been created in
214
+ production._
215
+
145
216
  ## P · Review process
146
217
 
147
218
  **P1. One PR per category.** Business logic and its tests apart from harness, mocks, tooling,
@@ -151,7 +222,7 @@ skills and docs. The deliverable PR carries only code and tests.
151
222
  practice is stopped in time, with the approved pattern already applied.
152
223
 
153
224
  **P3. If the human dislikes the class design, a structural pause.** First ask whether the
154
- objection is to the *solution* (the behavior) or to the *class design*; a validated solution is not
225
+ objection is to the _solution_ (the behavior) or to the _class design_; a validated solution is not
155
226
  redesigned. On a design objection, finish what is mechanical, agree a target architecture with the
156
227
  human and resume with a single sample concept.
157
228
 
@@ -160,7 +231,10 @@ per concept by a read-only reviewer on a fixed range of commits.
160
231
 
161
232
  **P5. File-by-file design review in batches** of at most 20 files through 8 lenses: layer and
162
233
  dependencies, coupling, duplication, SOLID, domain model, errors (fail open or closed),
163
- expressiveness, production risk.
234
+ expressiveness, production risk. Each new file brings its business sentence (R15) and repeated
235
+ conditionals bring their pattern proposal or the reason none fits (R22). **It is mandatory before
236
+ the first commit when the PR creates a module or an aggregate**, not only when the change is
237
+ large or the human asks: a design review that arrives after the cleanup started arrives late.
164
238
 
165
239
  **P6. One rebound package per review**: `file:line — rule — what is wrong — how it must be`,
166
240
  blockers first (base assertion changed, event renamed, behavior changed). What is not applied is
@@ -175,8 +249,10 @@ decides it and records why, or, for the hard list or under `delegation: "human"`
175
249
  human with two options, their cost and a recommendation. Meanwhile the author does not touch that
176
250
  part and works on something else.
177
251
 
178
- **P10. Effort by role**: whoever writes runs at medium; whoever orchestrates, reviews or gives
179
- feedback runs at high. Set it explicitly on every launch; never let it be inherited.
252
+ **P10. Model and effort by role**: whoever writes runs on the cheaper model at high effort (the
253
+ wrestler and the rudo on Sonnet); whoever orchestrates, reviews or gives feedback runs on the
254
+ strongest model at high effort. The host can change either per role (`agents` in
255
+ `.claude/ring.json`). Set both explicitly on every launch; never let them be inherited.
180
256
 
181
257
  **P11. When the host forbids them (`forbidAiTrailers`, the default), commits carry no AI
182
258
  attribution trailers**; human co-authors are always fine. Stage by explicit paths.
@@ -189,6 +265,20 @@ battery runs once when everything converged.** The targeted reproduction (a dire
189
265
  one e2e spec, minutes) must be green on the exact tip that ships before the finding's thread is
190
266
  replied to as fixed or resolved; the full validation (hours) runs once, on the final tip.
191
267
 
268
+ **P14. The host's rules are not the referee's decisions.** When the host fixes a pattern (a
269
+ repository only through specifications, a layer that may not import another), a deviation is a
270
+ cornerman BLOCKER or goes to the hard list; under `delegation: "referee"` the referee may not
271
+ approve it as a design doubt.
272
+
273
+ **P15. A PR that changes how a flow works today explains it in plain words before the code**:
274
+ what happens today, what will happen, and who notices. It goes in the wrestler's brief ("Flow
275
+ change" line of `templates/wrestler-brief.md`) and in the round-bell body (`round-bell.mjs open …
276
+ --flow-change "<today …; after …; who notices …>"`, rendered under "What changes for whom").
277
+
278
+ **P16. Read the execution path before claiming "today it goes through X".** Where a value is
279
+ stored does not say which path uses it; a claim about current behavior cites the call chain that
280
+ runs, not the column or the config that exists.
281
+
192
282
  ## Who decides
193
283
 
194
284
  The host's `delegation` (`.claude/ring.json`) sets who decides design doubts. With `"referee"`
@@ -208,6 +298,7 @@ bout moving; with `"human"` the referee escalates both lists, as before.
208
298
  writes, data deletion).
209
299
  - Anything `mask-guard` blocks.
210
300
  - A direct contradiction between two instructions of the host repo: it is written down and waits.
301
+ - A deviation from a pattern the host's own rules fix (P14).
211
302
 
212
303
  ### The referee's under `delegation: "referee"`
213
304
 
@@ -0,0 +1,115 @@
1
+ <!doctype html>
2
+ <!-- The endpoints of the contract for the judge (references/api-diagram.md). Copy to
3
+ <bout dir>/api-diagram.html and replace every <…>. Adapted from the architecture type of
4
+ diagram-design by Cathryn Lavery, MIT: references/diagram-design-LICENSE.md. No scripts: the
5
+ preview frames it without them. -->
6
+ <html lang="<judge's language, e.g. es>">
7
+ <head>
8
+ <meta charset="utf-8">
9
+ <meta name="viewport" content="width=device-width, initial-scale=1">
10
+ <title><contract title></title>
11
+ <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
12
+ <style>
13
+ :root { --paper:#f5f5f5; --ink:#2d3142; --muted:#4f5d75; --soft:#7a8399; --rule:rgba(45,49,66,0.12); --accent:#eb6c36; }
14
+ * { box-sizing:border-box; }
15
+ body { margin:0; background:var(--paper); color:var(--ink); font-family:'Geist',sans-serif; }
16
+ main { max-width:1080px; margin:0 auto; padding:32px 24px 40px; }
17
+ .eyebrow { font-family:'Geist Mono',monospace; font-size:12px; letter-spacing:0.14em; color:var(--muted); text-transform:uppercase; margin:0 0 8px; }
18
+ h1 { font-family:'Instrument Serif',serif; font-weight:400; font-size:1.75rem; margin:0 0 8px; }
19
+ .sub { color:var(--muted); font-size:14px; margin:0 0 24px; max-width:760px; line-height:1.5; }
20
+ svg { width:100%; height:auto; display:block; }
21
+ .card { background:#fff; border:1px solid var(--rule); border-radius:6px; padding:20px; margin-top:24px; overflow-x:auto; }
22
+ .card h3 { font-size:14px; margin:0 0 12px; }
23
+ table { border-collapse:collapse; width:100%; font-size:13px; }
24
+ th { text-align:left; font-family:'Geist Mono',monospace; font-size:11px; letter-spacing:0.08em; text-transform:uppercase; color:var(--soft); font-weight:500; padding:0 12px 8px 0; }
25
+ td { padding:8px 12px 8px 0; border-top:1px solid var(--rule); vertical-align:top; line-height:1.5; }
26
+ code { font-family:'Geist Mono',monospace; font-size:12px; }
27
+ .m { color:var(--accent); font-weight:600; }
28
+ ul { margin:0; padding-left:18px; font-size:13px; line-height:1.6; }
29
+ li { margin-bottom:6px; }
30
+ footer { margin-top:32px; padding-top:12px; border-top:1px solid var(--rule); font-family:'Geist Mono',monospace; font-size:12px; color:var(--soft); }
31
+ </style>
32
+ </head>
33
+ <body>
34
+ <main>
35
+ <p class="eyebrow">PR #<n> · <API contract></p>
36
+ <h1><contract title></h1>
37
+ <p class="sub"><one or two sentences: which endpoints change and for what, in plain words></p>
38
+
39
+ <!-- Size the viewBox to the boxes. Columns: callers (x 40), endpoints (x 300), tables (x 760).
40
+ Draw connectors first, then the boxes on top. -->
41
+ <svg viewBox="0 0 960 300" role="img" aria-labelledby="api-title api-desc">
42
+ <title id="api-title"><contract title></title>
43
+ <desc id="api-desc"><who calls what and which tables it touches, in one sentence></desc>
44
+ <defs>
45
+ <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
46
+ <polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/>
47
+ </marker>
48
+ <marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
49
+ <polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/>
50
+ </marker>
51
+ </defs>
52
+ <rect width="100%" height="100%" fill="#f5f5f5"/>
53
+
54
+ <!-- Caller → endpoint: a straight line when they share y, otherwise a rounded elbow
55
+ (M x1,y1 H mid-8 Q mid,y1 mid,y1+8 V y2-8 Q mid,y2 mid+8,y2 H x2). -->
56
+ <line x1="220" y1="96" x2="298" y2="96" stroke="#4f5d75" stroke-width="1.2" marker-end="url(#arrow)"/>
57
+ <!-- Endpoint → table: solid = writes, dashed = reads; the label on a paper patch 6 px above. -->
58
+ <path d="M 660,96 H 702 Q 710,96 710,104 V 172 Q 710,180 718,180 H 758" fill="none" stroke="#eb6c36" stroke-width="1.2" marker-end="url(#arrow-accent)"/>
59
+ <rect x="672" y="78" width="40" height="12" rx="2" fill="#f5f5f5"/>
60
+ <text x="692" y="87" fill="#7a8399" font-size="8" font-family="'Geist Mono',monospace" text-anchor="middle" letter-spacing="0.06em">writes</text>
61
+ <line x1="660" y1="232" x2="758" y2="232" stroke="#4f5d75" stroke-width="1" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
62
+ <rect x="690" y="214" width="36" height="12" rx="2" fill="#f5f5f5"/>
63
+ <text x="708" y="223" fill="#7a8399" font-size="8" font-family="'Geist Mono',monospace" text-anchor="middle" letter-spacing="0.06em">reads</text>
64
+
65
+ <!-- Caller: grey, tag CALLER. -->
66
+ <rect x="40" y="64" width="180" height="64" rx="6" fill="rgba(79,93,117,0.10)" stroke="#7a8399" stroke-width="1"/>
67
+ <rect x="52" y="76" width="52" height="12" rx="2" fill="none" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
68
+ <text x="78" y="85" fill="#4f5d75" font-size="8" font-family="'Geist Mono',monospace" text-anchor="middle" letter-spacing="0.08em">CALLER</text>
69
+ <text x="52" y="112" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist',sans-serif"><screen or action></text>
70
+
71
+ <!-- New (or changed) endpoint: accent stroke and tint; method tag, path, then in / out / err. -->
72
+ <rect x="300" y="64" width="360" height="132" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
73
+ <rect x="312" y="76" width="40" height="12" rx="2" fill="none" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
74
+ <text x="332" y="85" fill="#eb6c36" font-size="8" font-family="'Geist Mono',monospace" text-anchor="middle" letter-spacing="0.08em">NEW</text>
75
+ <text x="312" y="108" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist Mono',monospace">POST</text>
76
+ <text x="352" y="108" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist Mono',monospace"><path></text>
77
+ <line x1="300" y1="118" x2="660" y2="118" stroke="rgba(235,108,54,0.30)" stroke-width="0.8"/>
78
+ <text x="312" y="138" fill="#2d3142" font-size="12" font-family="'Geist Mono',monospace">in · <param>: <type>, <body field>: <type></text>
79
+ <text x="312" y="158" fill="#2d3142" font-size="12" font-family="'Geist Mono',monospace">out · 201 { <field>: <type>, … }</text>
80
+ <text x="312" y="178" fill="#4f5d75" font-size="12" font-family="'Geist Mono',monospace">err · 404 <code> · 409 <code></text>
81
+
82
+ <!-- Existing endpoint the change reuses: grey, tag EXISTING, path only plus a note. -->
83
+ <rect x="300" y="212" width="360" height="56" rx="6" fill="rgba(45,49,66,0.03)" stroke="rgba(45,49,66,0.30)" stroke-width="1"/>
84
+ <rect x="312" y="222" width="64" height="12" rx="2" fill="none" stroke="rgba(45,49,66,0.40)" stroke-width="0.8"/>
85
+ <text x="344" y="231" fill="#4f5d75" font-size="8" font-family="'Geist Mono',monospace" text-anchor="middle" letter-spacing="0.08em">EXISTING</text>
86
+ <text x="312" y="254" fill="#4f5d75" font-size="12" font-family="'Geist Mono',monospace">GET <path></text>
87
+ <text x="520" y="254" fill="#7a8399" font-size="12" font-family="'Instrument Serif',serif" font-style="italic">unchanged</text>
88
+
89
+ <!-- Tables: name only; accent when the model diagram shows them new or changed. -->
90
+ <rect x="760" y="164" width="160" height="32" rx="6" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1"/>
91
+ <text x="772" y="185" fill="#2d3142" font-size="12" font-family="'Geist Mono',monospace"><new_table></text>
92
+ <rect x="760" y="216" width="160" height="32" rx="6" fill="rgba(45,49,66,0.05)" stroke="#4f5d75" stroke-width="1"/>
93
+ <text x="772" y="237" fill="#2d3142" font-size="12" font-family="'Geist Mono',monospace"><existing_table></text>
94
+ </svg>
95
+
96
+ <div class="card">
97
+ <h3><The contract per endpoint></h3>
98
+ <table>
99
+ <thead><tr><th>Endpoint</th><th>Request</th><th>Response</th><th>Errors</th><th>Scoping</th></tr></thead>
100
+ <tbody>
101
+ <tr><td><code><span class="m">POST</span> <path></code></td><td><params and body></td><td><status and shape></td><td><status · code · when></td><td><tenant / workspace / user></td></tr>
102
+ </tbody>
103
+ </table>
104
+ </div>
105
+ <div class="card">
106
+ <h3><What to validate></h3>
107
+ <ul>
108
+ <li><b><decision>:</b> <what it means and what to check></li>
109
+ <li><b><shortcut of the sparring>:</b> <keep, fix in this bout, or ticket></li>
110
+ </ul>
111
+ </div>
112
+ <footer><Sources: the spec paths on branch …, and the sparring's contrato-&lt;repo&gt;.md files></footer>
113
+ </main>
114
+ </body>
115
+ </html>
@@ -1,15 +1,21 @@
1
- <!-- Agent{subagent_type: "ring:cornerman", effort: "high"}, several in parallel, before code is
2
- touched or when the human asks for a design pass. At most 20 files each. -->
3
-
4
- Mode: **batch**. Read only. Worktree `<absolute path>` at its live HEAD; the tree may change while
5
- you read: cite the lines of the moment. Rulebook `<absolute rulebook path>`.
1
+ Mode: **batch**. Read only. Worktree `{{worktree}}` at its live HEAD; the tree may change while
2
+ you read: cite the lines of the moment. The decisions taken are near the end of this brief and the
3
+ rules after them, at its end (the architecture checklist first). Ring scripts `{{ring}}/scripts`
4
+ (the format gate is `format-gate.mjs` there).
6
5
 
7
6
  Files (≤20):
8
- - <path>
7
+ {{files}}
8
+
9
+ Review in two passes and report both together.
9
10
 
10
- Each file through the lenses of the bout's venue (`config.lenses` from
11
- `config.mjs show --venue <venue>`): <lenses, one per line>.
11
+ 1. **Sweep.** Read each file whole, then go through it lens by lens, every lens of this venue:
12
+ {{lenses}}. Report everything wrong you find, production risk and behavior as much as design.
13
+ There is no cap on findings, and a problem no rule fits is still a finding.
14
+ 2. **Checklist.** Go over the architecture checklist at the end of this brief against each file
15
+ and add what the sweep missed.
12
16
 
13
- Return per file the findings with rule ids, one finding per line (the referee registers each line
14
- with `findings.mjs add --source batch --file`). Then the **open design questions**, numbered, each
15
- with two options, their cost and your recommendation.
17
+ Return per file the findings, one per line, as `<file:line> — <rule id> — <what is wrong> — <how
18
+ it must be>`. The rule id is one from the rules at the end of this brief, or `X0` when none covers
19
+ it: never drop a finding because no rule fits (the referee registers each line with
20
+ `findings.mjs add --source batch --file`, which refuses a line without a valid id). Then the
21
+ **open design questions**, numbered, each with two options, their cost and your recommendation.
@@ -1,44 +1,42 @@
1
- <!-- Agent{subagent_type: "ring:cornerman", effort: "high"}. When a concept closes. -->
2
-
3
1
  Mode: **concept**. You are the high-effort reviewer. Read only: no edits, no commits, no index or
4
2
  tree writes in the wrestler's worktree.
5
3
 
6
- Worktree `<absolute path>`, base `<base>`, range `<A>..<B>`. Rulebook `<absolute rulebook path>`;
7
- decisions `<bout dir>/decisions.md`. Ring scripts `<absolute ring path>/scripts`.
4
+ Worktree `{{worktree}}`, base `{{base}}`, range `{{range}}`. The decisions taken are near the end of
5
+ this brief and the rules after them, at its end. Ring scripts `{{ring}}/scripts`.
8
6
 
9
- Commits and what each claims:
10
- - `<sha>` <subject> — <claim>
7
+ Commits of the concept:
8
+ {{commits}}
11
9
 
12
- Author claims to verify against the base: <…>
10
+ Author claims to verify against the base: {{claims}}
13
11
 
14
12
  **Behavior: what matters most; any change is a BLOCKER.** Invariants, numbered:
15
- 1. <messages or jobs enqueued: names, ids, options, presence of undefined keys>
16
- 2. <order of side effects>
17
- 3. <payload to providers: keys and order>
18
- 4. <counters, status transitions, error propagation>
19
- 5. <telemetry event names and fields>
20
- 6. Base test assertions: none may change (`git show <base>:<path>` before calling it a blocker).
21
-
22
- How to test: `git -C <worktree> archive <B> | tar -x -C <new temp dir>`; install there if needed;
23
- only the tests of the area, each through `node <ring>/scripts/one-at-a-time.mjs run -- <command>`;
24
- never a test run and a typecheck at the same time. For a pure-calculation refactor, a differential
25
- check old vs new that fails if you remove the key piece.
26
-
27
- **Design (UI venues, when the concept draws a screen).** You do not have the design tool, so the
28
- referee hands you the reference: the design file and node id, the measurements read from the live
29
- node with the time of that reading (sizes, spacing, colors, type, the position of the main action)
30
- and the path of an export of that node made after its last change. Compare the screenshots of the venue's matrix against them:
31
- <design file · node id · measurements · export path · screenshots>. A difference not listed by the
32
- author is a finding; text is judged by the node's content, never by a layer name.
13
+ {{invariants}}
14
+ Base test assertions: none may change (`git show {{base}}:<path>` before calling it a blocker).
15
+
16
+ How to test: `git -C {{worktree}} archive <tip> | tar -x -C <new temp dir>`; install there if
17
+ needed; only the tests of the area, each through `node {{ring}}/scripts/one-at-a-time.mjs run --
18
+ <command>`; never a test run and a typecheck at the same time. For a pure-calculation refactor, a
19
+ differential check old vs new that fails if you remove the key piece.
20
+
21
+ **Design, the whole concept at once** (what a range-by-range review cannot see): read the concept
22
+ as one piece through the lenses of this venue, {{lenses}}. An anemic aggregate built across several
23
+ commits, a dependency that points outward once the pieces are together, a condition repeated
24
+ across the files of the concept: each is a finding with its rule id.
25
+
26
+ **Design of a screen (UI venues):** {{designReference}}. A difference from the reference not
27
+ listed by the author is a finding; text is judged by the node's content, never by a layer name.
33
28
 
34
29
  **Leftovers (every concept close):**
30
+
35
31
  - Symbols left without production callers: grep, on your copy, every exported or public symbol the
36
32
  range touched and every symbol whose caller the range deleted; one used only by its own spec, or
37
33
  by nobody, is dead code.
38
- - Narrating, stale or now-wrong comments in the files the assignment covers: <paths>, including the
39
- ones this range did not edit.
40
- - Commit messages of the range (`git -C <worktree> log --format=%B <A>..<B>`) carrying bout ids
34
+ - Narrating, stale or now-wrong comments in the files the assignment covers: {{leftoverPaths}},
35
+ including the ones this range did not edit.
36
+ - Commit messages of the range (`git -C {{worktree}} log --format=%B {{range}}`) carrying bout ids
41
37
  (D12, P7, HP3, PR5…).
42
38
 
43
- Return: a table per file, a table per invariant (holds / broken + evidence), the leftovers,
44
- totals, and a one-line verdict: `APPROVED` or `REBOUND: <n> blockers, <m> fixes`.
39
+ Return: a table per file (one finding per row, `| <file:line> | <rule id> | <what> | <how> |`), a
40
+ table per invariant (holds / broken + evidence), the leftovers, totals, and a one-line verdict:
41
+ `APPROVED` or `REBOUND: <n> blockers, <m> fixes`. Every finding cites one of the rules at the end of this brief, or
42
+ `X0` when none covers it.
@@ -1,15 +1,20 @@
1
- <!-- Agent{subagent_type: "ring:cornerman", effort: "high"} -->
2
-
3
1
  Mode: **range**. Read only: no edits, no commits, no index or tree writes in any worktree.
4
2
 
5
- Worktree `<absolute path>`, base `<base>`, range `<A>..<B>`. Review each commit with
6
- `git -C <worktree> show <sha>` against the rulebook `<absolute rulebook path>` (read it first) and
7
- the decisions in `<bout dir>/decisions.md`. Only the lines these commits add or change.
3
+ Worktree `{{worktree}}`, base `{{base}}`, range `{{range}}`. Review each commit with
4
+ `git -C {{worktree}} show <sha>` against the rules at the end of this brief (the architecture
5
+ checklist first) and the decisions at its end. Only the lines these commits add or change. Ring
6
+ scripts `{{ring}}/scripts`.
7
+
8
+ Commits of the range:
9
+ {{commits}}
8
10
 
9
- <Optional: the author claims "<claim>". Verify it against the base; if a single counter, event or
10
- payload changes, it is a BLOCKER.>
11
+ Author claims to verify against the base (if a single counter, event or payload changes, it is a
12
+ BLOCKER): {{claims}}
11
13
 
12
- Return `file:line — rule id — what is wrong — how it must be`. A changed base test assertion or a
13
- renamed telemetry event goes first, marked BLOCKER. "<sha>: no findings" when a commit complies.
14
- No taste, no pre-existing debt. **At most 15 lines.** One finding per line: the referee registers
15
- each line as a finding (`findings.mjs add --file`), so never wrap one across lines.
14
+ Return one finding per line, exactly `<file:line> — <rule id> — <what is wrong> — <how it must be>`.
15
+ The rule id is the second field and must be one of the rules at the end of this brief (several as `R11/R22`); a
16
+ finding no rule covers carries `X0`, and the referee proposes the rule it lacks. A changed base
17
+ test assertion or a renamed telemetry event goes first, marked BLOCKER. "<sha>: no findings" when a
18
+ commit complies. No taste, no pre-existing debt. **At most 15 lines.** The referee registers each
19
+ line as a finding (`findings.mjs add --file`), which refuses a line without a valid rule id, so
20
+ never wrap one across lines.
@@ -2,7 +2,13 @@
2
2
  host sets delegation to "human". Under the default "referee" delegation, design doubts are
3
3
  decided and recorded, never sent here. Numbered text, answerable as "1. b", by default;
4
4
  AskUserQuestion only when the host repo's instructions require it. The wrestler keeps working
5
- on something else meanwhile: never leave it idle waiting for an answer. -->
5
+ on something else meanwhile: never leave it idle waiting for an answer.
6
+ Keep each question on one numbered line with its options «(a) … · (b) …» and «I recommend
7
+ (x)» (or «Te recomiendo (x)»): `judges-card.mjs log <pr> escalation <file>` reads them from
8
+ there for the chronicle's interview, and `log <pr> answer` stamps the judge's reply.
9
+ Write its context too, in a file of its own, one `## Contexto <n> · <question>` section per
10
+ question: what each option includes, leaves out and costs. Log it with `--context <file>`;
11
+ the chronicle shows it under «Ver más información». -->
6
12
 
7
13
  **Done up to `<sha>`** (<concept>, round-bell #<n>).
8
14
 
@@ -9,6 +9,10 @@
9
9
 
10
10
  Production lines, tests excluded: {{productionStat}}
11
11
 
12
+ ## What changes for whom
13
+
14
+ {{flowChange}}
15
+
12
16
  ## What to read first
13
17
 
14
18
  {{readFirst}}
@@ -1,58 +1,45 @@
1
- <!-- The referee fills every <…> and sends this as the prompt of
2
- Agent{subagent_type: "ring:wrestler", effort: "medium", run_in_background: true}.
3
- Never `isolation: "worktree"`: that creates a new tree on another branch. -->
1
+ Assignment: {{assignment}}. PR #{{pr}}, branch `{{branch}}`, stack base `{{base}}`.
4
2
 
5
- Assignment: <what and why, in 3 lines>. PR #<pr>, branch `<branch>`, stack base `<base>`.
3
+ Flow change (P15): {{flowChange}}
6
4
 
7
- Worktree: `<absolute worktree path>`. Your cwd resets: every git command is `git -C <worktree> …`.
8
- Start with: `git -C <worktree> fetch -q origin && git -C <worktree> checkout -B <branch> origin/<branch>`.
9
- Ring scripts: `<absolute ring path>/scripts` (one-at-a-time.mjs lives there).
10
- Bout dir: `<bout dir>`. A helper script you need goes in `<bout dir>/tools/`, never in the repo.
5
+ Worktree: `{{worktree}}`. Your cwd resets: every git command is `git -C {{worktree}} …`.
6
+ Start with: `git -C {{worktree}} fetch -q origin && git -C {{worktree}} checkout -B {{branch}} origin/{{branch}}`.
7
+ Ring scripts: `{{ring}}/scripts` (one-at-a-time.mjs lives there).
8
+ Bout dir: `{{boutDir}}`. A helper script you need goes in `{{boutDir}}/tools/`, never in the repo.
11
9
  Write only inside your worktree; never in the main checkout or any other tree.
12
10
 
13
- Rulebook: `<absolute rulebook path>` (read it in full; rebounds cite its rule ids).
14
- Precedents: `<bundled precedents path>` (PRn) and `<host precedents path or "none">` (HPn); rebounds
15
- cite them too.
16
- Decisions already taken (do not reopen them): `<bout dir>/decisions.md`.
11
+ Rules: the rulebook and the precedents of this venue ({{venue}}) are at the end of this brief, in
12
+ full. They are the ones in force: apply them while you write, not only when a rebound cites them,
13
+ and check the architecture checklist before every commit.
14
+ Decisions already taken (do not reopen them): the excerpt before the rules; the whole
15
+ ledger is `{{boutDir}}/decisions.md`.
17
16
 
18
- Comments to address: <`gh api repos/<o>/<r>/pulls/<pr>/comments`, plus the list>.
19
- Reference pattern: <`gh pr diff <n>` of the round-bell the human approved> — replicate it.
17
+ Comments to address: {{comments}}
18
+ Reference pattern: {{referencePattern}}
20
19
 
21
- Order of concepts: 1. <pilot: one small concept, as a sample for the human> 2. <…> 3. <…>
20
+ Order of concepts: {{concepts}}
21
+ One commit per theme, never one commit for a whole concept: a removal goes with the tests it
22
+ updates; a behavior change (what the flow-change line names, or an error that now surfaces
23
+ differently) goes in its own commit with the test that pins it (T6); renames and formatting go
24
+ apart from logic.
22
25
  Commit locally and never push: when you close 2–3 commits (or ~200 lines), report the range and
23
26
  keep going only if I have not stopped you. The PR branch receives what the cornerman approved, and I
24
- push it; every commit you close is backed up for you to `ring/<pr>/respaldo`, approved or not. If mask-guard says the review cap is
25
- reached, report the range and wait for me.
27
+ push it; every commit you close is backed up for you to `{{backupBranch}}`, approved or not. If
28
+ mask-guard says the review cap is reached, report the range and wait for me.
26
29
 
27
- Frozen zones (do not touch): <paths>.
28
- WAITING ON THE HUMAN (hard list; do not touch): <list>.
30
+ Frozen zones (do not touch): {{frozen}}.
31
+ WAITING ON THE HUMAN (hard list; do not touch): {{waitingOnHuman}}.
29
32
  Design doubts go to me, never to the human: I decide them (or escalate them) and tell you.
30
33
 
31
34
  Gates (from `.claude/ring.json`, each through one-at-a-time; a long run such as a battery adds
32
35
  `--monitor <id>` when its command does not match a declared monitor, so it shows on the Scorecard):
33
- - typecheck: `<command>`
34
- - tests of what you touched: `<command with {paths}>`
35
- - lint: `<command>`
36
+
37
+ - typecheck: `{{gateTypecheck}}`
38
+ - tests of what you touched: `{{gateTest}}`
39
+ - lint: `{{gateLint}}`
36
40
 
37
41
  Standing conditions: behavior identical; no base test assertion changes (if one has to, stop and
38
42
  tell me first); no new flags or env vars; one heavy command at a time; stage by paths;
39
- forbidAiTrailers is <true|false> (when true, no AI attribution trailers; human co-authors are
40
- fine); disk floor <5> GB.
43
+ forbidAiTrailers is {{forbidAiTrailers}} (when true, no AI attribution trailers; human co-authors
44
+ are fine); disk floor {{diskFloor}} GB.
41
45
  Do NOT run reviewers, review loops or Copilot. Do NOT open ready PRs. Do NOT merge or change bases.
42
-
43
- ---
44
-
45
- ## Resume variant (a new session relaunches the wrestler)
46
-
47
- Same brief, plus at the top:
48
-
49
- You are resuming bout #<pr>; the previous wrestler stopped at `<sha>` while working on
50
- "<last subject>". First `git -C <worktree> status` and `git -C <worktree> diff`: finish and commit
51
- what was left uncommitted. Then read the open rebounds (`<bout dir>/rebounds.md`) and report the
52
- commit you are on before continuing with <concept>.
53
-
54
- ## Cut-off variant (the same wrestler lost its connection)
55
-
56
- The API cut you off mid-edit (you were on "<last subject>"). `git status` and `git diff`, finish
57
- what was left uncommitted, commit it, read the last rebound (`<bout dir>/rebounds.md`) and report
58
- the commit you are on.
@@ -0,0 +1,4 @@
1
+ The API cut you off mid-edit (you were on "{{lastSubject}}", at `{{headSha}}`). `git -C {{worktree}} status`
2
+ and `git -C {{worktree}} diff`, finish what was left uncommitted, commit it, read the last rebound
3
+ (`{{boutDir}}/rebounds.md`) and report the commit you are on. The rules you work by are the ones
4
+ your first brief embedded; nothing about them changed.
@@ -0,0 +1,4 @@
1
+ You are a new wrestler on bout #{{pr}}. The previous one stopped at `{{headSha}}` ("{{lastSubject}}").
2
+ First `git -C {{worktree}} status` and `git -C {{worktree}} diff`: finish and commit what was left
3
+ uncommitted. Then read the open rebounds (`{{boutDir}}/rebounds.md`) and report the commit you are
4
+ on before continuing with {{nextConcept}}.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: sparring
3
- description: Opens a sparring, a quick and deliberately low-quality draft (one PR per repo it touches, back and front included) that only proves whether a feature is worth building, before anyone pays for building it well. A rudo per repo (effort medium) writes it inside a timebox in its own worktree; the draft PR (labels sparring + do-not-merge) is the event the host project's CI catches to deploy a preview; credentials travel by name only. The judge calls KO, rematch or discard, in two out of three falls: a KO passes the host gates (vestidor), faces the team's Tapes until a bell (unless «sin equipo»), keeps or loses the mask, and then hands each branch to a ring bout. Invoke with `/ring:sparring <idea | Linear ticket>`, `/ring:sparring preview <slug>`, `/ring:sparring verdict <slug>`, `/ring:sparring list`, "make a quick draft of this to try it", "spar this feature first".
3
+ description: Opens a sparring, a quick and deliberately low-quality draft (one PR per repo it touches, back and front included) that only proves whether a feature is worth building, before anyone pays for building it well. A rudo per repo (Sonnet at effort high by default) writes it inside a timebox in its own worktree; the draft PR (labels sparring + do-not-merge) is the event the host project's CI catches to deploy a preview; credentials travel by name only. The judge calls KO, rematch or discard, in two out of three falls: a KO passes the host gates (vestidor), faces the team's Tapes until a bell (unless «sin equipo»), keeps or loses the mask, and then hands each branch to a ring bout. Invoke with `/ring:sparring <idea | Linear ticket>`, `/ring:sparring preview <slug>`, `/ring:sparring verdict <slug>`, `/ring:sparring list`, "make a quick draft of this to try it", "spar this feature first".
4
4
  argument-hint: '<idea | ticket> | preview <slug> | verdict <slug> | vestidor <slug> | list'
5
5
  ---
6
6
 
@@ -29,8 +29,16 @@ rest of the timebox goes to the controls that are still dead. Where time goes, a
29
29
  correction. Everything that does not change the hypothesis, the proof, the scope or a hard stop,
30
30
  you decide without asking, then and while the rudos work.
31
31
  - **Contract first, in the first 15 minutes.** With several repos, the producer writes the contract
32
- (routes, shapes, error codes) to `<sparring dir>/contrato.md` before implementing, and every rudo
33
- starts at once against it. The consumer never waits for the producer's code.
32
+ (routes, shapes, error codes) to its own `<sparring dir>/contrato-<repo>.md` before implementing,
33
+ and every rudo starts at once against it. The consumer never waits for the producer's code.
34
+ - **Every contract is written down the moment it is proposed**, with one repo too: each endpoint
35
+ and each data model a rudo adds or changes goes to `<sparring dir>/contrato-<repo>.md`
36
+ (`templates/contrato.md`) before it is implemented, with its shortcuts, and stays current when
37
+ the rudo changes it. **One file per repo, written only by that repo's rudo**: rudos run at the
38
+ same time, and two editing one file overwrite each other's entries. A rudo reads another repo's
39
+ file, never writes it. The sparring approves none of it: the referee bout that refactors a KO
40
+ opens with these bases and takes them to the judge first, because most of the code to build
41
+ depends on them.
34
42
  - **Ceremony the rudo skips:** migrations in the repo (tables come from a SQL in `tools/`), OpenAPI
35
43
  and generated types until the last push, typecheck after every edit (only before each push),
36
44
  tests, wiki, DTOs, CQRS, ports, feature flags. Each one goes on the shortcuts list.
@@ -114,7 +122,8 @@ defense|bell|mask-kept|mask-lost|no-team` the rest).
114
122
  for its repo (scope, designs, the other repos and what they exchange):
115
123
 
116
124
  ```
117
- Agent{subagent_type: "ring:rudo", effort: "medium", run_in_background: true,
125
+ Agent{subagent_type: "ring:rudo", model: "<config.agents.rudo.model>",
126
+ effort: "<config.agents.rudo.effort>", run_in_background: true,
118
127
  description: "Rudo: <slug> <repo>", prompt: <the brief>}
119
128
  ```
120
129