@claudexor/arbitration 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 joi-lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # @claudexor/arbitration
2
+
3
+ Internal package of [Claudexor](https://github.com/razzant/claudexor) — Evidence-first arbitration: rank candidates on typed gate/review evidence, pairwise tie-breaks, DecisionRecord.
4
+
5
+ Published as part of the Claudexor toolchain; it follows the monorepo's
6
+ lockstep version and has no separate semver contract. Use the `claudexor`
7
+ CLI (or `@claudexor/cli`) as the supported entry point.
@@ -0,0 +1,51 @@
1
+ import type { DecisionRecord, GateResult, PairwiseComparison, ReviewFinding } from "@claudexor/schema";
2
+ /** Evidence assembled for one tournament candidate. */
3
+ export interface CandidateEvidence {
4
+ attemptId: string;
5
+ /** Anonymized label shown to the arbiter (e.g. "Candidate A"). */
6
+ label: string;
7
+ gates: GateResult[];
8
+ acceptanceCovered: string[];
9
+ acceptanceTotal: number;
10
+ findings: ReviewFinding[];
11
+ testsPassed: number;
12
+ testsTotal: number;
13
+ finalReviewClean: boolean;
14
+ reviewVerified?: boolean;
15
+ /** Non-blocking tool hygiene warnings from the engine-owned attempt outcome. */
16
+ toolWarningsCount?: number;
17
+ /** Smaller = simpler (e.g. diff line count). */
18
+ diffSize?: number;
19
+ diffBytes?: number;
20
+ costUsd?: number;
21
+ }
22
+ /** Higher is better, compared lexicographically (evidence-first ordering). */
23
+ export declare function scoreTuple(c: CandidateEvidence): number[];
24
+ /** Compare two candidates (best-first): negative if `a` should rank ahead of `b`. */
25
+ export declare function compareCandidates(a: CandidateEvidence, b: CandidateEvidence): number;
26
+ export interface CandidateSummary {
27
+ gatesPassed: boolean;
28
+ blockers: number;
29
+ acceptance: number;
30
+ testFraction: number;
31
+ clean: boolean;
32
+ }
33
+ export declare function candidateSummary(c: CandidateEvidence): CandidateSummary;
34
+ export interface ArbitrationResult {
35
+ ranking: CandidateEvidence[];
36
+ decision: DecisionRecord;
37
+ pairwise: PairwiseComparison[];
38
+ }
39
+ /**
40
+ * Evidence-first arbitration. Ranks candidates lexicographically by hard gates,
41
+ * acceptance coverage, accepted blockers, tests, clean
42
+ * review, simplicity, cost. When the top two candidates are an EXACT
43
+ * tie on every evidence axis, the winner is chosen deterministically by route
44
+ * order and that tie is DISCLOSED in the decision (final_checks) — there is no
45
+ * hidden LLM tie-break, so the choice is never silently presented as decisive.
46
+ */
47
+ export declare function arbitrate(candidates: CandidateEvidence[], opts?: {
48
+ spendUsd?: number | null;
49
+ estimatedSpend?: boolean;
50
+ }): ArbitrationResult;
51
+ //# sourceMappingURL=arbitration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arbitration.d.ts","sourceRoot":"","sources":["../src/arbitration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvG,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA+CD,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAWzD;AAWD,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAEpF;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,iBAAiB,GAAG,gBAAgB,CAQvE;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;CAChC;AA0DD;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,iBAAiB,EAAE,EAC/B,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,GAChE,iBAAiB,CAoInB"}
@@ -0,0 +1,262 @@
1
+ import { DecisionRecord as DecisionRecordSchema, isBlocking } from "@claudexor/schema";
2
+ function requiredGatesPassed(c) {
3
+ const required = c.gates.filter((g) => g.required);
4
+ return required.length === 0 ? true : required.every((g) => g.status === "passed");
5
+ }
6
+ /**
7
+ * Acceptance coverage fraction. Zero configured success criteria is zero
8
+ * acceptance EVIDENCE (0, never a vacuous 1), mirroring `effectiveTestFraction`.
9
+ * Since all candidates in a tournament share one contract, a 0 here is a neutral
10
+ * tie axis (no relative penalty) — it only removes the false "100%" claim.
11
+ */
12
+ function acceptanceFraction(c) {
13
+ return c.acceptanceTotal > 0 ? c.acceptanceCovered.length / c.acceptanceTotal : 0;
14
+ }
15
+ /** Human label for gate-derived criteria coverage: honest "n/a" when no
16
+ * criteria exist. Named gates_coverage in decision strings: the
17
+ * number is a PROXY derived from the deterministic gates (all criteria
18
+ * count as covered only when gates pass), not independent per-criterion
19
+ * acceptance evidence. */
20
+ function acceptanceLabel(c) {
21
+ return c.acceptanceTotal > 0 ? `${(acceptanceFraction(c) * 100).toFixed(0)}%` : "n/a";
22
+ }
23
+ function openBlockerCount(c) {
24
+ return c.findings.filter((f) => isBlocking(f)).length;
25
+ }
26
+ /**
27
+ * Test pass-fraction. Zero configured tests is zero test EVIDENCE (0, never a
28
+ * vacuous 1): a candidate with no tests must not score "100%" in rankings or
29
+ * user-facing decision strings. (The held-out split axis was retired in the
30
+ * v0.15 triage: no producer ever populated it — re-add WITH a real held-out
31
+ * runner if that anti-reward-hacking design returns.)
32
+ */
33
+ function effectiveTestFraction(c) {
34
+ return c.testsTotal > 0 ? c.testsPassed / c.testsTotal : 0;
35
+ }
36
+ /** Human label for test evidence: honest "n/a" when no tests exist at all. */
37
+ function testEvidenceLabel(c) {
38
+ if (c.testsTotal === 0)
39
+ return "n/a";
40
+ return `${(effectiveTestFraction(c) * 100).toFixed(0)}%`;
41
+ }
42
+ /** Higher is better, compared lexicographically (evidence-first ordering). */
43
+ export function scoreTuple(c) {
44
+ return [
45
+ requiredGatesPassed(c) ? 1 : 0, // hard gates
46
+ acceptanceFraction(c), // acceptance coverage
47
+ -openBlockerCount(c), // fewer accepted blockers
48
+ effectiveTestFraction(c), // deterministic test pass fraction
49
+ c.finalReviewClean ? 1 : 0, // final clean review
50
+ -(c.toolWarningsCount ?? 0), // cleaner tool hygiene
51
+ -(c.diffSize ?? 0), // simplicity
52
+ -(c.costUsd ?? 0), // cost
53
+ ];
54
+ }
55
+ function compareTuples(a, b) {
56
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
57
+ const av = a[i] ?? 0;
58
+ const bv = b[i] ?? 0;
59
+ if (av !== bv)
60
+ return av > bv ? -1 : 1; // sort best-first
61
+ }
62
+ return 0;
63
+ }
64
+ /** Compare two candidates (best-first): negative if `a` should rank ahead of `b`. */
65
+ export function compareCandidates(a, b) {
66
+ return compareTuples(scoreTuple(a), scoreTuple(b));
67
+ }
68
+ export function candidateSummary(c) {
69
+ return {
70
+ gatesPassed: requiredGatesPassed(c),
71
+ blockers: openBlockerCount(c),
72
+ acceptance: acceptanceFraction(c),
73
+ testFraction: effectiveTestFraction(c),
74
+ clean: c.finalReviewClean,
75
+ };
76
+ }
77
+ const CRITERIA = [
78
+ {
79
+ key: "gates",
80
+ better: (a, b) => requiredGatesPassed(a) === requiredGatesPassed(b) ? "tie" : requiredGatesPassed(a) ? "a" : "b",
81
+ },
82
+ {
83
+ key: "gates_coverage",
84
+ better: (a, b) => acceptanceFraction(a) === acceptanceFraction(b) ? "tie" : acceptanceFraction(a) > acceptanceFraction(b) ? "a" : "b",
85
+ },
86
+ {
87
+ key: "blockers",
88
+ better: (a, b) => openBlockerCount(a) === openBlockerCount(b) ? "tie" : openBlockerCount(a) < openBlockerCount(b) ? "a" : "b",
89
+ },
90
+ {
91
+ key: "tests",
92
+ better: (a, b) => effectiveTestFraction(a) === effectiveTestFraction(b)
93
+ ? "tie"
94
+ : effectiveTestFraction(a) > effectiveTestFraction(b)
95
+ ? "a"
96
+ : "b",
97
+ },
98
+ ];
99
+ /** Concrete per-criterion evidence values, so the persisted pairwise reason
100
+ * says WHAT differed (not just which axis name was consulted). */
101
+ function criterionValue(key, c) {
102
+ switch (key) {
103
+ case "gates":
104
+ return requiredGatesPassed(c) ? "required gates passed" : "required gates FAILED";
105
+ case "gates_coverage":
106
+ return `acceptance ${(acceptanceFraction(c) * 100).toFixed(0)}%`;
107
+ case "blockers":
108
+ return `${openBlockerCount(c)} open blocker(s)`;
109
+ case "tests":
110
+ return `tests ${testEvidenceLabel(c)}`;
111
+ default:
112
+ return key;
113
+ }
114
+ }
115
+ function pairwise(a, b) {
116
+ const criteria = {};
117
+ for (const c of CRITERIA) {
118
+ const winner = c.better(a, b);
119
+ criteria[c.key] = {
120
+ winner,
121
+ reason: `${a.label}: ${criterionValue(c.key, a)} vs ${b.label}: ${criterionValue(c.key, b)}`,
122
+ };
123
+ }
124
+ return { candidate_a: a.label, candidate_b: b.label, criteria };
125
+ }
126
+ /**
127
+ * Evidence-first arbitration. Ranks candidates lexicographically by hard gates,
128
+ * acceptance coverage, accepted blockers, tests, clean
129
+ * review, simplicity, cost. When the top two candidates are an EXACT
130
+ * tie on every evidence axis, the winner is chosen deterministically by route
131
+ * order and that tie is DISCLOSED in the decision (final_checks) — there is no
132
+ * hidden LLM tie-break, so the choice is never silently presented as decisive.
133
+ */
134
+ export function arbitrate(candidates, opts = {}) {
135
+ if (candidates.length === 0) {
136
+ return {
137
+ ranking: [],
138
+ decision: DecisionRecordSchema.parse({
139
+ winner: null,
140
+ status: "failed",
141
+ outcome: "blocked",
142
+ why_winner: "no candidates",
143
+ evidence_facts: ["no candidates were produced"],
144
+ apply_recommendation: "continue",
145
+ }),
146
+ pairwise: [],
147
+ };
148
+ }
149
+ const ranking = [...candidates].sort((a, b) => compareTuples(scoreTuple(a), scoreTuple(b)));
150
+ const winner = ranking[0];
151
+ const runnerUp = ranking[1];
152
+ // An exact tie on every evidence axis: the winner is the first in route order.
153
+ // Disclose it instead of presenting the pick as evidence-decisive.
154
+ const tiedWithRunnerUp = runnerUp ? compareTuples(scoreTuple(winner), scoreTuple(runnerUp)) === 0 : false;
155
+ const requiredOk = requiredGatesPassed(winner);
156
+ const blockerCount = openBlockerCount(winner);
157
+ const winnerOk = requiredOk && winner.finalReviewClean && blockerCount === 0;
158
+ const noOpOk = requiredOk && blockerCount === 0;
159
+ const hasDiff = (winner.diffBytes ?? winner.diffSize ?? 0) > 0;
160
+ const hasGates = winner.testsTotal > 0 || winner.gates.length > 0;
161
+ const reviewRan = winner.reviewVerified === true;
162
+ // A clean, route-proof-VERIFIED cross-family review is real verification even
163
+ // when no deterministic test gate is configured. `reviewRan` already
164
+ // requires crossFamilyVerified (observed route proofs, §5), so this never
165
+ // adopts an unobserved/argv-echo review. The patch-hash binding is enforced
166
+ // separately by the apply gate.
167
+ const reviewCleanVerified = reviewRan && winner.finalReviewClean && blockerCount === 0;
168
+ const harnessFailed = winner.gates.some((g) => g.id === "harness" && g.status === "failed");
169
+ const outcome = harnessFailed
170
+ ? "blocked"
171
+ : !hasDiff
172
+ ? noOpOk
173
+ ? "no_op"
174
+ : "blocked"
175
+ : !hasGates
176
+ ? reviewCleanVerified
177
+ ? "ready"
178
+ : "ungated"
179
+ : !reviewRan
180
+ ? "review_not_run"
181
+ : winnerOk
182
+ ? "ready"
183
+ : "blocked";
184
+ // Honest disclosure of WHAT verified an applyable run. "both" requires a
185
+ // DETERMINISTIC gate — a real test count or a REQUIRED gate that passed — not
186
+ // mere gate presence (a non-required/diagnostic gate must not read as "tests
187
+ // passed"). A no-gate run adopted on review evidence is cross_family_review.
188
+ const gateVerified = (winner.testsTotal > 0 && winner.testsPassed === winner.testsTotal) || winner.gates.some((g) => g.required && g.status === "passed");
189
+ const verificationBasis = outcome === "ready" ? (gateVerified ? "both" : "cross_family_review") : "none";
190
+ const status = harnessFailed
191
+ ? "failed"
192
+ : outcome === "ready"
193
+ ? "success"
194
+ : outcome === "no_op"
195
+ ? "no_op"
196
+ : outcome === "ungated"
197
+ ? "ungated"
198
+ : outcome === "review_not_run"
199
+ ? "review_not_run"
200
+ : "not_converged";
201
+ const whyNot = {};
202
+ for (const c of ranking.slice(1)) {
203
+ const reasons = [];
204
+ if (!requiredGatesPassed(c))
205
+ reasons.push("required gates not all passing");
206
+ if (openBlockerCount(c) > 0)
207
+ reasons.push(`${openBlockerCount(c)} open blocker(s)`);
208
+ if (acceptanceFraction(c) < acceptanceFraction(winner))
209
+ reasons.push("lower gates-derived criteria coverage");
210
+ if (effectiveTestFraction(c) < effectiveTestFraction(winner))
211
+ reasons.push("weaker test evidence");
212
+ if (!c.finalReviewClean)
213
+ reasons.push("no clean final review");
214
+ whyNot[c.label] = reasons.length > 0 ? reasons.join("; ") : "narrowly behind on tie-breakers";
215
+ }
216
+ const acceptedRisks = winner.findings
217
+ .filter((f) => f.status === "accepted_risk")
218
+ .map((f) => f.claim);
219
+ const decision = DecisionRecordSchema.parse({
220
+ winner: winner.attemptId,
221
+ status,
222
+ outcome,
223
+ why_winner: `${winner.label}: gates=${requiredGatesPassed(winner)}, gates_coverage=${acceptanceLabel(winner)}, blockers=${openBlockerCount(winner)}, tests=${testEvidenceLabel(winner)}, cleanReview=${winner.finalReviewClean}`,
224
+ why_not_others: whyNot,
225
+ accepted_risks: acceptedRisks,
226
+ final_checks: [
227
+ `required gates ${requiredGatesPassed(winner) ? "passed" : "FAILED"}`,
228
+ `final cross-family review ${winner.finalReviewClean ? "clean" : "not clean"}`,
229
+ ...(tiedWithRunnerUp
230
+ ? [`tie: winner chosen by route order (no distinguishing evidence vs ${runnerUp?.label ?? "runner-up"})`]
231
+ : []),
232
+ ],
233
+ evidence_facts: [
234
+ `diff ${hasDiff ? "non-empty" : "empty"}`,
235
+ `gates ${hasGates ? "configured" : "not configured"}`,
236
+ `review ${reviewRan ? "verified" : "not verified"}`,
237
+ `blockers ${openBlockerCount(winner)}`,
238
+ ],
239
+ budget_summary: {
240
+ spend_usd: opts.spendUsd ?? winner.costUsd ?? null,
241
+ estimated: opts.estimatedSpend ?? false,
242
+ },
243
+ apply_recommendation: outcome === "ready"
244
+ ? "apply"
245
+ : outcome === "no_op"
246
+ ? "inspect"
247
+ : outcome === "ungated" || outcome === "review_not_run"
248
+ ? "human_review"
249
+ : openBlockerCount(winner) > 0
250
+ ? "human_review"
251
+ : "continue",
252
+ verification_basis: verificationBasis,
253
+ });
254
+ const pairs = [];
255
+ for (let i = 0; i < ranking.length; i++) {
256
+ for (let j = i + 1; j < ranking.length; j++) {
257
+ pairs.push(pairwise(ranking[i], ranking[j]));
258
+ }
259
+ }
260
+ return { ranking, decision, pairwise: pairs };
261
+ }
262
+ //# sourceMappingURL=arbitration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arbitration.js","sourceRoot":"","sources":["../src/arbitration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from "./arbitration.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./arbitration.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@claudexor/arbitration",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "description": "Evidence-first arbitration: rank candidates on typed gate/review evidence, pairwise tie-breaks, DecisionRecord.",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "dependencies": {
19
+ "@claudexor/schema": "1.0.0"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/razzant/claudexor.git",
24
+ "directory": "packages/arbitration"
25
+ },
26
+ "homepage": "https://github.com/razzant/claudexor#readme",
27
+ "bugs": {
28
+ "url": "https://github.com/razzant/claudexor/issues"
29
+ },
30
+ "engines": {
31
+ "node": ">=20.19"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "scripts": {
37
+ "build": "tsc",
38
+ "typecheck": "tsc --noEmit"
39
+ }
40
+ }