@thebattlearena/corner 0.10.1-beta.81 → 0.10.1-beta.82
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
CHANGED
|
@@ -439,7 +439,7 @@ accept|reject --why "<lo que dijo el humano>"`.
|
|
|
439
439
|
|
|
440
440
|
**Revisión humana por bloques (PR Review Lab)**: cada punto del plan técnico es un bloque (`B<n>` es
|
|
441
441
|
el punto n). `judges-card.mjs plan <pr> estimate <n> --minutes <m> [--priority 1-4]` le pone estimado y
|
|
442
|
-
prioridad. Al pasar a «en curso» se anotan el inicio y el autor (el `user.email` de git del worktree),
|
|
442
|
+
prioridad (sin ellos un bloque no arranca; también van en el mismo comando: `plan <pr> <n> "en curso" --minutes <m> --priority <p>`). Al pasar a «en curso» se anotan el inicio y el autor (el `user.email` de git del worktree),
|
|
443
443
|
y al pasar a «espera al juez» el fin y el rango (`--range A..B` lo fija a mano); todo va en
|
|
444
444
|
`plan.jsonl`, que es lo que lee el modo «Pelea del ring» de PR Review Lab. Cuando `humanReviewEvery`
|
|
445
445
|
bloques (2 por default, `null` lo apaga) esperan al juez, suena la campana en PR Review Lab y
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thebattlearena/corner",
|
|
3
|
-
"version": "0.10.1-beta.
|
|
3
|
+
"version": "0.10.1-beta.82",
|
|
4
4
|
"description": "Corner: tu esquina de Battle Arena en Claude Code (el plugin `battlearena`). Hooks de tracking, objetivo del turno, plan de batalla /battlearena:conquer, Ringside (el panel de tu día), el ring y la radio. Zero-dependency.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -610,10 +610,25 @@ function plan([pr, target, ...rest]) {
|
|
|
610
610
|
const [state] = rest;
|
|
611
611
|
if (!target || !state)
|
|
612
612
|
throw new Error(
|
|
613
|
-
'usage: plan <pr> <n|title> <pendiente|espera al juez|en curso|hecho> [--ref <sha|round-bell>] [--range A..B] | estimate <n> --minutes <m> [--priority 1-4] | add … | list',
|
|
613
|
+
'usage: plan <pr> <n|title> <pendiente|espera al juez|en curso|hecho> [--ref <sha|round-bell>] [--range A..B] [--minutes <m> --priority <1-4>] | estimate <n> --minutes <m> [--priority 1-4] | add … | list',
|
|
614
614
|
);
|
|
615
|
+
const { config } = loadConfig(projectDir(), {
|
|
616
|
+
contract: false,
|
|
617
|
+
venue: readState(dir).venue ?? DEFAULT_VENUE,
|
|
618
|
+
});
|
|
619
|
+
const inline = [value('--minutes'), value('--priority')].some(
|
|
620
|
+
(given) => given != null,
|
|
621
|
+
);
|
|
615
622
|
const changed = setPlanState(dir, target, state, value('--ref'), undefined, {
|
|
616
623
|
range: value('--range'),
|
|
624
|
+
estimate: inline
|
|
625
|
+
? estimateFacts({
|
|
626
|
+
priority: value('--priority'),
|
|
627
|
+
minutes: value('--minutes'),
|
|
628
|
+
})
|
|
629
|
+
: null,
|
|
630
|
+
// Under the human review by blocks a block starts with its estimate and priority.
|
|
631
|
+
requireEstimate: Boolean(config.humanReviewEvery),
|
|
617
632
|
});
|
|
618
633
|
console.log(
|
|
619
634
|
`${changed.n}. ${changed.title}: ${changed.from} → ${changed.to} at ${localStamp(new Date())}${changed.facts.range && changed.to === 'espera al juez' ? ` · range ${changed.facts.range}` : ''}`,
|
|
@@ -70,6 +70,21 @@ export function factsForState(previous, to, { at, head, email, range }) {
|
|
|
70
70
|
return {};
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Why a block may not start: under the human review by blocks, a block enters «en curso» only with
|
|
75
|
+
* its estimate and priority (PR Review Lab orders by one and calibrates the other against the real
|
|
76
|
+
* time per person). Null when it may. PURE.
|
|
77
|
+
*/
|
|
78
|
+
export function startRefusal(facts, to, n) {
|
|
79
|
+
if (to !== 'en curso') return null;
|
|
80
|
+
const missing = [
|
|
81
|
+
facts.estimateMin == null && '--minutes <m>',
|
|
82
|
+
facts.priority == null && '--priority <1-4>',
|
|
83
|
+
].filter(Boolean);
|
|
84
|
+
if (!missing.length) return null;
|
|
85
|
+
return `B${n} has no ${facts.estimateMin == null ? 'estimate' : 'priority'} yet: a block starts with its estimate and priority (the human review by blocks). Add ${missing.join(' ')} to this command, or run plan <pr> estimate ${n} ${missing.join(' ')} first`;
|
|
86
|
+
}
|
|
87
|
+
|
|
73
88
|
/** Checks an estimate: priority 1–4 and whole minutes. PURE. */
|
|
74
89
|
export function estimateFacts({ priority, minutes }) {
|
|
75
90
|
const facts = {};
|
|
@@ -12,7 +12,12 @@ import { join } from 'node:path';
|
|
|
12
12
|
|
|
13
13
|
import { readState } from './config.mjs';
|
|
14
14
|
import { scriptJson } from './contract-endpoints.mjs';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
authorEmail,
|
|
17
|
+
blockFacts,
|
|
18
|
+
factsForState,
|
|
19
|
+
startRefusal,
|
|
20
|
+
} from './review-blocks.mjs';
|
|
16
21
|
import {
|
|
17
22
|
parsePlan,
|
|
18
23
|
parsePlanLog,
|
|
@@ -34,7 +39,7 @@ export function setPlanState(
|
|
|
34
39
|
state,
|
|
35
40
|
ref = null,
|
|
36
41
|
at = new Date().toISOString(),
|
|
37
|
-
{ range = null, estimate = null } = {},
|
|
42
|
+
{ range = null, estimate = null, requireEstimate = false } = {},
|
|
38
43
|
) {
|
|
39
44
|
const file = join(dir, PLAN);
|
|
40
45
|
const markdown = read(file);
|
|
@@ -58,6 +63,11 @@ export function setPlanState(
|
|
|
58
63
|
range,
|
|
59
64
|
})),
|
|
60
65
|
};
|
|
66
|
+
const refusal =
|
|
67
|
+
requireEstimate && next !== item.state
|
|
68
|
+
? startRefusal(facts, next, item.n)
|
|
69
|
+
: null;
|
|
70
|
+
if (refusal) throw new Error(refusal);
|
|
61
71
|
writeFileSync(file, withPlanState(markdown, item, next));
|
|
62
72
|
appendFileSync(
|
|
63
73
|
join(dir, PLAN_LOG),
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: referee
|
|
3
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
|
+
effort: high
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# referee
|
|
@@ -212,7 +213,8 @@ way out, and it refuses without a KO. Then the bout runs as always, with three i
|
|
|
212
213
|
`brief.mjs` briefs no wrestler. That is what a compaction or a new session resumes from.
|
|
213
214
|
**Human review by blocks**: each point of the technical plan is a block. Give each its estimate
|
|
214
215
|
and priority when the plan is made (`judges-card.mjs plan <pr> estimate <n> --minutes <m>
|
|
215
|
-
--priority <1-4
|
|
216
|
+
--priority <1-4>`; the script refuses to start a block without both, or pass them with the
|
|
217
|
+
start: `plan <pr> <n> "en curso" --minutes <m> --priority <p>`), move it to «en curso» when its wrestler starts and to «espera al juez» when
|
|
216
218
|
its review passes (that stamps the author, the times and the range PR Review Lab reviews). Every
|
|
217
219
|
`humanReviewEvery` blocks waiting, brief.mjs stops: the human reviews that cut in PR Review Lab
|
|
218
220
|
(bout mode) and signs a verdict with a Tape. The next brief applies it: a pass closes the
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: sparring
|
|
3
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 bell <slug>`, `/ring:sparring mask <slug> [kept|lost]`, `/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> | bell <slug> | mask <slug> [kept|lost] | list'
|
|
5
|
+
effort: high
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# sparring
|