nexus-agents 8.58.2 → 8.58.4
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/dist/{ast-rule-runner-PIEUVYH5.js → ast-rule-runner-NIX2R2ER.js} +3 -3
- package/dist/{child-mcp-config-ZXP5YKTJ.js → child-mcp-config-LBCDGXVO.js} +2 -2
- package/dist/{chunk-YF3YIHPZ.js → chunk-3A5BXLPV.js} +695 -621
- package/dist/chunk-3A5BXLPV.js.map +1 -0
- package/dist/{chunk-MHXSHTHG.js → chunk-3JJHGGTT.js} +2 -2
- package/dist/{chunk-3JOMLFC7.js → chunk-4FFTWLHX.js} +10 -8
- package/dist/{chunk-3JOMLFC7.js.map → chunk-4FFTWLHX.js.map} +1 -1
- package/dist/{chunk-CGEWEJDT.js → chunk-5HAKYKCY.js} +2 -2
- package/dist/{chunk-QSSP62D3.js → chunk-5RSH7N6W.js} +2 -2
- package/dist/{chunk-HGR5L7C4.js → chunk-67AADYKZ.js} +2 -2
- package/dist/{chunk-JF77LAYJ.js → chunk-6DYJTPER.js} +3 -3
- package/dist/{chunk-RNWUIQTZ.js → chunk-AKC7SODA.js} +2 -2
- package/dist/{chunk-4UEZ2U5Q.js → chunk-AQHLUZ44.js} +2 -2
- package/dist/{chunk-PMWQSCYE.js → chunk-ARUHRGGB.js} +2 -2
- package/dist/{chunk-QMGMD6JB.js → chunk-CDT2CX3J.js} +7 -7
- package/dist/{chunk-NFGBBUZ5.js → chunk-GDOEI664.js} +4 -4
- package/dist/{chunk-3PJ3QW6E.js → chunk-GESWDHFD.js} +2 -2
- package/dist/{chunk-3YICA7KW.js → chunk-HGLRQ4N5.js} +4 -4
- package/dist/{chunk-54TOPQFO.js → chunk-HILSAACO.js} +3 -3
- package/dist/{chunk-NNWFXJGL.js → chunk-HRXWESJB.js} +3 -3
- package/dist/{chunk-JE2TRDX7.js → chunk-IK5FLVX4.js} +4 -4
- package/dist/{chunk-VZSMNIRN.js → chunk-J5MWJGDC.js} +2 -2
- package/dist/{chunk-TQERTSKG.js → chunk-KFOYGHUC.js} +2 -2
- package/dist/{chunk-UGJUQEGG.js → chunk-KMEGWPIU.js} +2 -2
- package/dist/{chunk-CSYESWQ2.js → chunk-KT26CDSA.js} +9 -9
- package/dist/{chunk-CZQRMQEI.js → chunk-MH2IGA2C.js} +2 -2
- package/dist/{chunk-6VKXYQ4V.js → chunk-MTKFVOKA.js} +2 -2
- package/dist/{chunk-IIZKJP44.js → chunk-PCGPMJBA.js} +36 -36
- package/dist/{chunk-FYN3HLCV.js → chunk-PSRLUHF2.js} +2 -2
- package/dist/{chunk-Y6MYVL5H.js → chunk-QV7WOPZY.js} +3 -3
- package/dist/{chunk-FLFAVKKO.js → chunk-S7Y4BHTF.js} +2 -2
- package/dist/{chunk-GNF77S63.js → chunk-SHH7CZOP.js} +2 -2
- package/dist/{chunk-SZXIRRHP.js → chunk-TZ6FVGJZ.js} +2 -2
- package/dist/{chunk-E3TCGLNB.js → chunk-VUB6RPPH.js} +2 -2
- package/dist/{chunk-ZOGZ3N2I.js → chunk-X7NUFNVJ.js} +5 -5
- package/dist/{chunk-CZN5JK7D.js → chunk-XFUWBS6A.js} +2 -2
- package/dist/{chunk-WV7KAIVF.js → chunk-YDVOA4I3.js} +5 -5
- package/dist/{chunk-BXP5K5TU.js → chunk-YLBVRBVK.js} +4 -4
- package/dist/{chunk-BCX7SDBW.js → chunk-ZTX7DLWE.js} +6 -6
- package/dist/{cli-circuit-breaker-ZH2WM7XG.js → cli-circuit-breaker-G7JVCCHA.js} +3 -3
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +65 -56
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-TUSPD2LH.js → composite-router-ZBNPUNRE.js} +2 -2
- package/dist/{consensus-vote-PLLP7IJE.js → consensus-vote-GEVSVYV6.js} +17 -17
- package/dist/{consensus-vote-types-ClG_UKij.d.ts → consensus-vote-types-DTUSdB9g.d.ts} +38 -0
- package/dist/{context-retriever-ZCA22Y2N.js → context-retriever-J34XBWSS.js} +8 -8
- package/dist/{doctor-deep-ZXVTSYI7.js → doctor-deep-ITUREQZO.js} +3 -3
- package/dist/{doctor-live-HZKYNHYG.js → doctor-live-UVODP772.js} +10 -10
- package/dist/{expert-bridge-CH5WJXKF.js → expert-bridge-QX2UR2BM.js} +4 -4
- package/dist/{factory-42S5Q2RE.js → factory-EYT7ROYW.js} +5 -5
- package/dist/{factory-S7FJJ7OM.js → factory-WOUE5TFB.js} +9 -9
- package/dist/{improvement-review-NAITF6LS.js → improvement-review-25ML3PFG.js} +6 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.js +32 -32
- package/dist/{init-opencode-HRC7UQEN.js → init-opencode-K7SFAFPP.js} +6 -6
- package/dist/issue-triage-ULMBQTMC.js +17 -0
- package/dist/{pr-reviewer-helpers-UIRMJ6ZL.js → pr-reviewer-helpers-AS7QF6EZ.js} +4 -4
- package/dist/{registry-command-7ONLPRER.js → registry-command-TBKBERPQ.js} +2 -2
- package/dist/{repo-security-plan-U3O7HMYZ.js → repo-security-plan-IL67SCKX.js} +3 -3
- package/dist/{research-helpers-synthesize-LQFCG5WB.js → research-helpers-synthesize-567ZPTCF.js} +4 -4
- package/dist/{routing-memory-75GUJNG6.js → routing-memory-RHDT5HIP.js} +2 -2
- package/dist/{session-memory-ZO5R4OCY.js → session-memory-UPX3KPG6.js} +3 -3
- package/dist/{setup-config-HIXX6M2Q.js → setup-config-HKQKKAIB.js} +3 -3
- package/dist/{setup-custom-api-5HFRWSFY.js → setup-custom-api-OBAFCX4H.js} +4 -4
- package/dist/setup-data-dir-S2YYGJSS.js +31 -0
- package/dist/{tool-memory-LGCIIQNG.js → tool-memory-NFO4G45N.js} +5 -5
- package/dist/{unified-registry-3GX75GJH.js → unified-registry-RQ34NS65.js} +10 -10
- package/dist/{weather-report-CR3M57AH.js → weather-report-5UHJLCEZ.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-YF3YIHPZ.js.map +0 -1
- package/dist/issue-triage-Z7I7DSB3.js +0 -17
- package/dist/setup-data-dir-AHUNLSRM.js +0 -31
- /package/dist/{ast-rule-runner-PIEUVYH5.js.map → ast-rule-runner-NIX2R2ER.js.map} +0 -0
- /package/dist/{child-mcp-config-ZXP5YKTJ.js.map → child-mcp-config-LBCDGXVO.js.map} +0 -0
- /package/dist/{chunk-MHXSHTHG.js.map → chunk-3JJHGGTT.js.map} +0 -0
- /package/dist/{chunk-CGEWEJDT.js.map → chunk-5HAKYKCY.js.map} +0 -0
- /package/dist/{chunk-QSSP62D3.js.map → chunk-5RSH7N6W.js.map} +0 -0
- /package/dist/{chunk-HGR5L7C4.js.map → chunk-67AADYKZ.js.map} +0 -0
- /package/dist/{chunk-JF77LAYJ.js.map → chunk-6DYJTPER.js.map} +0 -0
- /package/dist/{chunk-RNWUIQTZ.js.map → chunk-AKC7SODA.js.map} +0 -0
- /package/dist/{chunk-4UEZ2U5Q.js.map → chunk-AQHLUZ44.js.map} +0 -0
- /package/dist/{chunk-PMWQSCYE.js.map → chunk-ARUHRGGB.js.map} +0 -0
- /package/dist/{chunk-QMGMD6JB.js.map → chunk-CDT2CX3J.js.map} +0 -0
- /package/dist/{chunk-NFGBBUZ5.js.map → chunk-GDOEI664.js.map} +0 -0
- /package/dist/{chunk-3PJ3QW6E.js.map → chunk-GESWDHFD.js.map} +0 -0
- /package/dist/{chunk-3YICA7KW.js.map → chunk-HGLRQ4N5.js.map} +0 -0
- /package/dist/{chunk-54TOPQFO.js.map → chunk-HILSAACO.js.map} +0 -0
- /package/dist/{chunk-NNWFXJGL.js.map → chunk-HRXWESJB.js.map} +0 -0
- /package/dist/{chunk-JE2TRDX7.js.map → chunk-IK5FLVX4.js.map} +0 -0
- /package/dist/{chunk-VZSMNIRN.js.map → chunk-J5MWJGDC.js.map} +0 -0
- /package/dist/{chunk-TQERTSKG.js.map → chunk-KFOYGHUC.js.map} +0 -0
- /package/dist/{chunk-UGJUQEGG.js.map → chunk-KMEGWPIU.js.map} +0 -0
- /package/dist/{chunk-CSYESWQ2.js.map → chunk-KT26CDSA.js.map} +0 -0
- /package/dist/{chunk-CZQRMQEI.js.map → chunk-MH2IGA2C.js.map} +0 -0
- /package/dist/{chunk-6VKXYQ4V.js.map → chunk-MTKFVOKA.js.map} +0 -0
- /package/dist/{chunk-IIZKJP44.js.map → chunk-PCGPMJBA.js.map} +0 -0
- /package/dist/{chunk-FYN3HLCV.js.map → chunk-PSRLUHF2.js.map} +0 -0
- /package/dist/{chunk-Y6MYVL5H.js.map → chunk-QV7WOPZY.js.map} +0 -0
- /package/dist/{chunk-FLFAVKKO.js.map → chunk-S7Y4BHTF.js.map} +0 -0
- /package/dist/{chunk-GNF77S63.js.map → chunk-SHH7CZOP.js.map} +0 -0
- /package/dist/{chunk-SZXIRRHP.js.map → chunk-TZ6FVGJZ.js.map} +0 -0
- /package/dist/{chunk-E3TCGLNB.js.map → chunk-VUB6RPPH.js.map} +0 -0
- /package/dist/{chunk-ZOGZ3N2I.js.map → chunk-X7NUFNVJ.js.map} +0 -0
- /package/dist/{chunk-CZN5JK7D.js.map → chunk-XFUWBS6A.js.map} +0 -0
- /package/dist/{chunk-WV7KAIVF.js.map → chunk-YDVOA4I3.js.map} +0 -0
- /package/dist/{chunk-BXP5K5TU.js.map → chunk-YLBVRBVK.js.map} +0 -0
- /package/dist/{chunk-BCX7SDBW.js.map → chunk-ZTX7DLWE.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-ZH2WM7XG.js.map → cli-circuit-breaker-G7JVCCHA.js.map} +0 -0
- /package/dist/{composite-router-TUSPD2LH.js.map → composite-router-ZBNPUNRE.js.map} +0 -0
- /package/dist/{consensus-vote-PLLP7IJE.js.map → consensus-vote-GEVSVYV6.js.map} +0 -0
- /package/dist/{context-retriever-ZCA22Y2N.js.map → context-retriever-J34XBWSS.js.map} +0 -0
- /package/dist/{doctor-deep-ZXVTSYI7.js.map → doctor-deep-ITUREQZO.js.map} +0 -0
- /package/dist/{doctor-live-HZKYNHYG.js.map → doctor-live-UVODP772.js.map} +0 -0
- /package/dist/{expert-bridge-CH5WJXKF.js.map → expert-bridge-QX2UR2BM.js.map} +0 -0
- /package/dist/{factory-42S5Q2RE.js.map → factory-EYT7ROYW.js.map} +0 -0
- /package/dist/{factory-S7FJJ7OM.js.map → factory-WOUE5TFB.js.map} +0 -0
- /package/dist/{improvement-review-NAITF6LS.js.map → improvement-review-25ML3PFG.js.map} +0 -0
- /package/dist/{init-opencode-HRC7UQEN.js.map → init-opencode-K7SFAFPP.js.map} +0 -0
- /package/dist/{issue-triage-Z7I7DSB3.js.map → issue-triage-ULMBQTMC.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-UIRMJ6ZL.js.map → pr-reviewer-helpers-AS7QF6EZ.js.map} +0 -0
- /package/dist/{registry-command-7ONLPRER.js.map → registry-command-TBKBERPQ.js.map} +0 -0
- /package/dist/{repo-security-plan-U3O7HMYZ.js.map → repo-security-plan-IL67SCKX.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-LQFCG5WB.js.map → research-helpers-synthesize-567ZPTCF.js.map} +0 -0
- /package/dist/{routing-memory-75GUJNG6.js.map → routing-memory-RHDT5HIP.js.map} +0 -0
- /package/dist/{session-memory-ZO5R4OCY.js.map → session-memory-UPX3KPG6.js.map} +0 -0
- /package/dist/{setup-config-HIXX6M2Q.js.map → setup-config-HKQKKAIB.js.map} +0 -0
- /package/dist/{setup-custom-api-5HFRWSFY.js.map → setup-custom-api-OBAFCX4H.js.map} +0 -0
- /package/dist/{setup-data-dir-AHUNLSRM.js.map → setup-data-dir-S2YYGJSS.js.map} +0 -0
- /package/dist/{tool-memory-LGCIIQNG.js.map → tool-memory-NFO4G45N.js.map} +0 -0
- /package/dist/{unified-registry-3GX75GJH.js.map → unified-registry-RQ34NS65.js.map} +0 -0
- /package/dist/{weather-report-CR3M57AH.js.map → weather-report-5UHJLCEZ.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computeCostDetail,
|
|
3
3
|
priceBasisOf
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5RSH7N6W.js";
|
|
5
5
|
import {
|
|
6
6
|
allOf
|
|
7
7
|
} from "./chunk-OQB3XC5O.js";
|
|
@@ -25,20 +25,20 @@ import {
|
|
|
25
25
|
toolSuccessStructured,
|
|
26
26
|
withProgressHeartbeat,
|
|
27
27
|
wrapToolWithTimeout
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-IK5FLVX4.js";
|
|
29
29
|
import {
|
|
30
30
|
VERSION
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-XFUWBS6A.js";
|
|
32
32
|
import {
|
|
33
33
|
UNRESOLVED_MODEL_ID,
|
|
34
34
|
assessPanelIndependence,
|
|
35
35
|
countDistinctModels,
|
|
36
36
|
createEvent,
|
|
37
37
|
getGlobalRegistry
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-YLBVRBVK.js";
|
|
39
39
|
import {
|
|
40
40
|
getToolMemory
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-HGLRQ4N5.js";
|
|
42
42
|
import {
|
|
43
43
|
authRemediation,
|
|
44
44
|
classifyExtractedError,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
isTimeoutText,
|
|
48
48
|
sleep,
|
|
49
49
|
withTimeout
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-4FFTWLHX.js";
|
|
51
51
|
import {
|
|
52
52
|
AgentError,
|
|
53
53
|
CLI_NAMES,
|
|
@@ -77,7 +77,7 @@ import {
|
|
|
77
77
|
registerPersistentOutcomeStoreFactory,
|
|
78
78
|
resolveClassGuardMs,
|
|
79
79
|
resolveVoteTimeout
|
|
80
|
-
} from "./chunk-
|
|
80
|
+
} from "./chunk-6DYJTPER.js";
|
|
81
81
|
import {
|
|
82
82
|
ensureLearningDir,
|
|
83
83
|
getOutcomesFile
|
|
@@ -280,6 +280,463 @@ function reportPanelModelIndependence(modelIds, roleCount, phase, logger11) {
|
|
|
280
280
|
);
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
+
// src/audit/vote-record.ts
|
|
284
|
+
import * as crypto from "node:crypto";
|
|
285
|
+
import { z as z2 } from "zod";
|
|
286
|
+
var VoteRecordDecisionSchema = z2.enum(["approved", "rejected", "no_quorum"]);
|
|
287
|
+
var VoteRecordOptionCoverageSchema = z2.object({
|
|
288
|
+
/** Every approving voter, selecting or not — the tally's denominator. */
|
|
289
|
+
approverCount: z2.number().int().nonnegative(),
|
|
290
|
+
/** Approvers whose selection matched a declared option. */
|
|
291
|
+
selectedCount: z2.number().int().nonnegative(),
|
|
292
|
+
/** Approvers with no usable selection; their choice is unmeasured. */
|
|
293
|
+
unattributedApprovals: z2.number().int().nonnegative()
|
|
294
|
+
}).strict();
|
|
295
|
+
var VoteRecordPanelCoverageSchema = z2.object({
|
|
296
|
+
/** Voters the panel asked for. */
|
|
297
|
+
requested: z2.number().int().nonnegative(),
|
|
298
|
+
/** Voters that returned a usable vote — the denominator of `voteCounts`. */
|
|
299
|
+
responded: z2.number().int().nonnegative(),
|
|
300
|
+
/** Voters that errored or timed out. */
|
|
301
|
+
errored: z2.number().int().nonnegative(),
|
|
302
|
+
/** The roles behind `errored`, in panel order. */
|
|
303
|
+
erroredRoles: z2.array(z2.string().min(1).max(100))
|
|
304
|
+
}).strict();
|
|
305
|
+
var MAX_VOTER_REASONING_CHARS = 2e4;
|
|
306
|
+
function clipForRecord(text) {
|
|
307
|
+
if (text.length <= MAX_VOTER_REASONING_CHARS) return { text };
|
|
308
|
+
return { text: text.slice(0, MAX_VOTER_REASONING_CHARS), truncated: true };
|
|
309
|
+
}
|
|
310
|
+
var RetriedFromRecordSchema = z2.object({
|
|
311
|
+
/** The first pass's `source`: errored, or answered without reading. */
|
|
312
|
+
source: z2.enum(["error", "unverifiable"]),
|
|
313
|
+
/** The first pass's `error` string, when it had one; already clipped. */
|
|
314
|
+
error: z2.string().max(MAX_VOTER_REASONING_CHARS).optional(),
|
|
315
|
+
/** True when `error` was clipped to {@link MAX_VOTER_REASONING_CHARS}. */
|
|
316
|
+
errorTruncated: z2.literal(true).optional()
|
|
317
|
+
}).strict();
|
|
318
|
+
var SeatFallbackRecordSchema = z2.object({
|
|
319
|
+
/** The CLI the seat was assigned to, bare (`claude`, not `cli-claude`). */
|
|
320
|
+
fromCli: z2.string().min(1).max(100),
|
|
321
|
+
/** The model the assigned adapter had detected, when it had one. */
|
|
322
|
+
fromModel: z2.string().min(1).max(200).optional(),
|
|
323
|
+
/** The adapter-layer class of the error that moved the seat. */
|
|
324
|
+
reason: z2.enum(["rate-limit", "capacity", "auth", "timeout", "sandbox", "unknown"])
|
|
325
|
+
}).strict();
|
|
326
|
+
var VoterSummarySchema = z2.object({
|
|
327
|
+
role: z2.string().min(1).max(100),
|
|
328
|
+
decision: z2.enum(["approve", "reject", "abstain"]),
|
|
329
|
+
confidence: z2.number().min(0).max(1),
|
|
330
|
+
/**
|
|
331
|
+
* The voter's stated grounds (#5373, schema 1.6).
|
|
332
|
+
*
|
|
333
|
+
* `generateVoteHash` already hashed `{role, decision, reasoning}` and then
|
|
334
|
+
* discarded the text, so the chain attested to a value it did not store and
|
|
335
|
+
* nobody could re-verify the hash without re-obtaining the reasoning. On
|
|
336
|
+
* #5228 a contrarian rejection was clipped mid-sentence in the terminal, the
|
|
337
|
+
* grounds were unrecoverable, and the same defect resurfaced a round later —
|
|
338
|
+
* one round of a 7-voter panel is 7-13 minutes of model time, and the
|
|
339
|
+
* objection was right both times.
|
|
340
|
+
*
|
|
341
|
+
* Stored whole rather than sampled. Warn-mode near-misses are emitted per
|
|
342
|
+
* TOOL CALL, thousands a day; votes are emitted per PANEL, dozens a day at
|
|
343
|
+
* most, so ~17 KB per vote is not the same growth problem.
|
|
344
|
+
*
|
|
345
|
+
* Absence is not an empty argument: an errored voter has no entry in
|
|
346
|
+
* `voters` at all (see `panelCoverage`), so `reasoning: ''` means a live
|
|
347
|
+
* voter returned nothing, which is itself a signal.
|
|
348
|
+
*/
|
|
349
|
+
reasoning: z2.string().max(MAX_VOTER_REASONING_CHARS).optional(),
|
|
350
|
+
/** True when `reasoning` was clipped to {@link MAX_VOTER_REASONING_CHARS}. */
|
|
351
|
+
reasoningTruncated: z2.literal(true).optional(),
|
|
352
|
+
/**
|
|
353
|
+
* True when this seat was recovered by the per-role retry (#6050, schema 1.7).
|
|
354
|
+
*
|
|
355
|
+
* `voter-retry.ts` has set `retried: true` on recovered results since it was
|
|
356
|
+
* written, and `vote-types.ts` states the reason: the flag is "what makes the
|
|
357
|
+
* recovery visible instead of indistinguishable from a clean first attempt".
|
|
358
|
+
* It had one producer and ZERO consumers — both summarizers and the record
|
|
359
|
+
* dropped it — so the field existed, was documented, and never reached
|
|
360
|
+
* anything that could act on it.
|
|
361
|
+
*
|
|
362
|
+
* A retried seat is weaker evidence than a first-pass one: the model was
|
|
363
|
+
* unavailable or timed out, and the recovery ran under different conditions.
|
|
364
|
+
* For a ratification vote on a governor-path change, "7 of 7 answered" and
|
|
365
|
+
* "6 answered, 1 recovered on retry" are different facts about the scrutiny
|
|
366
|
+
* the change received, and the record stated the first for both.
|
|
367
|
+
*
|
|
368
|
+
* `literal(true)` and optional, on the `reasoningTruncated` rule: a clean
|
|
369
|
+
* seat carries no key, so its entry re-hashes byte-identical and every
|
|
370
|
+
* historical record still verifies.
|
|
371
|
+
*/
|
|
372
|
+
retried: z2.literal(true).optional(),
|
|
373
|
+
/**
|
|
374
|
+
* Registry model id the seat ran on (#6091, schema 1.8).
|
|
375
|
+
*
|
|
376
|
+
* The seat→model mapping is round-robin over the available CLIs plus
|
|
377
|
+
* `NEXUS_VOTER_MODEL_<ROLE>` pins, so it is not recoverable from the
|
|
378
|
+
* ledger after the fact: 1844 voter entries across 278 records carried no
|
|
379
|
+
* model. "When an agent's output becomes evidence, its provenance travels
|
|
380
|
+
* with it" — a tally that says `scope_steward: approve` without saying
|
|
381
|
+
* which model answered cannot be audited for the #6068 failure class.
|
|
382
|
+
* Present-only, on the `retried` rule; absent when the result carried no
|
|
383
|
+
* model or only the pending-detection placeholder.
|
|
384
|
+
*/
|
|
385
|
+
model: z2.string().min(1).max(200).optional(),
|
|
386
|
+
/**
|
|
387
|
+
* True when the seat could not read the artifact (#6094, schema 1.8).
|
|
388
|
+
*
|
|
389
|
+
* `decision` is `abstain` for such a seat, so without this flag the record
|
|
390
|
+
* could not tell "read it and abstained" from "never saw it" — and one
|
|
391
|
+
* ledger entry (`vote-1789058788915-6lfrbuq`) shows a seat that APPROVED
|
|
392
|
+
* on the proposal text after failing to read. `literal(true)` and
|
|
393
|
+
* present-only, so every pre-1.8 entry re-hashes byte-identical.
|
|
394
|
+
*/
|
|
395
|
+
unverifiable: z2.literal(true).optional(),
|
|
396
|
+
/**
|
|
397
|
+
* The CLI the round-robin or `NEXUS_VOTER_MODEL_<ROLE>` pin chose for the
|
|
398
|
+
* seat, as a bare name (#6115, schema 1.9). `model` says where a seat
|
|
399
|
+
* answered; this says where it was MEANT to. Three consecutive 7-seat
|
|
400
|
+
* ratification panels on 2026-09-13 answered every seat on one gemini
|
|
401
|
+
* model while the assignment was three claude, two codex, two gemini,
|
|
402
|
+
* and the 1.8 record showed seven identical `model` values with nothing
|
|
403
|
+
* that said five of them were substitutes. Present-only, on the `model`
|
|
404
|
+
* rule; absent on a result built outside the panel launcher.
|
|
405
|
+
*/
|
|
406
|
+
assignedCli: z2.string().min(1).max(100).optional(),
|
|
407
|
+
/**
|
|
408
|
+
* Present only when the seat answered on a different CLI or model than
|
|
409
|
+
* assigned (#6115, schema 1.9): the exact `SeatFallback` shape the live
|
|
410
|
+
* result carries, rebuilt field-by-field. `fromCli` is the assigned CLI,
|
|
411
|
+
* `fromModel` the model it had detected (absent when it never did — the
|
|
412
|
+
* pending-detection placeholder is not a model), `reason` the adapter
|
|
413
|
+
* layer's error class. The vocabulary is compile-checked against the live
|
|
414
|
+
* `FallbackReason` in vote-record.test.ts; a class one side learns alone
|
|
415
|
+
* would either refuse every record that carries it (#6054) or accept one
|
|
416
|
+
* no producer can write.
|
|
417
|
+
*/
|
|
418
|
+
fallback: SeatFallbackRecordSchema.optional(),
|
|
419
|
+
/**
|
|
420
|
+
* Present only when the per-role retry REPLACED this seat (#6246, schema
|
|
421
|
+
* 1.12): the first pass's source and, when it had one, its clipped error
|
|
422
|
+
* string. `retried` (1.7) says a recovery happened; this says what it
|
|
423
|
+
* recovered from. On the #6241 panel a seat recorded `retried: true,
|
|
424
|
+
* unverifiable: true` after a first pass that errored on two response-parse
|
|
425
|
+
* failures, and nothing in the record joined the two — a reader of the
|
|
426
|
+
* ledger and the log together concluded the parse errors had been
|
|
427
|
+
* misclassified (#6244). Rebuilt field-by-field on the `fallback` rule; the
|
|
428
|
+
* `source` vocabulary is compile-checked against the live `RetriedFrom`.
|
|
429
|
+
*/
|
|
430
|
+
retriedFrom: RetriedFromRecordSchema.optional()
|
|
431
|
+
}).strict();
|
|
432
|
+
function defineVoterKeys(keys) {
|
|
433
|
+
return keys;
|
|
434
|
+
}
|
|
435
|
+
var VOTER_SUMMARY_KEYS = defineVoterKeys([
|
|
436
|
+
"role",
|
|
437
|
+
"decision",
|
|
438
|
+
"confidence",
|
|
439
|
+
"reasoning",
|
|
440
|
+
"reasoningTruncated",
|
|
441
|
+
"retried",
|
|
442
|
+
// 1.8 (#6091, #6094): appended after `retried`, present-only, so a 1.7
|
|
443
|
+
// entry projects byte-identically.
|
|
444
|
+
"model",
|
|
445
|
+
"unverifiable",
|
|
446
|
+
// 1.9 (#6115): appended after `unverifiable`, present-only, so a 1.8 entry
|
|
447
|
+
// projects byte-identically. `fallback` is the first nested voter field;
|
|
448
|
+
// `projectSeatFallback` rebuilds it in its own canonical order.
|
|
449
|
+
"assignedCli",
|
|
450
|
+
"fallback",
|
|
451
|
+
// 1.12 (#6246): appended after `fallback`, present-only, so a 1.11 entry
|
|
452
|
+
// projects byte-identically. Nested; `projectRetriedFrom` rebuilds it in
|
|
453
|
+
// its own canonical order.
|
|
454
|
+
"retriedFrom"
|
|
455
|
+
]);
|
|
456
|
+
function noUnprojectedKeys(rest) {
|
|
457
|
+
return rest;
|
|
458
|
+
}
|
|
459
|
+
function projectSeatFallback(f) {
|
|
460
|
+
const { fromCli, fromModel, reason, ...rest } = f;
|
|
461
|
+
noUnprojectedKeys(rest);
|
|
462
|
+
return {
|
|
463
|
+
fromCli,
|
|
464
|
+
...fromModel !== void 0 ? { fromModel } : {},
|
|
465
|
+
reason
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
function projectRetriedFrom(r) {
|
|
469
|
+
const { source, error, errorTruncated, ...rest } = r;
|
|
470
|
+
noUnprojectedKeys(rest);
|
|
471
|
+
return {
|
|
472
|
+
source,
|
|
473
|
+
...error !== void 0 ? { error } : {},
|
|
474
|
+
...errorTruncated !== void 0 ? { errorTruncated } : {}
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
function projectVoterField(v, key) {
|
|
478
|
+
if (key === "fallback") {
|
|
479
|
+
return v.fallback === void 0 ? void 0 : projectSeatFallback(v.fallback);
|
|
480
|
+
}
|
|
481
|
+
if (key === "retriedFrom") {
|
|
482
|
+
return v.retriedFrom === void 0 ? void 0 : projectRetriedFrom(v.retriedFrom);
|
|
483
|
+
}
|
|
484
|
+
return v[key];
|
|
485
|
+
}
|
|
486
|
+
function projectVoterSummary(v) {
|
|
487
|
+
const out = {};
|
|
488
|
+
for (const key of VOTER_SUMMARY_KEYS) {
|
|
489
|
+
const value = projectVoterField(v, key);
|
|
490
|
+
if (value !== void 0) out[key] = value;
|
|
491
|
+
}
|
|
492
|
+
return out;
|
|
493
|
+
}
|
|
494
|
+
var VoteRecordCountsSchema = z2.object({
|
|
495
|
+
approve: z2.number().int().nonnegative(),
|
|
496
|
+
reject: z2.number().int().nonnegative(),
|
|
497
|
+
abstain: z2.number().int().nonnegative(),
|
|
498
|
+
total: z2.number().int().nonnegative()
|
|
499
|
+
}).strict();
|
|
500
|
+
var VoteRecordOptionCountSchema = z2.object({
|
|
501
|
+
/** The option label as declared in the proposal (e.g. 'A'). */
|
|
502
|
+
option: z2.string().min(1),
|
|
503
|
+
/** How many voters selected it. */
|
|
504
|
+
count: z2.number().int().nonnegative()
|
|
505
|
+
}).strict();
|
|
506
|
+
var GIT_SHA_PATTERN = /^[0-9a-f]{40}$/;
|
|
507
|
+
var VoteRecordPrBindingSchema = z2.object({
|
|
508
|
+
pr: z2.number().int().positive(),
|
|
509
|
+
headSha: z2.string().regex(GIT_SHA_PATTERN, "expected a full 40-hex lowercase commit sha")
|
|
510
|
+
}).strict();
|
|
511
|
+
function projectPrBinding(b) {
|
|
512
|
+
return { pr: b.pr, headSha: b.headSha };
|
|
513
|
+
}
|
|
514
|
+
var VoteRecordErrorPolicySchema = z2.enum([
|
|
515
|
+
"reduce_denominator",
|
|
516
|
+
"count_as_abstain",
|
|
517
|
+
"fail_closed",
|
|
518
|
+
"absolute_quorum"
|
|
519
|
+
]);
|
|
520
|
+
var VoteRecordSchema = z2.object({
|
|
521
|
+
/**
|
|
522
|
+
* Schema version. '1.1' marked the chain→record-set+sequence model (#3927);
|
|
523
|
+
* '1.2' adds the optional `ratifies` subject-binding field (#3927 item 1);
|
|
524
|
+
* '1.10' adds the optional `ratifiesPr` PR-binding (#5130); '1.11' the
|
|
525
|
+
* optional `errorPolicy` (#6211); '1.12' the per-voter `retriedFrom`
|
|
526
|
+
* (#6246). Every tier is accepted — a 1.1 record
|
|
527
|
+
* (no `ratifies`) verifies unchanged because each optional is folded into
|
|
528
|
+
* the self-hash ONLY when present (see {@link computeVoteRecordHash}).
|
|
529
|
+
* Tiers are labels, not ordered numbers: '1.10' follows '1.9' by
|
|
530
|
+
* convention only and nothing compares them.
|
|
531
|
+
*/
|
|
532
|
+
version: z2.enum([
|
|
533
|
+
"1.1",
|
|
534
|
+
"1.2",
|
|
535
|
+
"1.3",
|
|
536
|
+
"1.4",
|
|
537
|
+
"1.5",
|
|
538
|
+
"1.6",
|
|
539
|
+
"1.7",
|
|
540
|
+
"1.8",
|
|
541
|
+
"1.9",
|
|
542
|
+
"1.10",
|
|
543
|
+
"1.11",
|
|
544
|
+
"1.12"
|
|
545
|
+
]),
|
|
546
|
+
/** Unique record id (also usable as a `ratificationVoteRef`). */
|
|
547
|
+
id: z2.string().min(1),
|
|
548
|
+
/**
|
|
549
|
+
* Monotonic sequence number (integer ≥ 0). Assigned as (max existing
|
|
550
|
+
* sequence)+1 at write time. Sorted, the set of sequences must cover
|
|
551
|
+
* 0..maxSeq with no gap (omission detection); DUPLICATE sequences are a
|
|
552
|
+
* benign concurrent-fork signal, not tampering.
|
|
553
|
+
*/
|
|
554
|
+
sequence: z2.number().int().nonnegative(),
|
|
555
|
+
/** ISO-8601 timestamp the vote was recorded. */
|
|
556
|
+
recordedAt: z2.string().min(1),
|
|
557
|
+
/**
|
|
558
|
+
* SHA-256 of the FULL proposal text. The proposal itself is truncated for
|
|
559
|
+
* the human record (`proposal`), but the hash binds the record to the exact
|
|
560
|
+
* proposal voted on — a later edit of `proposal` that changes meaning is
|
|
561
|
+
* detectable by recomputing this hash from the original.
|
|
562
|
+
*/
|
|
563
|
+
proposalHash: z2.string().length(64),
|
|
564
|
+
/** Truncated proposal text for the human/reviewer record. */
|
|
565
|
+
proposal: z2.string(),
|
|
566
|
+
/** The voting strategy used. */
|
|
567
|
+
strategy: z2.enum([
|
|
568
|
+
"simple_majority",
|
|
569
|
+
"supermajority",
|
|
570
|
+
"unanimous",
|
|
571
|
+
"higher_order",
|
|
572
|
+
"opinion_wise",
|
|
573
|
+
"proof_of_learning"
|
|
574
|
+
]),
|
|
575
|
+
/** The resolved decision. */
|
|
576
|
+
decision: VoteRecordDecisionSchema,
|
|
577
|
+
/** Approval fraction as a percentage (0-100). */
|
|
578
|
+
approvalPercentage: z2.number().min(0).max(100),
|
|
579
|
+
/** Vote-count breakdown. */
|
|
580
|
+
voteCounts: VoteRecordCountsSchema,
|
|
581
|
+
/** Per-voter {role, decision, confidence} summary. */
|
|
582
|
+
voters: z2.array(VoterSummarySchema),
|
|
583
|
+
/** Optional correlation/decision id linking to the cost rollup / trace. */
|
|
584
|
+
correlationId: z2.string().min(1).optional(),
|
|
585
|
+
/**
|
|
586
|
+
* Per-option distribution for a multi-option proposal (#4452, schema 1.3).
|
|
587
|
+
*
|
|
588
|
+
* Present only when the vote declared `options`. Absent on an ordinary
|
|
589
|
+
* yes/no vote, and absent on every 1.1/1.2 record — which is why it is
|
|
590
|
+
* folded into the self-hash ONLY when present (see
|
|
591
|
+
* {@link computeVoteRecordHash}), exactly as `ratifies` was.
|
|
592
|
+
*
|
|
593
|
+
* Without this, a 6-1 or 5-2 option split is recorded as `approve: 7` and
|
|
594
|
+
* reads as unanimous. Threshold semantics invert too: `unanimous` becomes
|
|
595
|
+
* the EASIEST bar to clear, because every engaged voter approves while
|
|
596
|
+
* choosing different things.
|
|
597
|
+
*/
|
|
598
|
+
// No `.min(1)` (#6049). The rule this field's own docstring states is
|
|
599
|
+
// "present only when the vote declared `options`" -- keyed on DECLARATION,
|
|
600
|
+
// not on whether anyone picked one. `.min(1)` encoded the older, narrower
|
|
601
|
+
// rule, so once the builder started emitting `[]` for "declared, nothing
|
|
602
|
+
// attributable" the record appended fine and then failed to parse on read:
|
|
603
|
+
// `too_small, minimum 1`. The write path does not validate, so the line
|
|
604
|
+
// landed in the ledger and `parseVoteRecordsText` silently dropped it --
|
|
605
|
+
// the case most worth auditing became the one no reader could see.
|
|
606
|
+
//
|
|
607
|
+
// Relaxing is a pure widening: no previously-valid record changes meaning
|
|
608
|
+
// or hash, and no persisted record can currently hold an empty tally.
|
|
609
|
+
optionTally: z2.array(VoteRecordOptionCountSchema).optional(),
|
|
610
|
+
/**
|
|
611
|
+
* Selection coverage for a multi-option vote (#4472, schema 1.4).
|
|
612
|
+
*
|
|
613
|
+
* `optionTally` alone cannot distinguish dissent from absence: `4 pick X
|
|
614
|
+
* + 3 unreadable` and a genuine 4/3 split both leave a leading share of
|
|
615
|
+
* 57%. Recording how many approvers produced no usable selection is what
|
|
616
|
+
* makes a partial measurement legible AS partial — the condition every
|
|
617
|
+
* voter attached to adopting the "credit no option" rule.
|
|
618
|
+
*/
|
|
619
|
+
optionCoverage: VoteRecordOptionCoverageSchema.optional(),
|
|
620
|
+
/**
|
|
621
|
+
* Panel coverage (#5738, schema 1.5). Present only when at least one
|
|
622
|
+
* requested voter failed to return a vote; absent keeps a clean panel on
|
|
623
|
+
* the pre-1.5 projection, so every historical record still verifies.
|
|
624
|
+
*/
|
|
625
|
+
panelCoverage: VoteRecordPanelCoverageSchema.optional(),
|
|
626
|
+
/**
|
|
627
|
+
* The loop/strategy subject this vote RATIFIES (#3927 item 1). Present only on
|
|
628
|
+
* a ratification vote; set at vote time and bound into the self-hash (so it is
|
|
629
|
+
* tamper-evident). The authority-tier promotion gate
|
|
630
|
+
* (`scripts/check-authority-tier-drift.ts`) resolves a transition's
|
|
631
|
+
* `ratificationVoteRef` to a record and requires `ratifies === transition.subject`
|
|
632
|
+
* (with `decision === 'approved'` and `strategy === 'higher_order'`). Absent on
|
|
633
|
+
* an ordinary (non-ratification) vote; a 1.1 record never carries it.
|
|
634
|
+
*/
|
|
635
|
+
ratifies: z2.string().min(1).optional(),
|
|
636
|
+
/**
|
|
637
|
+
* The PR this vote RATIFIES, bound to the head the panel saw (#5130 step 1,
|
|
638
|
+
* schema 1.10; panel decision Q1 option A, 5 of 6). Present only on a
|
|
639
|
+
* governor-path ratification vote; hash-covered like `ratifies`, so a
|
|
640
|
+
* record cannot be repointed at a different PR or a later push without
|
|
641
|
+
* breaking its hash. The governor gate (step 2, #5779/#5131) resolves the
|
|
642
|
+
* record from the committed ledger and requires `pr` to be the PR under
|
|
643
|
+
* review and `headSha` to be its head (or `head^` when `head` touches only
|
|
644
|
+
* the ledger — the caller-commits tip). Absent on every pre-1.10 record.
|
|
645
|
+
*
|
|
646
|
+
* A SEPARATE key rather than a structured encoding of `ratifies`: that
|
|
647
|
+
* field is the authority-ladder SUBJECT, compared by string equality to
|
|
648
|
+
* `transition.subject` and grouped by `conflictingRatifiedSubjects`; no
|
|
649
|
+
* resolver parses it. Overloading it would give one field two consumers
|
|
650
|
+
* with two equality rules. The two may coexist on one record.
|
|
651
|
+
*/
|
|
652
|
+
ratifiesPr: VoteRecordPrBindingSchema.optional(),
|
|
653
|
+
/**
|
|
654
|
+
* The error policy the panel actually ran under (#6211, schema 1.11): the
|
|
655
|
+
* EFFECTIVE policy after `consensus_vote` applied the per-strategy default
|
|
656
|
+
* (`input.errorPolicy ?? getDefaultErrorPolicy(strategy)`), not the raw
|
|
657
|
+
* input the caller may have omitted. Hash-covered, present-only.
|
|
658
|
+
*
|
|
659
|
+
* Before this tier the policy reached the RESPONSE only, so the governor
|
|
660
|
+
* ledger gate (`scripts/governor-ledger-evidence.ts`) could not say which
|
|
661
|
+
* policy a whole-panel ratification was configured with: under
|
|
662
|
+
* `absolute_quorum` an errored seat voids the vote, so the one
|
|
663
|
+
* ledger-observable trace of a different policy was an approved record
|
|
664
|
+
* with `panelCoverage.errored > 0` — and a whole panel under
|
|
665
|
+
* `reduce_denominator` looked exactly like one under `absolute_quorum`.
|
|
666
|
+
* The gate's `wrong-error-policy` verdict reads this field; a record
|
|
667
|
+
* without it (every pre-1.11 record) keeps the panel-coverage inference
|
|
668
|
+
* and is reported as `errorPolicy: unrecorded`.
|
|
669
|
+
*/
|
|
670
|
+
errorPolicy: VoteRecordErrorPolicySchema.optional(),
|
|
671
|
+
/**
|
|
672
|
+
* ADVISORY hash of the tip record at write time (absent for the first).
|
|
673
|
+
* Retained for audit texture but NOT covered by `hash` and NOT verified —
|
|
674
|
+
* the record-set model is position-independent (#3927).
|
|
675
|
+
*/
|
|
676
|
+
previousHash: z2.string().length(64).optional(),
|
|
677
|
+
/** SHA-256 over every field above EXCEPT `previousHash` (and except `hash`). */
|
|
678
|
+
hash: z2.string().length(64)
|
|
679
|
+
}).strict();
|
|
680
|
+
function foldOptionalFields(base, payload) {
|
|
681
|
+
const withTally = payload.optionTally !== void 0 ? {
|
|
682
|
+
...base,
|
|
683
|
+
optionTally: payload.optionTally.map((o) => ({ option: o.option, count: o.count }))
|
|
684
|
+
} : base;
|
|
685
|
+
const withCoverage = payload.optionCoverage !== void 0 ? {
|
|
686
|
+
...withTally,
|
|
687
|
+
optionCoverage: {
|
|
688
|
+
approverCount: payload.optionCoverage.approverCount,
|
|
689
|
+
selectedCount: payload.optionCoverage.selectedCount,
|
|
690
|
+
unattributedApprovals: payload.optionCoverage.unattributedApprovals
|
|
691
|
+
}
|
|
692
|
+
} : withTally;
|
|
693
|
+
const withPanel = payload.panelCoverage !== void 0 ? {
|
|
694
|
+
...withCoverage,
|
|
695
|
+
panelCoverage: {
|
|
696
|
+
requested: payload.panelCoverage.requested,
|
|
697
|
+
responded: payload.panelCoverage.responded,
|
|
698
|
+
errored: payload.panelCoverage.errored,
|
|
699
|
+
erroredRoles: [...payload.panelCoverage.erroredRoles]
|
|
700
|
+
}
|
|
701
|
+
} : withCoverage;
|
|
702
|
+
const withRatifies = payload.ratifies !== void 0 ? { ...withPanel, ratifies: payload.ratifies } : withPanel;
|
|
703
|
+
const withPrBinding = payload.ratifiesPr !== void 0 ? { ...withRatifies, ratifiesPr: projectPrBinding(payload.ratifiesPr) } : withRatifies;
|
|
704
|
+
return payload.errorPolicy !== void 0 ? { ...withPrBinding, errorPolicy: payload.errorPolicy } : withPrBinding;
|
|
705
|
+
}
|
|
706
|
+
function computeVoteRecordHash(payload) {
|
|
707
|
+
const base = {
|
|
708
|
+
version: payload.version,
|
|
709
|
+
id: payload.id,
|
|
710
|
+
sequence: payload.sequence,
|
|
711
|
+
recordedAt: payload.recordedAt,
|
|
712
|
+
proposalHash: payload.proposalHash,
|
|
713
|
+
proposal: payload.proposal,
|
|
714
|
+
strategy: payload.strategy,
|
|
715
|
+
decision: payload.decision,
|
|
716
|
+
approvalPercentage: payload.approvalPercentage,
|
|
717
|
+
// Rebuild voteCounts in schema order (approve, reject, abstain, total) so the
|
|
718
|
+
// hash does not depend on how the nested object's keys were ordered (#3962).
|
|
719
|
+
voteCounts: {
|
|
720
|
+
approve: payload.voteCounts.approve,
|
|
721
|
+
reject: payload.voteCounts.reject,
|
|
722
|
+
abstain: payload.voteCounts.abstain,
|
|
723
|
+
total: payload.voteCounts.total
|
|
724
|
+
},
|
|
725
|
+
// `reasoning` / `reasoningTruncated` (#5373, schema 1.6) are appended per
|
|
726
|
+
// entry ONLY when present, on the same rule as the record-level optional
|
|
727
|
+
// fields: a pre-1.6 voter entry re-hashes byte-identical, so every
|
|
728
|
+
// historical record still verifies, while editing or removing a stored
|
|
729
|
+
// reasoning flips the hash.
|
|
730
|
+
voters: payload.voters.map(projectVoterSummary),
|
|
731
|
+
correlationId: payload.correlationId ?? null
|
|
732
|
+
};
|
|
733
|
+
const canonical = JSON.stringify(foldOptionalFields(base, payload));
|
|
734
|
+
return crypto.createHash("sha256").update(canonical).digest("hex");
|
|
735
|
+
}
|
|
736
|
+
function hashProposal(proposal) {
|
|
737
|
+
return crypto.createHash("sha256").update(proposal).digest("hex");
|
|
738
|
+
}
|
|
739
|
+
|
|
283
740
|
// src/cli/voter-unverifiable.ts
|
|
284
741
|
var UNVERIFIABLE_STDERR_RE = /\bbwrap: |RTM_NEWADDR|\bsandbox\b[^\n]*\b(?:denied|failed|not permitted)\b/i;
|
|
285
742
|
var UNVERIFIABLE_REASONING_RE = /\bbwrap: |RTM_NEWADDR|\b(?:repository|source|shell) (?:reads?|access|execution|inspection) failed\b|\bcould not (?:read|inspect) the artifact\b/i;
|
|
@@ -317,6 +774,13 @@ function isAbsentSeat(v) {
|
|
|
317
774
|
}
|
|
318
775
|
|
|
319
776
|
// src/cli/voter-retry.ts
|
|
777
|
+
var CONTROL_CHARS_RE = /[\x00-\x1f\x7f-\x9f]/g;
|
|
778
|
+
function retriedFromOf(first) {
|
|
779
|
+
const source = first.source === "unverifiable" ? "unverifiable" : "error";
|
|
780
|
+
if (first.error === void 0) return { source };
|
|
781
|
+
const { text, truncated } = clipForRecord(first.error.replace(CONTROL_CHARS_RE, " "));
|
|
782
|
+
return { source, error: text, ...truncated === true ? { errorTruncated: true } : {} };
|
|
783
|
+
}
|
|
320
784
|
var DEFAULT_ERRORED_ROLE_BACKOFF_MS = 3e3;
|
|
321
785
|
async function retryErroredRoles(first, relaunch, logger11, backoffMs) {
|
|
322
786
|
const erroredRoles = first.filter(isAbsentSeat).map((v) => v.role);
|
|
@@ -328,10 +792,17 @@ async function retryErroredRoles(first, relaunch, logger11, backoffMs) {
|
|
|
328
792
|
});
|
|
329
793
|
if (backoffMs > 0) await sleep(backoffMs);
|
|
330
794
|
const retriedResults = await relaunch(erroredRoles);
|
|
795
|
+
const firstByRole = new Map(first.map((v) => [v.role, v]));
|
|
331
796
|
const recovered = /* @__PURE__ */ new Map();
|
|
332
797
|
for (const r of retriedResults) {
|
|
333
798
|
if (r.source === "error") continue;
|
|
334
|
-
|
|
799
|
+
const prior = firstByRole.get(r.role);
|
|
800
|
+
const from = prior !== void 0 && isAbsentSeat(prior) ? retriedFromOf(prior) : void 0;
|
|
801
|
+
recovered.set(r.role, {
|
|
802
|
+
...r,
|
|
803
|
+
retried: true,
|
|
804
|
+
...from !== void 0 ? { retriedFrom: from } : {}
|
|
805
|
+
});
|
|
335
806
|
}
|
|
336
807
|
if (recovered.size === 0) {
|
|
337
808
|
logger11.warn("Per-role retry recovered no voter \u2014 the panel stays degraded", { erroredRoles });
|
|
@@ -666,7 +1137,7 @@ var SIMULATED_VOTE_REASONING = {
|
|
|
666
1137
|
};
|
|
667
1138
|
|
|
668
1139
|
// src/cli/voter-response.ts
|
|
669
|
-
import { z as
|
|
1140
|
+
import { z as z3 } from "zod";
|
|
670
1141
|
|
|
671
1142
|
// src/consensus/option-tally.ts
|
|
672
1143
|
var SUPERMAJORITY_SHARE = 2 / 3;
|
|
@@ -726,26 +1197,26 @@ var SyntheticVoteError = class extends Error {
|
|
|
726
1197
|
}
|
|
727
1198
|
rawOutput;
|
|
728
1199
|
};
|
|
729
|
-
var RawFindingSchema =
|
|
730
|
-
summary:
|
|
731
|
-
location:
|
|
732
|
-
severity:
|
|
733
|
-
gate:
|
|
734
|
-
reread_cited_line:
|
|
735
|
-
traced_call_path:
|
|
736
|
-
named_assertion:
|
|
737
|
-
ruled_out_language_non_issue:
|
|
1200
|
+
var RawFindingSchema = z3.object({
|
|
1201
|
+
summary: z3.string().min(1).max(500).describe("One-line summary of the issue"),
|
|
1202
|
+
location: z3.string().min(1).max(200).describe("path/file.ext:line"),
|
|
1203
|
+
severity: z3.enum(["critical", "high", "medium", "low"]).default("medium"),
|
|
1204
|
+
gate: z3.object({
|
|
1205
|
+
reread_cited_line: z3.enum(["passed", "failed", "skipped"]).default("skipped"),
|
|
1206
|
+
traced_call_path: z3.enum(["passed", "failed", "skipped"]).default("skipped"),
|
|
1207
|
+
named_assertion: z3.string().default("").describe("Concrete failing assertion \u2014 substantive, not a rubber-stamp word"),
|
|
1208
|
+
ruled_out_language_non_issue: z3.enum(["passed", "failed", "skipped"]).default("skipped")
|
|
738
1209
|
}),
|
|
739
|
-
claim:
|
|
1210
|
+
claim: z3.string().min(1).max(2e3).describe("What is wrong and why it justifies blocking")
|
|
740
1211
|
});
|
|
741
|
-
var VoteResponseSchema =
|
|
742
|
-
decision:
|
|
743
|
-
reasoning:
|
|
744
|
-
confidence:
|
|
745
|
-
conditions:
|
|
1212
|
+
var VoteResponseSchema = z3.object({
|
|
1213
|
+
decision: z3.enum(["approve", "reject", "abstain"]).describe("Your vote decision"),
|
|
1214
|
+
reasoning: z3.string().min(10).max(4e3).describe("Explanation for your vote (10-4000 chars)"),
|
|
1215
|
+
confidence: z3.number().min(0).max(1).describe("Confidence level 0-1"),
|
|
1216
|
+
conditions: z3.array(z3.string()).optional().describe("Optional conditions for approval"),
|
|
746
1217
|
/** Structured rejection categories for reject→refine→re-vote loops (Issue #1213). */
|
|
747
|
-
rejectionCategories:
|
|
748
|
-
|
|
1218
|
+
rejectionCategories: z3.array(
|
|
1219
|
+
z3.enum([
|
|
749
1220
|
"YAGNI",
|
|
750
1221
|
"DRY_VIOLATION",
|
|
751
1222
|
"OVER_ENGINEERING",
|
|
@@ -757,11 +1228,11 @@ var VoteResponseSchema = z2.object({
|
|
|
757
1228
|
).optional().describe("Rejection reason categories when decision is reject"),
|
|
758
1229
|
/** Top-level structured findings for PR-review mode (#2245 v4 follow-up).
|
|
759
1230
|
* Replaces the YAML-in-reasoning encoding that proved lossy. */
|
|
760
|
-
findings:
|
|
1231
|
+
findings: z3.array(RawFindingSchema).optional().describe("Structured findings (PR review only)"),
|
|
761
1232
|
/** Chosen option when the proposal declared `options` (#4472). Validated
|
|
762
1233
|
* against the declared list by the caller; an unmatched value is dropped
|
|
763
1234
|
* rather than recorded, so a parse miss surfaces as absent. */
|
|
764
|
-
selectedOption:
|
|
1235
|
+
selectedOption: z3.string().optional().describe("Which declared option you choose")
|
|
765
1236
|
});
|
|
766
1237
|
var VOTE_JSON_SCHEMA = {
|
|
767
1238
|
type: "object",
|
|
@@ -903,12 +1374,12 @@ Example PR-review request_changes response with structured findings:
|
|
|
903
1374
|
}
|
|
904
1375
|
]
|
|
905
1376
|
}`;
|
|
906
|
-
function buildVotePrompt(proposal, options) {
|
|
1377
|
+
function buildVotePrompt(proposal, options, workspace) {
|
|
907
1378
|
return `Evaluate the following proposal and provide your vote.
|
|
908
1379
|
|
|
909
1380
|
PROPOSAL:
|
|
910
1381
|
${proposal}
|
|
911
|
-
${buildOptionsBlock(options)}
|
|
1382
|
+
${buildOptionsBlock(options)}${buildWorkspaceBlock(workspace)}
|
|
912
1383
|
In addition to your role-specific criteria, assess these workflow-test dimensions:
|
|
913
1384
|
- Testability: Can the proposed changes be verified with automated tests?
|
|
914
1385
|
- Workflow integration: Does this fit into existing CI/make/test workflows?
|
|
@@ -932,6 +1403,14 @@ OPTIONS \u2014 choose exactly ONE of these and name it verbatim in \`selectedOpt
|
|
|
932
1403
|
${list}
|
|
933
1404
|
`;
|
|
934
1405
|
}
|
|
1406
|
+
function buildWorkspaceBlock(workspace) {
|
|
1407
|
+
if (workspace === void 0 || workspace === "") return "";
|
|
1408
|
+
return `
|
|
1409
|
+
REPOSITORY ACCESS:
|
|
1410
|
+
The repository under review is the working directory of this panel: ${workspace}
|
|
1411
|
+
Every seat's file and shell tools run there, and reading it is expected. When the proposal refers to something in that repository \u2014 a PR head, a diff, the files it touches \u2014 read it there before you vote: the proposal text describes the artifact and is not a substitute for it. If your tools cannot read that directory, follow the UNVERIFIABLE rule in your instructions.
|
|
1412
|
+
`;
|
|
1413
|
+
}
|
|
935
1414
|
function buildSelectionFieldDoc(options) {
|
|
936
1415
|
if (options === void 0 || options.length === 0) return "";
|
|
937
1416
|
return "- selectedOption: REQUIRED. Exactly one option from the OPTIONS list above, copied verbatim. Do not invent an option, combine two, or leave it blank \u2014 your selection is what the threshold is measured over.";
|
|
@@ -1155,14 +1634,17 @@ function buildVoteRequest({
|
|
|
1155
1634
|
timeoutMs,
|
|
1156
1635
|
withResponseFormat,
|
|
1157
1636
|
options,
|
|
1158
|
-
project
|
|
1637
|
+
project,
|
|
1638
|
+
workspace
|
|
1159
1639
|
}) {
|
|
1160
1640
|
const base = {
|
|
1161
1641
|
messages: [
|
|
1162
1642
|
// #6110: the seat judges the caller's target project, not this
|
|
1163
1643
|
// repository's. `undefined` renders the `nexus-agents` default.
|
|
1164
1644
|
{ role: "system", content: getVoterPrompts(project)[role] },
|
|
1165
|
-
|
|
1645
|
+
// #6254: and the working directory the seats run in, so a seat with
|
|
1646
|
+
// file tools knows where the artifact is and that reading it is expected.
|
|
1647
|
+
{ role: "user", content: buildVotePrompt(proposal, options, workspace) }
|
|
1166
1648
|
],
|
|
1167
1649
|
// 4000 (#4131): headroom so a findings-bearing verdict (JSON envelope +
|
|
1168
1650
|
// reasoning + structured findings) isn't cut mid-JSON by the token cap and
|
|
@@ -1219,8 +1701,8 @@ async function runVoteCompletion(args) {
|
|
|
1219
1701
|
};
|
|
1220
1702
|
}
|
|
1221
1703
|
async function executeSingleVoteAttempt(role, proposal, adapter, timeoutMs, context = {}) {
|
|
1222
|
-
const { options, project } = context;
|
|
1223
|
-
const completionArgs = { role, proposal, adapter, timeoutMs, options, project };
|
|
1704
|
+
const { options, project, workspace } = context;
|
|
1705
|
+
const completionArgs = { role, proposal, adapter, timeoutMs, options, project, workspace };
|
|
1224
1706
|
let completion = await runVoteCompletion({ ...completionArgs, withResponseFormat: true });
|
|
1225
1707
|
if (!completion.ok && isStructuredOutputUnsupported(completion.error)) {
|
|
1226
1708
|
completion = await runVoteCompletion({ ...completionArgs, withResponseFormat: false });
|
|
@@ -1251,7 +1733,7 @@ function logAbandonedRetries(logger11, role, attempt, maxRetries) {
|
|
|
1251
1733
|
});
|
|
1252
1734
|
}
|
|
1253
1735
|
async function executeWithRetries(opts) {
|
|
1254
|
-
const { role, proposal, adapter, logger: logger11, timeoutMs, maxRetries, options, project } = opts;
|
|
1736
|
+
const { role, proposal, adapter, logger: logger11, timeoutMs, maxRetries, options, project, workspace } = opts;
|
|
1255
1737
|
let lastError = "";
|
|
1256
1738
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1257
1739
|
if (attempt > 0) {
|
|
@@ -1264,7 +1746,8 @@ async function executeWithRetries(opts) {
|
|
|
1264
1746
|
const attemptStart = Date.now();
|
|
1265
1747
|
const result = await executeSingleVoteAttempt(role, proposal, adapter, timeoutMs, {
|
|
1266
1748
|
options,
|
|
1267
|
-
project
|
|
1749
|
+
project,
|
|
1750
|
+
workspace
|
|
1268
1751
|
});
|
|
1269
1752
|
const attemptMs = Date.now() - attemptStart;
|
|
1270
1753
|
if (result.ok) {
|
|
@@ -1457,14 +1940,15 @@ function resolveVoteExecution(options) {
|
|
|
1457
1940
|
maxRetries: options?.maxRetries ?? VOTE_TIMEOUTS.maxRetries,
|
|
1458
1941
|
allowSimulation: options?.allowSimulation ?? false,
|
|
1459
1942
|
declaredOptions: options?.declaredOptions,
|
|
1460
|
-
project: options?.project
|
|
1943
|
+
project: options?.project,
|
|
1944
|
+
workspace: options?.workspace
|
|
1461
1945
|
};
|
|
1462
1946
|
}
|
|
1463
1947
|
async function executeAgentVote(role, proposal, adapter, logger11, options) {
|
|
1464
1948
|
const start = getTimeProvider().now();
|
|
1465
|
-
const {
|
|
1949
|
+
const { allowSimulation, declaredOptions, ...settings } = resolveVoteExecution(options);
|
|
1466
1950
|
logger11.info("Executing vote", { role, model: adapter.modelId, provider: adapter.providerId });
|
|
1467
|
-
const retryOptions = { role, proposal, adapter, logger: logger11,
|
|
1951
|
+
const retryOptions = { role, proposal, adapter, logger: logger11, ...settings };
|
|
1468
1952
|
const result = await executeWithRetries({ ...retryOptions, options: declaredOptions });
|
|
1469
1953
|
const processingTimeMs = getTimeProvider().now() - start;
|
|
1470
1954
|
if (result.ok) {
|
|
@@ -1607,8 +2091,6 @@ async function assignPanelSeats(fallbackAdapter, options, logger11) {
|
|
|
1607
2091
|
async function collectRealVotes(options) {
|
|
1608
2092
|
const logger11 = options.logger ?? defaultLogger;
|
|
1609
2093
|
const { roles, proposal, simulate, allowSimulation } = options;
|
|
1610
|
-
const timeoutMs = options.timeoutMs ?? resolveVoteTimeout();
|
|
1611
|
-
const maxRetries = options.maxRetries ?? VOTE_TIMEOUTS.maxRetries;
|
|
1612
2094
|
if (simulate === true) {
|
|
1613
2095
|
logger11.info("Using simulation mode (explicitly requested)");
|
|
1614
2096
|
return createSimulatedVotes(roles, proposal);
|
|
@@ -1618,16 +2100,7 @@ async function collectRealVotes(options) {
|
|
|
1618
2100
|
return createSimulatedVotes(roles, proposal, "No adapter available");
|
|
1619
2101
|
const roleAdapters = await assignPanelSeats(adapterResult.adapter, options, logger11);
|
|
1620
2102
|
warnIfCodexConcurrencyExceeded(roleAdapters, logger11);
|
|
1621
|
-
const voteOptions = {
|
|
1622
|
-
timeoutMs,
|
|
1623
|
-
maxRetries,
|
|
1624
|
-
allowSimulation: allowSimulation ?? false,
|
|
1625
|
-
// #4472: reaches executeAgentVote, which puts the declared options in the
|
|
1626
|
-
// prompt and resolves each voter's selection against them.
|
|
1627
|
-
declaredOptions: options.declaredOptions,
|
|
1628
|
-
// #6110: likewise the target project, into every seat's system prompt.
|
|
1629
|
-
project: options.project
|
|
1630
|
-
};
|
|
2103
|
+
const voteOptions = resolveVoteExecution({ ...options, workspace: process.cwd() });
|
|
1631
2104
|
const interDelay = options.interAgentDelayMs ?? DEFAULT_INTER_AGENT_DELAY_MS;
|
|
1632
2105
|
const launchInput = {
|
|
1633
2106
|
roles,
|
|
@@ -1653,9 +2126,9 @@ async function collectRealVotes(options) {
|
|
|
1653
2126
|
// src/cli/voter-project.ts
|
|
1654
2127
|
import { readFileSync, statSync } from "node:fs";
|
|
1655
2128
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
1656
|
-
import { z as
|
|
2129
|
+
import { z as z4 } from "zod";
|
|
1657
2130
|
var VOTER_PROJECT_PATTERN = /^[A-Za-z0-9._/@-]{1,200}$/;
|
|
1658
|
-
var VoterProjectInputSchema =
|
|
2131
|
+
var VoterProjectInputSchema = z4.string().regex(VOTER_PROJECT_PATTERN).optional().describe(
|
|
1659
2132
|
"The project the panel is judging (#6110), e.g. `acme/widgets` \u2014 it replaces `nexus-agents` in every voter's system prompt, so a consuming repository is not judged against this one's mission and governance files. When omitted the name is DERIVED from the server's working directory (the `origin` remote as `owner/repo`, else the nearest `package.json` name) and falls back to `nexus-agents`; the response discloses which on `project.source`. Letters, digits and `._/@-` only, at most 200 characters."
|
|
1660
2133
|
);
|
|
1661
2134
|
var MAX_ANCESTOR_DEPTH = 64;
|
|
@@ -1821,40 +2294,40 @@ function describeVeto(verdict) {
|
|
|
1821
2294
|
}
|
|
1822
2295
|
|
|
1823
2296
|
// src/consensus/types-voting-protocol.ts
|
|
1824
|
-
import { z as
|
|
2297
|
+
import { z as z5 } from "zod";
|
|
1825
2298
|
var VOTING_ROUND_DEFAULT_TIMEOUT_MS = OPERATION_CLASSES["multi-llm-panel"].guardMs;
|
|
1826
|
-
var VotingRoundPhaseSchema =
|
|
1827
|
-
var VotingRoundStatusSchema =
|
|
2299
|
+
var VotingRoundPhaseSchema = z5.enum(["analysis", "deliberation", "consensus"]);
|
|
2300
|
+
var VotingRoundStatusSchema = z5.enum([
|
|
1828
2301
|
"pending",
|
|
1829
2302
|
"in_progress",
|
|
1830
2303
|
"awaiting_votes",
|
|
1831
2304
|
"completed",
|
|
1832
2305
|
"aborted"
|
|
1833
2306
|
]);
|
|
1834
|
-
var AgentFindingSchema =
|
|
1835
|
-
agentId:
|
|
1836
|
-
category:
|
|
1837
|
-
severity:
|
|
1838
|
-
description:
|
|
1839
|
-
location:
|
|
1840
|
-
suggestion:
|
|
1841
|
-
confidence:
|
|
1842
|
-
timestamp:
|
|
2307
|
+
var AgentFindingSchema = z5.object({
|
|
2308
|
+
agentId: z5.string(),
|
|
2309
|
+
category: z5.enum(["bug", "security", "performance", "style", "design", "documentation", "other"]),
|
|
2310
|
+
severity: z5.enum(["critical", "major", "minor", "suggestion"]),
|
|
2311
|
+
description: z5.string().min(1),
|
|
2312
|
+
location: z5.string().optional().describe("File path and line range if applicable"),
|
|
2313
|
+
suggestion: z5.string().optional().describe("Recommended fix"),
|
|
2314
|
+
confidence: z5.number().min(0).max(1),
|
|
2315
|
+
timestamp: z5.iso.datetime().optional()
|
|
1843
2316
|
});
|
|
1844
|
-
var FindingVoteSchema =
|
|
1845
|
-
agentId:
|
|
1846
|
-
findingId:
|
|
1847
|
-
agree:
|
|
1848
|
-
reasoning:
|
|
1849
|
-
amendedSeverity:
|
|
2317
|
+
var FindingVoteSchema = z5.object({
|
|
2318
|
+
agentId: z5.string(),
|
|
2319
|
+
findingId: z5.string(),
|
|
2320
|
+
agree: z5.boolean(),
|
|
2321
|
+
reasoning: z5.string().optional(),
|
|
2322
|
+
amendedSeverity: z5.enum(["critical", "major", "minor", "suggestion"]).optional()
|
|
1850
2323
|
});
|
|
1851
|
-
var VotingProtocolConfigSchema =
|
|
1852
|
-
committeeSize:
|
|
1853
|
-
maxRounds:
|
|
1854
|
-
roundTimeoutMs:
|
|
1855
|
-
agreementThreshold:
|
|
1856
|
-
enableAntiSycophancy:
|
|
1857
|
-
sycophancyThreshold:
|
|
2324
|
+
var VotingProtocolConfigSchema = z5.object({
|
|
2325
|
+
committeeSize: z5.number().int().min(2).max(7).default(3),
|
|
2326
|
+
maxRounds: z5.number().int().min(1).max(5).default(3),
|
|
2327
|
+
roundTimeoutMs: z5.number().int().positive().default(VOTING_ROUND_DEFAULT_TIMEOUT_MS),
|
|
2328
|
+
agreementThreshold: z5.number().min(0.5).max(1).default(SUPERMAJORITY_THRESHOLD),
|
|
2329
|
+
enableAntiSycophancy: z5.boolean().default(true),
|
|
2330
|
+
sycophancyThreshold: z5.number().min(0).max(1).default(0.8)
|
|
1858
2331
|
});
|
|
1859
2332
|
var DEFAULT_VOTING_PROTOCOL_CONFIG = {
|
|
1860
2333
|
committeeSize: 3,
|
|
@@ -1867,30 +2340,30 @@ var DEFAULT_VOTING_PROTOCOL_CONFIG = {
|
|
|
1867
2340
|
};
|
|
1868
2341
|
|
|
1869
2342
|
// src/consensus/types-weighted-voting.ts
|
|
1870
|
-
import { z as
|
|
1871
|
-
var TaskOutcomeStatusSchema =
|
|
1872
|
-
var WeightedAgentRecordSchema =
|
|
1873
|
-
agentId:
|
|
1874
|
-
totalTasks:
|
|
1875
|
-
successfulTasks:
|
|
1876
|
-
failedTasks:
|
|
1877
|
-
partialTasks:
|
|
1878
|
-
successRate:
|
|
1879
|
-
weight:
|
|
1880
|
-
trustScore:
|
|
1881
|
-
byzantineFlags:
|
|
1882
|
-
lastActive:
|
|
1883
|
-
createdAt:
|
|
2343
|
+
import { z as z6 } from "zod";
|
|
2344
|
+
var TaskOutcomeStatusSchema = z6.enum(["success", "failure", "partial", "unknown"]);
|
|
2345
|
+
var WeightedAgentRecordSchema = z6.object({
|
|
2346
|
+
agentId: z6.string().min(1),
|
|
2347
|
+
totalTasks: z6.number().int().nonnegative(),
|
|
2348
|
+
successfulTasks: z6.number().int().nonnegative(),
|
|
2349
|
+
failedTasks: z6.number().int().nonnegative(),
|
|
2350
|
+
partialTasks: z6.number().int().nonnegative(),
|
|
2351
|
+
successRate: z6.number().min(0).max(1),
|
|
2352
|
+
weight: z6.number().min(0).max(1),
|
|
2353
|
+
trustScore: z6.number().min(0).max(1),
|
|
2354
|
+
byzantineFlags: z6.number().int().nonnegative(),
|
|
2355
|
+
lastActive: z6.date(),
|
|
2356
|
+
createdAt: z6.date()
|
|
1884
2357
|
});
|
|
1885
|
-
var WeightedVotingConfigSchema =
|
|
1886
|
-
minWeight:
|
|
1887
|
-
maxByzantineFraction:
|
|
1888
|
-
weightDecayFactor:
|
|
1889
|
-
weightRecoveryFactor:
|
|
1890
|
-
minTrustScore:
|
|
1891
|
-
byzantineFlagThreshold:
|
|
1892
|
-
initialWeight:
|
|
1893
|
-
quorumThreshold:
|
|
2358
|
+
var WeightedVotingConfigSchema = z6.object({
|
|
2359
|
+
minWeight: z6.number().min(0).max(1).default(0.1),
|
|
2360
|
+
maxByzantineFraction: z6.number().min(0).max(0.5).default(0.33),
|
|
2361
|
+
weightDecayFactor: z6.number().min(0.5).max(1).default(0.9),
|
|
2362
|
+
weightRecoveryFactor: z6.number().min(1).max(2).default(1.05),
|
|
2363
|
+
minTrustScore: z6.number().min(0).max(1).default(0.3),
|
|
2364
|
+
byzantineFlagThreshold: z6.number().int().positive().default(3),
|
|
2365
|
+
initialWeight: z6.number().min(0).max(1).default(0.5),
|
|
2366
|
+
quorumThreshold: z6.number().min(0.5).max(1).default(SUPERMAJORITY_THRESHOLD)
|
|
1894
2367
|
});
|
|
1895
2368
|
var DEFAULT_WEIGHTED_VOTING_CONFIG = {
|
|
1896
2369
|
minWeight: 0.1,
|
|
@@ -1905,7 +2378,7 @@ var DEFAULT_WEIGHTED_VOTING_CONFIG = {
|
|
|
1905
2378
|
};
|
|
1906
2379
|
|
|
1907
2380
|
// src/consensus/higher-order-types.ts
|
|
1908
|
-
import { z as
|
|
2381
|
+
import { z as z7 } from "zod";
|
|
1909
2382
|
function createAgentPairKey(agentA, agentB) {
|
|
1910
2383
|
return agentA < agentB ? `${agentA}:${agentB}` : `${agentB}:${agentA}`;
|
|
1911
2384
|
}
|
|
@@ -1916,52 +2389,52 @@ function parseAgentPairKey(key) {
|
|
|
1916
2389
|
}
|
|
1917
2390
|
return [parts[0], parts[1]];
|
|
1918
2391
|
}
|
|
1919
|
-
var CorrelationCoefficientSchema =
|
|
1920
|
-
var IndependentSubsetSchema =
|
|
1921
|
-
id:
|
|
1922
|
-
agentIds:
|
|
1923
|
-
independenceScore:
|
|
1924
|
-
pairCoverage:
|
|
1925
|
-
observed:
|
|
1926
|
-
total:
|
|
2392
|
+
var CorrelationCoefficientSchema = z7.number().min(-1).max(1);
|
|
2393
|
+
var IndependentSubsetSchema = z7.object({
|
|
2394
|
+
id: z7.string(),
|
|
2395
|
+
agentIds: z7.array(z7.string()),
|
|
2396
|
+
independenceScore: z7.number().min(0).max(1),
|
|
2397
|
+
pairCoverage: z7.object({
|
|
2398
|
+
observed: z7.number().int().nonnegative(),
|
|
2399
|
+
total: z7.number().int().nonnegative()
|
|
1927
2400
|
}),
|
|
1928
|
-
observationCount:
|
|
2401
|
+
observationCount: z7.number().int().nonnegative()
|
|
1929
2402
|
});
|
|
1930
|
-
var VotingObservationSchema =
|
|
1931
|
-
proposalId:
|
|
1932
|
-
agentId:
|
|
1933
|
-
decision:
|
|
1934
|
-
confidence:
|
|
1935
|
-
alignedWithOutcome:
|
|
1936
|
-
timestamp:
|
|
1937
|
-
modelKey:
|
|
1938
|
-
observedModel:
|
|
2403
|
+
var VotingObservationSchema = z7.object({
|
|
2404
|
+
proposalId: z7.string(),
|
|
2405
|
+
agentId: z7.string(),
|
|
2406
|
+
decision: z7.enum(["approve", "reject", "abstain"]),
|
|
2407
|
+
confidence: z7.number().min(0).max(1),
|
|
2408
|
+
alignedWithOutcome: z7.boolean(),
|
|
2409
|
+
timestamp: z7.date(),
|
|
2410
|
+
modelKey: z7.string().optional(),
|
|
2411
|
+
observedModel: z7.string().optional()
|
|
1939
2412
|
});
|
|
1940
|
-
var PairwiseVotingHistorySchema =
|
|
1941
|
-
pairKey:
|
|
1942
|
-
jointObservations:
|
|
1943
|
-
agreements:
|
|
1944
|
-
disagreements:
|
|
2413
|
+
var PairwiseVotingHistorySchema = z7.object({
|
|
2414
|
+
pairKey: z7.string(),
|
|
2415
|
+
jointObservations: z7.number().int().nonnegative(),
|
|
2416
|
+
agreements: z7.number().int().nonnegative(),
|
|
2417
|
+
disagreements: z7.number().int().nonnegative(),
|
|
1945
2418
|
correlation: CorrelationCoefficientSchema,
|
|
1946
|
-
lastUpdated:
|
|
2419
|
+
lastUpdated: z7.date()
|
|
1947
2420
|
});
|
|
1948
|
-
var HigherOrderVotingConfigSchema =
|
|
1949
|
-
minObservationsForCorrelation:
|
|
1950
|
-
correlationThreshold:
|
|
2421
|
+
var HigherOrderVotingConfigSchema = z7.object({
|
|
2422
|
+
minObservationsForCorrelation: z7.number().int().positive().default(10),
|
|
2423
|
+
correlationThreshold: z7.number().min(0).max(1).default(0.3),
|
|
1951
2424
|
/**
|
|
1952
2425
|
* @deprecated Ignored since 8.x: correlation evidence is lifetime and partitioned by the role's pinned model (#5555); nothing reads this value. Removed in the next major (#5564).
|
|
1953
2426
|
*/
|
|
1954
|
-
correlationMaxAgeMs:
|
|
2427
|
+
correlationMaxAgeMs: z7.number().int().positive().default(864e5),
|
|
1955
2428
|
// 24 hours
|
|
1956
|
-
independenceThreshold:
|
|
1957
|
-
fallbackToSimpleVoting:
|
|
2429
|
+
independenceThreshold: z7.number().min(0).max(1).default(0.2),
|
|
2430
|
+
fallbackToSimpleVoting: z7.boolean().default(true),
|
|
1958
2431
|
/**
|
|
1959
2432
|
* @deprecated Ignored since 8.x: correlation evidence is lifetime and partitioned by the role's pinned model (#5555); nothing reads this value. Removed in the next major (#5564).
|
|
1960
2433
|
*/
|
|
1961
|
-
observationDecayFactor:
|
|
1962
|
-
maxObservationsPerAgent:
|
|
1963
|
-
maxProposals:
|
|
1964
|
-
maxTrackedPairs:
|
|
2434
|
+
observationDecayFactor: z7.number().min(0).max(1).default(0.95),
|
|
2435
|
+
maxObservationsPerAgent: z7.number().int().positive().default(1e3),
|
|
2436
|
+
maxProposals: z7.number().int().positive().default(5e3),
|
|
2437
|
+
maxTrackedPairs: z7.number().int().positive().default(100)
|
|
1965
2438
|
});
|
|
1966
2439
|
var DEFAULT_HIGHER_ORDER_CONFIG = {
|
|
1967
2440
|
minObservationsForCorrelation: 10,
|
|
@@ -1975,25 +2448,25 @@ var DEFAULT_HIGHER_ORDER_CONFIG = {
|
|
|
1975
2448
|
maxProposals: 5e3,
|
|
1976
2449
|
maxTrackedPairs: 100
|
|
1977
2450
|
};
|
|
1978
|
-
var HigherOrderVotingResultSchema =
|
|
1979
|
-
decision:
|
|
1980
|
-
posteriorApproval:
|
|
1981
|
-
posteriorRejection:
|
|
1982
|
-
effectiveVoteCount:
|
|
1983
|
-
usedCorrelationData:
|
|
1984
|
-
method:
|
|
1985
|
-
improvementOverBaseline:
|
|
1986
|
-
independentSubsets:
|
|
1987
|
-
downweightedAgents:
|
|
1988
|
-
reasoning:
|
|
2451
|
+
var HigherOrderVotingResultSchema = z7.object({
|
|
2452
|
+
decision: z7.enum(["approve", "reject", "no_consensus"]),
|
|
2453
|
+
posteriorApproval: z7.number().min(0).max(1),
|
|
2454
|
+
posteriorRejection: z7.number().min(0).max(1),
|
|
2455
|
+
effectiveVoteCount: z7.number().nonnegative(),
|
|
2456
|
+
usedCorrelationData: z7.boolean(),
|
|
2457
|
+
method: z7.enum(["ow", "isp", "simple"]),
|
|
2458
|
+
improvementOverBaseline: z7.number(),
|
|
2459
|
+
independentSubsets: z7.array(IndependentSubsetSchema).optional(),
|
|
2460
|
+
downweightedAgents: z7.array(z7.string()),
|
|
2461
|
+
reasoning: z7.string()
|
|
1989
2462
|
});
|
|
1990
|
-
var CorrelationTrackerStatsSchema =
|
|
1991
|
-
totalAgents:
|
|
1992
|
-
trackedPairs:
|
|
1993
|
-
totalObservations:
|
|
1994
|
-
averageCorrelation:
|
|
1995
|
-
independentSubsetCount:
|
|
1996
|
-
pairsWithSufficientData:
|
|
2463
|
+
var CorrelationTrackerStatsSchema = z7.object({
|
|
2464
|
+
totalAgents: z7.number().int().nonnegative(),
|
|
2465
|
+
trackedPairs: z7.number().int().nonnegative(),
|
|
2466
|
+
totalObservations: z7.number().int().nonnegative(),
|
|
2467
|
+
averageCorrelation: z7.number(),
|
|
2468
|
+
independentSubsetCount: z7.number().int().nonnegative(),
|
|
2469
|
+
pairsWithSufficientData: z7.number().int().nonnegative()
|
|
1997
2470
|
});
|
|
1998
2471
|
|
|
1999
2472
|
// src/consensus/higher-order-helpers.ts
|
|
@@ -5005,24 +5478,24 @@ function createCorrelationTracker(config) {
|
|
|
5005
5478
|
import * as fs from "node:fs";
|
|
5006
5479
|
|
|
5007
5480
|
// src/consensus/correlation-persistence-records.ts
|
|
5008
|
-
import { z as
|
|
5009
|
-
var PersistedVoteSchema =
|
|
5010
|
-
agentId:
|
|
5011
|
-
decision:
|
|
5012
|
-
confidence:
|
|
5013
|
-
modelKey:
|
|
5014
|
-
observedModel:
|
|
5481
|
+
import { z as z8 } from "zod";
|
|
5482
|
+
var PersistedVoteSchema = z8.object({
|
|
5483
|
+
agentId: z8.string(),
|
|
5484
|
+
decision: z8.enum(["approve", "reject", "abstain"]),
|
|
5485
|
+
confidence: z8.number().min(0).max(1),
|
|
5486
|
+
modelKey: z8.string().optional(),
|
|
5487
|
+
observedModel: z8.string().optional()
|
|
5015
5488
|
});
|
|
5016
|
-
var PersistedProposalSchema =
|
|
5017
|
-
proposalId:
|
|
5018
|
-
votes:
|
|
5019
|
-
outcome:
|
|
5020
|
-
timestamp:
|
|
5489
|
+
var PersistedProposalSchema = z8.object({
|
|
5490
|
+
proposalId: z8.string(),
|
|
5491
|
+
votes: z8.array(PersistedVoteSchema),
|
|
5492
|
+
outcome: z8.enum(["approved", "rejected"]),
|
|
5493
|
+
timestamp: z8.iso.datetime()
|
|
5021
5494
|
});
|
|
5022
|
-
var PersistedCorrelationDataSchema =
|
|
5023
|
-
version:
|
|
5024
|
-
proposals:
|
|
5025
|
-
savedAt:
|
|
5495
|
+
var PersistedCorrelationDataSchema = z8.object({
|
|
5496
|
+
version: z8.number().int().positive(),
|
|
5497
|
+
proposals: z8.array(PersistedProposalSchema),
|
|
5498
|
+
savedAt: z8.iso.datetime()
|
|
5026
5499
|
});
|
|
5027
5500
|
function createPersistedProposal(proposalId, votes, outcome, context) {
|
|
5028
5501
|
const persistedVotes = [];
|
|
@@ -5270,449 +5743,40 @@ import { z as z9 } from "zod";
|
|
|
5270
5743
|
function answeringSeats(votes) {
|
|
5271
5744
|
return votes.filter((v) => v.source === "llm");
|
|
5272
5745
|
}
|
|
5273
|
-
function resolvedModel(v) {
|
|
5274
|
-
return v.model === void 0 || v.model === "" || v.model === UNRESOLVED_MODEL_ID ? void 0 : v.model;
|
|
5275
|
-
}
|
|
5276
|
-
function seatFallbacks(votes) {
|
|
5277
|
-
const out = [];
|
|
5278
|
-
for (const v of answeringSeats(votes)) {
|
|
5279
|
-
if (v.fallback === void 0) continue;
|
|
5280
|
-
out.push({
|
|
5281
|
-
role: v.role,
|
|
5282
|
-
fallback: v.fallback,
|
|
5283
|
-
toCli: v.cli === void 0 ? "?" : bareCliName(v.cli),
|
|
5284
|
-
toModel: resolvedModel(v)
|
|
5285
|
-
});
|
|
5286
|
-
}
|
|
5287
|
-
return out;
|
|
5288
|
-
}
|
|
5289
|
-
function panelDiversityOf(votes) {
|
|
5290
|
-
const models = answeringSeats(votes).map(resolvedModel).filter((m) => m !== void 0);
|
|
5291
|
-
return {
|
|
5292
|
-
distinctModels: countDistinctModels(models),
|
|
5293
|
-
fallbacks: seatFallbacks(votes).length
|
|
5294
|
-
};
|
|
5295
|
-
}
|
|
5296
|
-
var MIN_PANEL_FOR_DIVERSITY_WARNING = 3;
|
|
5297
|
-
function singleModelPanelWarning(votes) {
|
|
5298
|
-
if (votes.length < MIN_PANEL_FOR_DIVERSITY_WARNING) return void 0;
|
|
5299
|
-
const answered = answeringSeats(votes);
|
|
5300
|
-
const models = answered.map(resolvedModel);
|
|
5301
|
-
const model = models[0];
|
|
5302
|
-
if (model === void 0 || models.includes(void 0)) return void 0;
|
|
5303
|
-
if (panelDiversityOf(votes).distinctModels !== 1) return void 0;
|
|
5304
|
-
const silent = votes.length - answered.length;
|
|
5305
|
-
const missing = silent > 0 ? ` (${String(silent)} did not answer)` : "";
|
|
5306
|
-
return `All ${String(answered.length)} seats answered on ${model}${missing}; independence is weaker than assigned.`;
|
|
5307
|
-
}
|
|
5308
|
-
|
|
5309
|
-
// src/audit/vote-record.ts
|
|
5310
|
-
import * as crypto from "node:crypto";
|
|
5311
|
-
import { z as z8 } from "zod";
|
|
5312
|
-
var VoteRecordDecisionSchema = z8.enum(["approved", "rejected", "no_quorum"]);
|
|
5313
|
-
var VoteRecordOptionCoverageSchema = z8.object({
|
|
5314
|
-
/** Every approving voter, selecting or not — the tally's denominator. */
|
|
5315
|
-
approverCount: z8.number().int().nonnegative(),
|
|
5316
|
-
/** Approvers whose selection matched a declared option. */
|
|
5317
|
-
selectedCount: z8.number().int().nonnegative(),
|
|
5318
|
-
/** Approvers with no usable selection; their choice is unmeasured. */
|
|
5319
|
-
unattributedApprovals: z8.number().int().nonnegative()
|
|
5320
|
-
}).strict();
|
|
5321
|
-
var VoteRecordPanelCoverageSchema = z8.object({
|
|
5322
|
-
/** Voters the panel asked for. */
|
|
5323
|
-
requested: z8.number().int().nonnegative(),
|
|
5324
|
-
/** Voters that returned a usable vote — the denominator of `voteCounts`. */
|
|
5325
|
-
responded: z8.number().int().nonnegative(),
|
|
5326
|
-
/** Voters that errored or timed out. */
|
|
5327
|
-
errored: z8.number().int().nonnegative(),
|
|
5328
|
-
/** The roles behind `errored`, in panel order. */
|
|
5329
|
-
erroredRoles: z8.array(z8.string().min(1).max(100))
|
|
5330
|
-
}).strict();
|
|
5331
|
-
var MAX_VOTER_REASONING_CHARS = 2e4;
|
|
5332
|
-
var SeatFallbackRecordSchema = z8.object({
|
|
5333
|
-
/** The CLI the seat was assigned to, bare (`claude`, not `cli-claude`). */
|
|
5334
|
-
fromCli: z8.string().min(1).max(100),
|
|
5335
|
-
/** The model the assigned adapter had detected, when it had one. */
|
|
5336
|
-
fromModel: z8.string().min(1).max(200).optional(),
|
|
5337
|
-
/** The adapter-layer class of the error that moved the seat. */
|
|
5338
|
-
reason: z8.enum(["rate-limit", "capacity", "auth", "timeout", "sandbox", "unknown"])
|
|
5339
|
-
}).strict();
|
|
5340
|
-
var VoterSummarySchema = z8.object({
|
|
5341
|
-
role: z8.string().min(1).max(100),
|
|
5342
|
-
decision: z8.enum(["approve", "reject", "abstain"]),
|
|
5343
|
-
confidence: z8.number().min(0).max(1),
|
|
5344
|
-
/**
|
|
5345
|
-
* The voter's stated grounds (#5373, schema 1.6).
|
|
5346
|
-
*
|
|
5347
|
-
* `generateVoteHash` already hashed `{role, decision, reasoning}` and then
|
|
5348
|
-
* discarded the text, so the chain attested to a value it did not store and
|
|
5349
|
-
* nobody could re-verify the hash without re-obtaining the reasoning. On
|
|
5350
|
-
* #5228 a contrarian rejection was clipped mid-sentence in the terminal, the
|
|
5351
|
-
* grounds were unrecoverable, and the same defect resurfaced a round later —
|
|
5352
|
-
* one round of a 7-voter panel is 7-13 minutes of model time, and the
|
|
5353
|
-
* objection was right both times.
|
|
5354
|
-
*
|
|
5355
|
-
* Stored whole rather than sampled. Warn-mode near-misses are emitted per
|
|
5356
|
-
* TOOL CALL, thousands a day; votes are emitted per PANEL, dozens a day at
|
|
5357
|
-
* most, so ~17 KB per vote is not the same growth problem.
|
|
5358
|
-
*
|
|
5359
|
-
* Absence is not an empty argument: an errored voter has no entry in
|
|
5360
|
-
* `voters` at all (see `panelCoverage`), so `reasoning: ''` means a live
|
|
5361
|
-
* voter returned nothing, which is itself a signal.
|
|
5362
|
-
*/
|
|
5363
|
-
reasoning: z8.string().max(MAX_VOTER_REASONING_CHARS).optional(),
|
|
5364
|
-
/** True when `reasoning` was clipped to {@link MAX_VOTER_REASONING_CHARS}. */
|
|
5365
|
-
reasoningTruncated: z8.literal(true).optional(),
|
|
5366
|
-
/**
|
|
5367
|
-
* True when this seat was recovered by the per-role retry (#6050, schema 1.7).
|
|
5368
|
-
*
|
|
5369
|
-
* `voter-retry.ts` has set `retried: true` on recovered results since it was
|
|
5370
|
-
* written, and `vote-types.ts` states the reason: the flag is "what makes the
|
|
5371
|
-
* recovery visible instead of indistinguishable from a clean first attempt".
|
|
5372
|
-
* It had one producer and ZERO consumers — both summarizers and the record
|
|
5373
|
-
* dropped it — so the field existed, was documented, and never reached
|
|
5374
|
-
* anything that could act on it.
|
|
5375
|
-
*
|
|
5376
|
-
* A retried seat is weaker evidence than a first-pass one: the model was
|
|
5377
|
-
* unavailable or timed out, and the recovery ran under different conditions.
|
|
5378
|
-
* For a ratification vote on a governor-path change, "7 of 7 answered" and
|
|
5379
|
-
* "6 answered, 1 recovered on retry" are different facts about the scrutiny
|
|
5380
|
-
* the change received, and the record stated the first for both.
|
|
5381
|
-
*
|
|
5382
|
-
* `literal(true)` and optional, on the `reasoningTruncated` rule: a clean
|
|
5383
|
-
* seat carries no key, so its entry re-hashes byte-identical and every
|
|
5384
|
-
* historical record still verifies.
|
|
5385
|
-
*/
|
|
5386
|
-
retried: z8.literal(true).optional(),
|
|
5387
|
-
/**
|
|
5388
|
-
* Registry model id the seat ran on (#6091, schema 1.8).
|
|
5389
|
-
*
|
|
5390
|
-
* The seat→model mapping is round-robin over the available CLIs plus
|
|
5391
|
-
* `NEXUS_VOTER_MODEL_<ROLE>` pins, so it is not recoverable from the
|
|
5392
|
-
* ledger after the fact: 1844 voter entries across 278 records carried no
|
|
5393
|
-
* model. "When an agent's output becomes evidence, its provenance travels
|
|
5394
|
-
* with it" — a tally that says `scope_steward: approve` without saying
|
|
5395
|
-
* which model answered cannot be audited for the #6068 failure class.
|
|
5396
|
-
* Present-only, on the `retried` rule; absent when the result carried no
|
|
5397
|
-
* model or only the pending-detection placeholder.
|
|
5398
|
-
*/
|
|
5399
|
-
model: z8.string().min(1).max(200).optional(),
|
|
5400
|
-
/**
|
|
5401
|
-
* True when the seat could not read the artifact (#6094, schema 1.8).
|
|
5402
|
-
*
|
|
5403
|
-
* `decision` is `abstain` for such a seat, so without this flag the record
|
|
5404
|
-
* could not tell "read it and abstained" from "never saw it" — and one
|
|
5405
|
-
* ledger entry (`vote-1789058788915-6lfrbuq`) shows a seat that APPROVED
|
|
5406
|
-
* on the proposal text after failing to read. `literal(true)` and
|
|
5407
|
-
* present-only, so every pre-1.8 entry re-hashes byte-identical.
|
|
5408
|
-
*/
|
|
5409
|
-
unverifiable: z8.literal(true).optional(),
|
|
5410
|
-
/**
|
|
5411
|
-
* The CLI the round-robin or `NEXUS_VOTER_MODEL_<ROLE>` pin chose for the
|
|
5412
|
-
* seat, as a bare name (#6115, schema 1.9). `model` says where a seat
|
|
5413
|
-
* answered; this says where it was MEANT to. Three consecutive 7-seat
|
|
5414
|
-
* ratification panels on 2026-09-13 answered every seat on one gemini
|
|
5415
|
-
* model while the assignment was three claude, two codex, two gemini,
|
|
5416
|
-
* and the 1.8 record showed seven identical `model` values with nothing
|
|
5417
|
-
* that said five of them were substitutes. Present-only, on the `model`
|
|
5418
|
-
* rule; absent on a result built outside the panel launcher.
|
|
5419
|
-
*/
|
|
5420
|
-
assignedCli: z8.string().min(1).max(100).optional(),
|
|
5421
|
-
/**
|
|
5422
|
-
* Present only when the seat answered on a different CLI or model than
|
|
5423
|
-
* assigned (#6115, schema 1.9): the exact `SeatFallback` shape the live
|
|
5424
|
-
* result carries, rebuilt field-by-field. `fromCli` is the assigned CLI,
|
|
5425
|
-
* `fromModel` the model it had detected (absent when it never did — the
|
|
5426
|
-
* pending-detection placeholder is not a model), `reason` the adapter
|
|
5427
|
-
* layer's error class. The vocabulary is compile-checked against the live
|
|
5428
|
-
* `FallbackReason` in vote-record.test.ts; a class one side learns alone
|
|
5429
|
-
* would either refuse every record that carries it (#6054) or accept one
|
|
5430
|
-
* no producer can write.
|
|
5431
|
-
*/
|
|
5432
|
-
fallback: SeatFallbackRecordSchema.optional()
|
|
5433
|
-
}).strict();
|
|
5434
|
-
function defineVoterKeys(keys) {
|
|
5435
|
-
return keys;
|
|
5436
|
-
}
|
|
5437
|
-
var VOTER_SUMMARY_KEYS = defineVoterKeys([
|
|
5438
|
-
"role",
|
|
5439
|
-
"decision",
|
|
5440
|
-
"confidence",
|
|
5441
|
-
"reasoning",
|
|
5442
|
-
"reasoningTruncated",
|
|
5443
|
-
"retried",
|
|
5444
|
-
// 1.8 (#6091, #6094): appended after `retried`, present-only, so a 1.7
|
|
5445
|
-
// entry projects byte-identically.
|
|
5446
|
-
"model",
|
|
5447
|
-
"unverifiable",
|
|
5448
|
-
// 1.9 (#6115): appended after `unverifiable`, present-only, so a 1.8 entry
|
|
5449
|
-
// projects byte-identically. `fallback` is the first nested voter field;
|
|
5450
|
-
// `projectSeatFallback` rebuilds it in its own canonical order.
|
|
5451
|
-
"assignedCli",
|
|
5452
|
-
"fallback"
|
|
5453
|
-
]);
|
|
5454
|
-
function noUnprojectedKeys(rest) {
|
|
5455
|
-
return rest;
|
|
5456
|
-
}
|
|
5457
|
-
function projectSeatFallback(f) {
|
|
5458
|
-
const { fromCli, fromModel, reason, ...rest } = f;
|
|
5459
|
-
noUnprojectedKeys(rest);
|
|
5460
|
-
return {
|
|
5461
|
-
fromCli,
|
|
5462
|
-
...fromModel !== void 0 ? { fromModel } : {},
|
|
5463
|
-
reason
|
|
5464
|
-
};
|
|
5465
|
-
}
|
|
5466
|
-
function projectVoterSummary(v) {
|
|
5467
|
-
const out = {};
|
|
5468
|
-
for (const key of VOTER_SUMMARY_KEYS) {
|
|
5469
|
-
const value = key === "fallback" ? v.fallback === void 0 ? void 0 : projectSeatFallback(v.fallback) : v[key];
|
|
5470
|
-
if (value !== void 0) out[key] = value;
|
|
5746
|
+
function resolvedModel(v) {
|
|
5747
|
+
return v.model === void 0 || v.model === "" || v.model === UNRESOLVED_MODEL_ID ? void 0 : v.model;
|
|
5748
|
+
}
|
|
5749
|
+
function seatFallbacks(votes) {
|
|
5750
|
+
const out = [];
|
|
5751
|
+
for (const v of answeringSeats(votes)) {
|
|
5752
|
+
if (v.fallback === void 0) continue;
|
|
5753
|
+
out.push({
|
|
5754
|
+
role: v.role,
|
|
5755
|
+
fallback: v.fallback,
|
|
5756
|
+
toCli: v.cli === void 0 ? "?" : bareCliName(v.cli),
|
|
5757
|
+
toModel: resolvedModel(v)
|
|
5758
|
+
});
|
|
5471
5759
|
}
|
|
5472
5760
|
return out;
|
|
5473
5761
|
}
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
}).strict();
|
|
5480
|
-
var VoteRecordOptionCountSchema = z8.object({
|
|
5481
|
-
/** The option label as declared in the proposal (e.g. 'A'). */
|
|
5482
|
-
option: z8.string().min(1),
|
|
5483
|
-
/** How many voters selected it. */
|
|
5484
|
-
count: z8.number().int().nonnegative()
|
|
5485
|
-
}).strict();
|
|
5486
|
-
var GIT_SHA_PATTERN = /^[0-9a-f]{40}$/;
|
|
5487
|
-
var VoteRecordPrBindingSchema = z8.object({
|
|
5488
|
-
pr: z8.number().int().positive(),
|
|
5489
|
-
headSha: z8.string().regex(GIT_SHA_PATTERN, "expected a full 40-hex lowercase commit sha")
|
|
5490
|
-
}).strict();
|
|
5491
|
-
function projectPrBinding(b) {
|
|
5492
|
-
return { pr: b.pr, headSha: b.headSha };
|
|
5493
|
-
}
|
|
5494
|
-
var VoteRecordErrorPolicySchema = z8.enum([
|
|
5495
|
-
"reduce_denominator",
|
|
5496
|
-
"count_as_abstain",
|
|
5497
|
-
"fail_closed",
|
|
5498
|
-
"absolute_quorum"
|
|
5499
|
-
]);
|
|
5500
|
-
var VoteRecordSchema = z8.object({
|
|
5501
|
-
/**
|
|
5502
|
-
* Schema version. '1.1' marked the chain→record-set+sequence model (#3927);
|
|
5503
|
-
* '1.2' adds the optional `ratifies` subject-binding field (#3927 item 1);
|
|
5504
|
-
* '1.10' adds the optional `ratifiesPr` PR-binding (#5130); '1.11' the
|
|
5505
|
-
* optional `errorPolicy` (#6211). Every tier is accepted — a 1.1 record
|
|
5506
|
-
* (no `ratifies`) verifies unchanged because each optional is folded into
|
|
5507
|
-
* the self-hash ONLY when present (see {@link computeVoteRecordHash}).
|
|
5508
|
-
* Tiers are labels, not ordered numbers: '1.10' follows '1.9' by
|
|
5509
|
-
* convention only and nothing compares them.
|
|
5510
|
-
*/
|
|
5511
|
-
version: z8.enum([
|
|
5512
|
-
"1.1",
|
|
5513
|
-
"1.2",
|
|
5514
|
-
"1.3",
|
|
5515
|
-
"1.4",
|
|
5516
|
-
"1.5",
|
|
5517
|
-
"1.6",
|
|
5518
|
-
"1.7",
|
|
5519
|
-
"1.8",
|
|
5520
|
-
"1.9",
|
|
5521
|
-
"1.10",
|
|
5522
|
-
"1.11"
|
|
5523
|
-
]),
|
|
5524
|
-
/** Unique record id (also usable as a `ratificationVoteRef`). */
|
|
5525
|
-
id: z8.string().min(1),
|
|
5526
|
-
/**
|
|
5527
|
-
* Monotonic sequence number (integer ≥ 0). Assigned as (max existing
|
|
5528
|
-
* sequence)+1 at write time. Sorted, the set of sequences must cover
|
|
5529
|
-
* 0..maxSeq with no gap (omission detection); DUPLICATE sequences are a
|
|
5530
|
-
* benign concurrent-fork signal, not tampering.
|
|
5531
|
-
*/
|
|
5532
|
-
sequence: z8.number().int().nonnegative(),
|
|
5533
|
-
/** ISO-8601 timestamp the vote was recorded. */
|
|
5534
|
-
recordedAt: z8.string().min(1),
|
|
5535
|
-
/**
|
|
5536
|
-
* SHA-256 of the FULL proposal text. The proposal itself is truncated for
|
|
5537
|
-
* the human record (`proposal`), but the hash binds the record to the exact
|
|
5538
|
-
* proposal voted on — a later edit of `proposal` that changes meaning is
|
|
5539
|
-
* detectable by recomputing this hash from the original.
|
|
5540
|
-
*/
|
|
5541
|
-
proposalHash: z8.string().length(64),
|
|
5542
|
-
/** Truncated proposal text for the human/reviewer record. */
|
|
5543
|
-
proposal: z8.string(),
|
|
5544
|
-
/** The voting strategy used. */
|
|
5545
|
-
strategy: z8.enum([
|
|
5546
|
-
"simple_majority",
|
|
5547
|
-
"supermajority",
|
|
5548
|
-
"unanimous",
|
|
5549
|
-
"higher_order",
|
|
5550
|
-
"opinion_wise",
|
|
5551
|
-
"proof_of_learning"
|
|
5552
|
-
]),
|
|
5553
|
-
/** The resolved decision. */
|
|
5554
|
-
decision: VoteRecordDecisionSchema,
|
|
5555
|
-
/** Approval fraction as a percentage (0-100). */
|
|
5556
|
-
approvalPercentage: z8.number().min(0).max(100),
|
|
5557
|
-
/** Vote-count breakdown. */
|
|
5558
|
-
voteCounts: VoteRecordCountsSchema,
|
|
5559
|
-
/** Per-voter {role, decision, confidence} summary. */
|
|
5560
|
-
voters: z8.array(VoterSummarySchema),
|
|
5561
|
-
/** Optional correlation/decision id linking to the cost rollup / trace. */
|
|
5562
|
-
correlationId: z8.string().min(1).optional(),
|
|
5563
|
-
/**
|
|
5564
|
-
* Per-option distribution for a multi-option proposal (#4452, schema 1.3).
|
|
5565
|
-
*
|
|
5566
|
-
* Present only when the vote declared `options`. Absent on an ordinary
|
|
5567
|
-
* yes/no vote, and absent on every 1.1/1.2 record — which is why it is
|
|
5568
|
-
* folded into the self-hash ONLY when present (see
|
|
5569
|
-
* {@link computeVoteRecordHash}), exactly as `ratifies` was.
|
|
5570
|
-
*
|
|
5571
|
-
* Without this, a 6-1 or 5-2 option split is recorded as `approve: 7` and
|
|
5572
|
-
* reads as unanimous. Threshold semantics invert too: `unanimous` becomes
|
|
5573
|
-
* the EASIEST bar to clear, because every engaged voter approves while
|
|
5574
|
-
* choosing different things.
|
|
5575
|
-
*/
|
|
5576
|
-
// No `.min(1)` (#6049). The rule this field's own docstring states is
|
|
5577
|
-
// "present only when the vote declared `options`" -- keyed on DECLARATION,
|
|
5578
|
-
// not on whether anyone picked one. `.min(1)` encoded the older, narrower
|
|
5579
|
-
// rule, so once the builder started emitting `[]` for "declared, nothing
|
|
5580
|
-
// attributable" the record appended fine and then failed to parse on read:
|
|
5581
|
-
// `too_small, minimum 1`. The write path does not validate, so the line
|
|
5582
|
-
// landed in the ledger and `parseVoteRecordsText` silently dropped it --
|
|
5583
|
-
// the case most worth auditing became the one no reader could see.
|
|
5584
|
-
//
|
|
5585
|
-
// Relaxing is a pure widening: no previously-valid record changes meaning
|
|
5586
|
-
// or hash, and no persisted record can currently hold an empty tally.
|
|
5587
|
-
optionTally: z8.array(VoteRecordOptionCountSchema).optional(),
|
|
5588
|
-
/**
|
|
5589
|
-
* Selection coverage for a multi-option vote (#4472, schema 1.4).
|
|
5590
|
-
*
|
|
5591
|
-
* `optionTally` alone cannot distinguish dissent from absence: `4 pick X
|
|
5592
|
-
* + 3 unreadable` and a genuine 4/3 split both leave a leading share of
|
|
5593
|
-
* 57%. Recording how many approvers produced no usable selection is what
|
|
5594
|
-
* makes a partial measurement legible AS partial — the condition every
|
|
5595
|
-
* voter attached to adopting the "credit no option" rule.
|
|
5596
|
-
*/
|
|
5597
|
-
optionCoverage: VoteRecordOptionCoverageSchema.optional(),
|
|
5598
|
-
/**
|
|
5599
|
-
* Panel coverage (#5738, schema 1.5). Present only when at least one
|
|
5600
|
-
* requested voter failed to return a vote; absent keeps a clean panel on
|
|
5601
|
-
* the pre-1.5 projection, so every historical record still verifies.
|
|
5602
|
-
*/
|
|
5603
|
-
panelCoverage: VoteRecordPanelCoverageSchema.optional(),
|
|
5604
|
-
/**
|
|
5605
|
-
* The loop/strategy subject this vote RATIFIES (#3927 item 1). Present only on
|
|
5606
|
-
* a ratification vote; set at vote time and bound into the self-hash (so it is
|
|
5607
|
-
* tamper-evident). The authority-tier promotion gate
|
|
5608
|
-
* (`scripts/check-authority-tier-drift.ts`) resolves a transition's
|
|
5609
|
-
* `ratificationVoteRef` to a record and requires `ratifies === transition.subject`
|
|
5610
|
-
* (with `decision === 'approved'` and `strategy === 'higher_order'`). Absent on
|
|
5611
|
-
* an ordinary (non-ratification) vote; a 1.1 record never carries it.
|
|
5612
|
-
*/
|
|
5613
|
-
ratifies: z8.string().min(1).optional(),
|
|
5614
|
-
/**
|
|
5615
|
-
* The PR this vote RATIFIES, bound to the head the panel saw (#5130 step 1,
|
|
5616
|
-
* schema 1.10; panel decision Q1 option A, 5 of 6). Present only on a
|
|
5617
|
-
* governor-path ratification vote; hash-covered like `ratifies`, so a
|
|
5618
|
-
* record cannot be repointed at a different PR or a later push without
|
|
5619
|
-
* breaking its hash. The governor gate (step 2, #5779/#5131) resolves the
|
|
5620
|
-
* record from the committed ledger and requires `pr` to be the PR under
|
|
5621
|
-
* review and `headSha` to be its head (or `head^` when `head` touches only
|
|
5622
|
-
* the ledger — the caller-commits tip). Absent on every pre-1.10 record.
|
|
5623
|
-
*
|
|
5624
|
-
* A SEPARATE key rather than a structured encoding of `ratifies`: that
|
|
5625
|
-
* field is the authority-ladder SUBJECT, compared by string equality to
|
|
5626
|
-
* `transition.subject` and grouped by `conflictingRatifiedSubjects`; no
|
|
5627
|
-
* resolver parses it. Overloading it would give one field two consumers
|
|
5628
|
-
* with two equality rules. The two may coexist on one record.
|
|
5629
|
-
*/
|
|
5630
|
-
ratifiesPr: VoteRecordPrBindingSchema.optional(),
|
|
5631
|
-
/**
|
|
5632
|
-
* The error policy the panel actually ran under (#6211, schema 1.11): the
|
|
5633
|
-
* EFFECTIVE policy after `consensus_vote` applied the per-strategy default
|
|
5634
|
-
* (`input.errorPolicy ?? getDefaultErrorPolicy(strategy)`), not the raw
|
|
5635
|
-
* input the caller may have omitted. Hash-covered, present-only.
|
|
5636
|
-
*
|
|
5637
|
-
* Before this tier the policy reached the RESPONSE only, so the governor
|
|
5638
|
-
* ledger gate (`scripts/governor-ledger-evidence.ts`) could not say which
|
|
5639
|
-
* policy a whole-panel ratification was configured with: under
|
|
5640
|
-
* `absolute_quorum` an errored seat voids the vote, so the one
|
|
5641
|
-
* ledger-observable trace of a different policy was an approved record
|
|
5642
|
-
* with `panelCoverage.errored > 0` — and a whole panel under
|
|
5643
|
-
* `reduce_denominator` looked exactly like one under `absolute_quorum`.
|
|
5644
|
-
* The gate's `wrong-error-policy` verdict reads this field; a record
|
|
5645
|
-
* without it (every pre-1.11 record) keeps the panel-coverage inference
|
|
5646
|
-
* and is reported as `errorPolicy: unrecorded`.
|
|
5647
|
-
*/
|
|
5648
|
-
errorPolicy: VoteRecordErrorPolicySchema.optional(),
|
|
5649
|
-
/**
|
|
5650
|
-
* ADVISORY hash of the tip record at write time (absent for the first).
|
|
5651
|
-
* Retained for audit texture but NOT covered by `hash` and NOT verified —
|
|
5652
|
-
* the record-set model is position-independent (#3927).
|
|
5653
|
-
*/
|
|
5654
|
-
previousHash: z8.string().length(64).optional(),
|
|
5655
|
-
/** SHA-256 over every field above EXCEPT `previousHash` (and except `hash`). */
|
|
5656
|
-
hash: z8.string().length(64)
|
|
5657
|
-
}).strict();
|
|
5658
|
-
function foldOptionalFields(base, payload) {
|
|
5659
|
-
const withTally = payload.optionTally !== void 0 ? {
|
|
5660
|
-
...base,
|
|
5661
|
-
optionTally: payload.optionTally.map((o) => ({ option: o.option, count: o.count }))
|
|
5662
|
-
} : base;
|
|
5663
|
-
const withCoverage = payload.optionCoverage !== void 0 ? {
|
|
5664
|
-
...withTally,
|
|
5665
|
-
optionCoverage: {
|
|
5666
|
-
approverCount: payload.optionCoverage.approverCount,
|
|
5667
|
-
selectedCount: payload.optionCoverage.selectedCount,
|
|
5668
|
-
unattributedApprovals: payload.optionCoverage.unattributedApprovals
|
|
5669
|
-
}
|
|
5670
|
-
} : withTally;
|
|
5671
|
-
const withPanel = payload.panelCoverage !== void 0 ? {
|
|
5672
|
-
...withCoverage,
|
|
5673
|
-
panelCoverage: {
|
|
5674
|
-
requested: payload.panelCoverage.requested,
|
|
5675
|
-
responded: payload.panelCoverage.responded,
|
|
5676
|
-
errored: payload.panelCoverage.errored,
|
|
5677
|
-
erroredRoles: [...payload.panelCoverage.erroredRoles]
|
|
5678
|
-
}
|
|
5679
|
-
} : withCoverage;
|
|
5680
|
-
const withRatifies = payload.ratifies !== void 0 ? { ...withPanel, ratifies: payload.ratifies } : withPanel;
|
|
5681
|
-
const withPrBinding = payload.ratifiesPr !== void 0 ? { ...withRatifies, ratifiesPr: projectPrBinding(payload.ratifiesPr) } : withRatifies;
|
|
5682
|
-
return payload.errorPolicy !== void 0 ? { ...withPrBinding, errorPolicy: payload.errorPolicy } : withPrBinding;
|
|
5683
|
-
}
|
|
5684
|
-
function computeVoteRecordHash(payload) {
|
|
5685
|
-
const base = {
|
|
5686
|
-
version: payload.version,
|
|
5687
|
-
id: payload.id,
|
|
5688
|
-
sequence: payload.sequence,
|
|
5689
|
-
recordedAt: payload.recordedAt,
|
|
5690
|
-
proposalHash: payload.proposalHash,
|
|
5691
|
-
proposal: payload.proposal,
|
|
5692
|
-
strategy: payload.strategy,
|
|
5693
|
-
decision: payload.decision,
|
|
5694
|
-
approvalPercentage: payload.approvalPercentage,
|
|
5695
|
-
// Rebuild voteCounts in schema order (approve, reject, abstain, total) so the
|
|
5696
|
-
// hash does not depend on how the nested object's keys were ordered (#3962).
|
|
5697
|
-
voteCounts: {
|
|
5698
|
-
approve: payload.voteCounts.approve,
|
|
5699
|
-
reject: payload.voteCounts.reject,
|
|
5700
|
-
abstain: payload.voteCounts.abstain,
|
|
5701
|
-
total: payload.voteCounts.total
|
|
5702
|
-
},
|
|
5703
|
-
// `reasoning` / `reasoningTruncated` (#5373, schema 1.6) are appended per
|
|
5704
|
-
// entry ONLY when present, on the same rule as the record-level optional
|
|
5705
|
-
// fields: a pre-1.6 voter entry re-hashes byte-identical, so every
|
|
5706
|
-
// historical record still verifies, while editing or removing a stored
|
|
5707
|
-
// reasoning flips the hash.
|
|
5708
|
-
voters: payload.voters.map(projectVoterSummary),
|
|
5709
|
-
correlationId: payload.correlationId ?? null
|
|
5762
|
+
function panelDiversityOf(votes) {
|
|
5763
|
+
const models = answeringSeats(votes).map(resolvedModel).filter((m) => m !== void 0);
|
|
5764
|
+
return {
|
|
5765
|
+
distinctModels: countDistinctModels(models),
|
|
5766
|
+
fallbacks: seatFallbacks(votes).length
|
|
5710
5767
|
};
|
|
5711
|
-
const canonical = JSON.stringify(foldOptionalFields(base, payload));
|
|
5712
|
-
return crypto.createHash("sha256").update(canonical).digest("hex");
|
|
5713
5768
|
}
|
|
5714
|
-
|
|
5715
|
-
|
|
5769
|
+
var MIN_PANEL_FOR_DIVERSITY_WARNING = 3;
|
|
5770
|
+
function singleModelPanelWarning(votes) {
|
|
5771
|
+
if (votes.length < MIN_PANEL_FOR_DIVERSITY_WARNING) return void 0;
|
|
5772
|
+
const answered = answeringSeats(votes);
|
|
5773
|
+
const models = answered.map(resolvedModel);
|
|
5774
|
+
const model = models[0];
|
|
5775
|
+
if (model === void 0 || models.includes(void 0)) return void 0;
|
|
5776
|
+
if (panelDiversityOf(votes).distinctModels !== 1) return void 0;
|
|
5777
|
+
const silent = votes.length - answered.length;
|
|
5778
|
+
const missing = silent > 0 ? ` (${String(silent)} did not answer)` : "";
|
|
5779
|
+
return `All ${String(answered.length)} seats answered on ${model}${missing}; independence is weaker than assigned.`;
|
|
5716
5780
|
}
|
|
5717
5781
|
|
|
5718
5782
|
// src/mcp/tools/consensus-vote-option-detection.ts
|
|
@@ -5876,7 +5940,9 @@ function toAgentVoteSummary(result) {
|
|
|
5876
5940
|
// #6094: same rule for a seat that could not read the artifact.
|
|
5877
5941
|
...result.source === "unverifiable" ? { unverifiable: true } : {},
|
|
5878
5942
|
// #6115: and for a seat that answered elsewhere.
|
|
5879
|
-
...result.fallback !== void 0 ? { fallback: result.fallback } : {}
|
|
5943
|
+
...result.fallback !== void 0 ? { fallback: result.fallback } : {},
|
|
5944
|
+
// #6246: and for what a recovered seat was retried from.
|
|
5945
|
+
...result.retriedFrom !== void 0 ? { retriedFrom: result.retriedFrom } : {}
|
|
5880
5946
|
};
|
|
5881
5947
|
}
|
|
5882
5948
|
function panelDegradationWarning(errorCount, total) {
|
|
@@ -6090,7 +6156,7 @@ function logPartialProposal(bounded, log) {
|
|
|
6090
6156
|
}
|
|
6091
6157
|
async function runContrarianCheck(proposal, log) {
|
|
6092
6158
|
try {
|
|
6093
|
-
const { executeExpert } = await import("./expert-bridge-
|
|
6159
|
+
const { executeExpert } = await import("./expert-bridge-QX2UR2BM.js");
|
|
6094
6160
|
const bounded = boundArtifactForReview(proposal, CONTRARIAN_PROPOSAL_BUDGET, "proposal");
|
|
6095
6161
|
logPartialProposal(bounded, log);
|
|
6096
6162
|
const result = await executeExpert("architecture", buildContrarianPrompt(bounded));
|
|
@@ -6236,17 +6302,18 @@ function toVoterSummaries(votes) {
|
|
|
6236
6302
|
// the fallback the live result stated. `model` alone showed seven
|
|
6237
6303
|
// identical values on a panel assigned three ways and could not say so.
|
|
6238
6304
|
...v.assignedCli !== void 0 ? { assignedCli: v.assignedCli } : {},
|
|
6239
|
-
...v.fallback !== void 0 ? { fallback: projectSeatFallback(v.fallback) } : {}
|
|
6305
|
+
...v.fallback !== void 0 ? { fallback: projectSeatFallback(v.fallback) } : {},
|
|
6306
|
+
// #6246: what the per-role retry replaced, so the record names both the
|
|
6307
|
+
// seat's final state and the state it recovered from. The live retry
|
|
6308
|
+
// already clipped and de-controlled the cause; this is projection only.
|
|
6309
|
+
...v.retriedFrom !== void 0 ? { retriedFrom: projectRetriedFrom(v.retriedFrom) } : {}
|
|
6240
6310
|
});
|
|
6241
6311
|
}
|
|
6242
6312
|
return summaries;
|
|
6243
6313
|
}
|
|
6244
6314
|
function reasoningFields(reasoning) {
|
|
6245
|
-
|
|
6246
|
-
return {
|
|
6247
|
-
reasoning: reasoning.slice(0, MAX_VOTER_REASONING_CHARS),
|
|
6248
|
-
reasoningTruncated: true
|
|
6249
|
-
};
|
|
6315
|
+
const { text, truncated } = clipForRecord(reasoning);
|
|
6316
|
+
return { reasoning: text, ...truncated === true ? { reasoningTruncated: true } : {} };
|
|
6250
6317
|
}
|
|
6251
6318
|
function recordDecisionFor(input) {
|
|
6252
6319
|
return input.resolvedDecision ?? outcomeToDecision(input.result, input.votes, input.errorVoided ?? false);
|
|
@@ -6260,15 +6327,22 @@ function deriveOptionFields(votes, declaredOptions) {
|
|
|
6260
6327
|
return { optionTally: tallied ?? [], optionCoverage: coverageOf(votes) };
|
|
6261
6328
|
}
|
|
6262
6329
|
function recordVersion(optionTally, optionCoverage, panelCoverage, voters, recordLevel) {
|
|
6330
|
+
const voterTier = voterTierOf(voters);
|
|
6331
|
+
if (voterTier === "1.12") return "1.12";
|
|
6263
6332
|
if (recordLevel.errorPolicy !== void 0) return "1.11";
|
|
6264
6333
|
if (recordLevel.ratifiesPr !== void 0) return "1.10";
|
|
6334
|
+
if (voterTier !== void 0) return voterTier;
|
|
6335
|
+
if (panelCoverage !== void 0) return "1.5";
|
|
6336
|
+
if (optionCoverage !== void 0) return "1.4";
|
|
6337
|
+
return optionTally !== void 0 ? "1.3" : "1.2";
|
|
6338
|
+
}
|
|
6339
|
+
function voterTierOf(voters) {
|
|
6340
|
+
if (voters.some((v) => v.retriedFrom !== void 0)) return "1.12";
|
|
6265
6341
|
if (voters.some((v) => v.assignedCli !== void 0 || v.fallback !== void 0)) return "1.9";
|
|
6266
6342
|
if (voters.some((v) => v.model !== void 0 || v.unverifiable === true)) return "1.8";
|
|
6267
6343
|
if (voters.some((v) => v.retried === true)) return "1.7";
|
|
6268
6344
|
if (voters.some((v) => v.reasoning !== void 0)) return "1.6";
|
|
6269
|
-
|
|
6270
|
-
if (optionCoverage !== void 0) return "1.4";
|
|
6271
|
-
return optionTally !== void 0 ? "1.3" : "1.2";
|
|
6345
|
+
return void 0;
|
|
6272
6346
|
}
|
|
6273
6347
|
function panelCoverageOf(votes, always) {
|
|
6274
6348
|
const erroredRoles = votes.filter((v) => v.source === "error").map((v) => v.role);
|
|
@@ -8753,6 +8827,7 @@ export {
|
|
|
8753
8827
|
DEFAULT_VOTE_TIMEOUT_MS,
|
|
8754
8828
|
isRateLimitError,
|
|
8755
8829
|
PersistentOutcomeStore,
|
|
8830
|
+
VoteRecordPrBindingSchema,
|
|
8756
8831
|
isAbsentSeat,
|
|
8757
8832
|
NoAdapterError,
|
|
8758
8833
|
resolveAdapter,
|
|
@@ -8805,7 +8880,6 @@ export {
|
|
|
8805
8880
|
createCorrelationTracker,
|
|
8806
8881
|
seatFallbacks,
|
|
8807
8882
|
panelDiversityOf,
|
|
8808
|
-
VoteRecordPrBindingSchema,
|
|
8809
8883
|
VotingStrategySchema,
|
|
8810
8884
|
ErrorPolicySchema,
|
|
8811
8885
|
VoteThresholdSchema,
|
|
@@ -8827,4 +8901,4 @@ export {
|
|
|
8827
8901
|
CONSENSUS_VOTE_TOOL_SCHEMA,
|
|
8828
8902
|
registerConsensusVoteTool
|
|
8829
8903
|
};
|
|
8830
|
-
//# sourceMappingURL=chunk-
|
|
8904
|
+
//# sourceMappingURL=chunk-3A5BXLPV.js.map
|