github-router 0.3.177 → 0.3.178
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/browser-ext/manifest.json +1 -1
- package/dist/{engine-DOOYh35O.js → engine-D7mUKnIZ.js} +1 -1
- package/dist/lib/tree-sitter-pool/worker.js +1 -1
- package/dist/main.js +5 -5
- package/dist/main.js.map +1 -1
- package/dist/{peer-mcp-personas-BtQi-dF-.js → peer-mcp-personas-B1-1mVPB.js} +136 -47
- package/dist/peer-mcp-personas-B1-1mVPB.js.map +1 -0
- package/package.json +1 -1
- package/dist/peer-mcp-personas-BtQi-dF-.js.map +0 -1
|
@@ -12076,6 +12076,14 @@ var TreeSitterPool = class {
|
|
|
12076
12076
|
* entirely and force the in-process path, rather than churning spawn→crash
|
|
12077
12077
|
* forever. */
|
|
12078
12078
|
crashCount = 0;
|
|
12079
|
+
workersSpawned = 0;
|
|
12080
|
+
/** Test-only observability for crash/respawn assertions. */
|
|
12081
|
+
__workerLifecycleForTest() {
|
|
12082
|
+
return {
|
|
12083
|
+
crashes: this.crashCount,
|
|
12084
|
+
spawned: this.workersSpawned
|
|
12085
|
+
};
|
|
12086
|
+
}
|
|
12079
12087
|
queue = [];
|
|
12080
12088
|
inflight = /* @__PURE__ */ new Map();
|
|
12081
12089
|
constructor() {
|
|
@@ -12123,6 +12131,7 @@ var TreeSitterPool = class {
|
|
|
12123
12131
|
let worker;
|
|
12124
12132
|
try {
|
|
12125
12133
|
worker = new Worker(this.workerPath);
|
|
12134
|
+
this.workersSpawned += 1;
|
|
12126
12135
|
} catch (err) {
|
|
12127
12136
|
consola.debug(`[code_search] tree-sitter worker spawn failed: ${err.message}`);
|
|
12128
12137
|
resolve(null);
|
|
@@ -12225,8 +12234,14 @@ var TreeSitterPool = class {
|
|
|
12225
12234
|
if (!job) break;
|
|
12226
12235
|
pw.busyJobId = job.id;
|
|
12227
12236
|
this.inflight.set(job.id, job);
|
|
12237
|
+
const injectCrash = _testCrashOnceArmed;
|
|
12238
|
+
const reqToPost = injectCrash ? {
|
|
12239
|
+
...job.req,
|
|
12240
|
+
testCrash: true
|
|
12241
|
+
} : job.req;
|
|
12228
12242
|
try {
|
|
12229
|
-
pw.worker.postMessage(
|
|
12243
|
+
pw.worker.postMessage(reqToPost);
|
|
12244
|
+
if (injectCrash) _testCrashOnceArmed = false;
|
|
12230
12245
|
} catch (err) {
|
|
12231
12246
|
consola.debug(`[code_search] tree-sitter worker postMessage failed: ${err.message}`);
|
|
12232
12247
|
this.inflight.delete(job.id);
|
|
@@ -12398,6 +12413,7 @@ function resolveWorkerPath() {
|
|
|
12398
12413
|
}
|
|
12399
12414
|
let _pool = null;
|
|
12400
12415
|
let _shutdownRegistered = false;
|
|
12416
|
+
let _testCrashOnceArmed = false;
|
|
12401
12417
|
/**
|
|
12402
12418
|
* The pool is ON by default for real (non-CI) runs and OFF under CI.
|
|
12403
12419
|
*
|
|
@@ -12650,6 +12666,10 @@ const WALL_TIME_MS = 3e4;
|
|
|
12650
12666
|
* comfortable headroom for ~5-10 files even on cold cache.
|
|
12651
12667
|
*/
|
|
12652
12668
|
const STRUCTURAL_BUDGET_MS = 200;
|
|
12669
|
+
let _structuralBudgetTestOverride = null;
|
|
12670
|
+
function structuralBudgetMs() {
|
|
12671
|
+
return _structuralBudgetTestOverride ?? STRUCTURAL_BUDGET_MS;
|
|
12672
|
+
}
|
|
12653
12673
|
const STRUCTURAL_TOPN_FULL = 50;
|
|
12654
12674
|
const STRUCTURAL_TOPN_FAST = 10;
|
|
12655
12675
|
/**
|
|
@@ -13957,7 +13977,7 @@ async function searchCode(rawInput, externalSignal) {
|
|
|
13957
13977
|
})).filter((e) => e.index >= 0),
|
|
13958
13978
|
workspaceRoot: ws.canonical,
|
|
13959
13979
|
topN,
|
|
13960
|
-
budgetMs:
|
|
13980
|
+
budgetMs: structuralBudgetMs(),
|
|
13961
13981
|
signal: ac.signal
|
|
13962
13982
|
});
|
|
13963
13983
|
structuralOutlines = structural.outlinesByFile;
|
|
@@ -24084,9 +24104,9 @@ function jsonPathPreflightCap(body, scope) {
|
|
|
24084
24104
|
const decision = typeof args.decision === "string" ? args.decision : "";
|
|
24085
24105
|
const optionsRaw = Array.isArray(args.options) ? args.options : [];
|
|
24086
24106
|
const standInContext = typeof args.context === "string" ? args.context : "";
|
|
24087
|
-
if (!decision || optionsRaw.length === 0) return void 0;
|
|
24107
|
+
if (!decision || optionsRaw.length === 0 || !standInContext.trim()) return void 0;
|
|
24088
24108
|
const briefBytes$1 = Buffer.byteLength(decision + JSON.stringify(optionsRaw) + standInContext, "utf8");
|
|
24089
|
-
const STAND_IN_CAP_BYTES =
|
|
24109
|
+
const STAND_IN_CAP_BYTES = 32 * 1024;
|
|
24090
24110
|
if (briefBytes$1 > STAND_IN_CAP_BYTES) return rpcResult(body.id, toolError(`pre-flight rejected: stand_in on a ${briefBytes$1}-byte input is predicted to exceed the JSON tools/call timeout (cap=${STAND_IN_CAP_BYTES} bytes). stand_in runs two sequential voting rounds across three frontier models — wall-clock is typically 2-3 minutes regardless of input size. Send Accept: text/event-stream to use the SSE path which bypasses this cap, or trim the decision/options/context.`));
|
|
24091
24111
|
return;
|
|
24092
24112
|
}
|
|
@@ -28039,12 +28059,15 @@ Respond with ONLY a single JSON object — no prose, no markdown fences, no prea
|
|
|
28039
28059
|
"choice": "<option.id>" | null,
|
|
28040
28060
|
"confidence": <number between 0.0 and 1.0>,
|
|
28041
28061
|
"reasoning": "<one short sentence>",
|
|
28042
|
-
"need_more_info": "<what context is missing, if you cannot decide>"
|
|
28062
|
+
"need_more_info": "<what context is missing, if you cannot decide>",
|
|
28063
|
+
"alternative": "<a concrete unlisted option — ONLY if every provided option is inadequate>"
|
|
28043
28064
|
}
|
|
28044
28065
|
|
|
28045
28066
|
Calibration rules:
|
|
28046
28067
|
- "confidence" reflects how sure you are this is the better option (not how confident you are in your prose). 0.5 = coin flip. 0.9 = clear winner. Be honestly calibrated; the orchestrator weighs your number directly.
|
|
28047
28068
|
- If the question is genuinely under-specified — you'd need information you don't have to choose well — set "choice": null AND populate "need_more_info" with the specific gap. Do NOT guess.
|
|
28069
|
+
- The caller curated these options; default to choosing among them. Only if a provided option is actively harmful, or clearly dominated by an obvious unlisted option, set "choice": null AND put that concrete option in "alternative" (one sentence). This is distinct from "need_more_info" (which is about missing context, not a better option). Prefer choosing over proposing — do not invent an alternative to avoid committing.
|
|
28070
|
+
- On an abstention, populate at most ONE escape channel: "need_more_info" OR "alternative", never both. If both seem to apply, use "need_more_info" — missing context takes precedence, because you can't reliably judge the options inadequate without it.
|
|
28048
28071
|
- One sentence of reasoning. Not a paragraph.
|
|
28049
28072
|
- The other two models will vote independently and you will see their votes in round 2. There is no benefit to anticipating what they'll pick; vote on the merits.
|
|
28050
28073
|
|
|
@@ -28057,16 +28080,19 @@ Same JSON schema as round 1:
|
|
|
28057
28080
|
"choice": "<option.id>" | null,
|
|
28058
28081
|
"confidence": <number between 0.0 and 1.0>,
|
|
28059
28082
|
"reasoning": "<one short sentence>",
|
|
28060
|
-
"need_more_info": "<gap, if any>"
|
|
28083
|
+
"need_more_info": "<gap, if any>",
|
|
28084
|
+
"alternative": "<a concrete unlisted option, if every provided option is inadequate>"
|
|
28061
28085
|
}
|
|
28062
28086
|
|
|
28063
28087
|
Calibration rules:
|
|
28064
28088
|
- You may keep your round-1 vote OR change it. Do NOT change just to agree — agreement is not the goal, the right answer is. Capitulating to peer pressure when you still believe your original choice is better is a failure mode, not a success.
|
|
28065
28089
|
- If a peer's reasoning identifies a consideration you missed or weighed wrong, update freely. The blind round was the anti-anchor mechanism; this round is where genuine evidence can move you.
|
|
28066
28090
|
- If round 1 left you genuinely uncertain and peer reasoning hasn't resolved it, "choice": null is still the honest answer.
|
|
28091
|
+
- Keep using "alternative" only when every provided option is inadequate (choice null); it is not a way to dodge a decision the options already support.
|
|
28092
|
+
- On an abstention, populate at most ONE escape channel: "need_more_info" OR "alternative", never both. If both seem to apply, use "need_more_info" (missing context takes precedence).
|
|
28067
28093
|
|
|
28068
28094
|
Output ONLY the JSON object.`;
|
|
28069
|
-
const RETRY_PROMPT_SUFFIX = `\n\nYour previous response was not valid JSON matching the schema. Respond with ONLY the JSON object — no preamble, no markdown fences, no closing remarks. Schema reminder: {"choice": "<id>" | null, "confidence": 0.0-1.0, "reasoning": "<one sentence>", "need_more_info": "<gap, if any>"}`;
|
|
28095
|
+
const RETRY_PROMPT_SUFFIX = `\n\nYour previous response was not valid JSON matching the schema. Respond with ONLY the JSON object — no preamble, no markdown fences, no closing remarks. Schema reminder: {"choice": "<id>" | null, "confidence": 0.0-1.0, "reasoning": "<one sentence>", "need_more_info": "<gap, if any>", "alternative": "<unlisted option, if any>"}`;
|
|
28070
28096
|
/**
|
|
28071
28097
|
* Run the two-round stand-in protocol. Returns a structured verdict
|
|
28072
28098
|
* envelope. Throws only on systemic failure (e.g., all three upstream
|
|
@@ -28074,71 +28100,66 @@ const RETRY_PROMPT_SUFFIX = `\n\nYour previous response was not valid JSON match
|
|
|
28074
28100
|
* `VoteFailure` entries in the result.
|
|
28075
28101
|
*/
|
|
28076
28102
|
async function runStandIn(input, signal) {
|
|
28103
|
+
const validIds = new Set(input.options.map((o) => o.id));
|
|
28077
28104
|
const r1UserText = buildRound1UserText(input);
|
|
28078
|
-
const r1 = await Promise.all(STAND_IN_MODELS.map((cfg) => callAndParse(cfg, SYSTEM_PROMPT_R1, r1UserText, signal)));
|
|
28105
|
+
const r1 = await Promise.all(STAND_IN_MODELS.map((cfg) => callAndParse(cfg, SYSTEM_PROMPT_R1, r1UserText, validIds, signal)));
|
|
28079
28106
|
const successfulR1 = r1.filter((r) => isVote(r.vote));
|
|
28080
|
-
|
|
28081
|
-
|
|
28082
|
-
return {
|
|
28083
|
-
verdict: "need_more_info",
|
|
28084
|
-
recommendation: null,
|
|
28085
|
-
confidence: 0,
|
|
28086
|
-
votes: voteRecord(r1, null),
|
|
28087
|
-
notes: `All three models reported they need more context to decide:\n${gaps}`
|
|
28088
|
-
};
|
|
28089
|
-
}
|
|
28107
|
+
const nmiR1 = gapAbstainVerdict(successfulR1, r1, null);
|
|
28108
|
+
if (nmiR1) return nmiR1;
|
|
28090
28109
|
const r1Decision = aggregateVotes(successfulR1);
|
|
28091
|
-
if (r1Decision.verdict === "consensus" && r1Decision.meanConfidence >= .8) return {
|
|
28110
|
+
if (r1Decision.verdict === "consensus" && r1Decision.meanConfidence >= .8) return withDerivedNotes({
|
|
28092
28111
|
verdict: "consensus",
|
|
28093
28112
|
recommendation: r1Decision.winner,
|
|
28094
28113
|
confidence: round2(r1Decision.meanConfidence),
|
|
28095
28114
|
votes: voteRecord(r1, null),
|
|
28096
28115
|
notes: `All three models picked ${r1Decision.winner} in round 1 with high confidence (skipped round 2).`
|
|
28097
|
-
};
|
|
28098
|
-
if (successfulR1.length < 2) return {
|
|
28116
|
+
}, r1, null);
|
|
28117
|
+
if (successfulR1.length < 2) return withDerivedNotes({
|
|
28099
28118
|
verdict: "no_consensus",
|
|
28100
28119
|
recommendation: null,
|
|
28101
28120
|
confidence: 0,
|
|
28102
28121
|
votes: voteRecord(r1, null),
|
|
28103
28122
|
notes: `Only ${successfulR1.length} of 3 models returned a parseable round-1 vote; insufficient signal to run round 2.`
|
|
28104
|
-
};
|
|
28123
|
+
}, r1, null);
|
|
28105
28124
|
const r2UserTextBase = buildRound2UserTextBase(input, r1);
|
|
28106
|
-
const r2 = await Promise.all(STAND_IN_MODELS.map((cfg) => callAndParse(cfg, SYSTEM_PROMPT_R2, r2UserTextBase + `\n\nYou are ${cfg.key}. Reconsider and vote.`, signal)));
|
|
28125
|
+
const r2 = await Promise.all(STAND_IN_MODELS.map((cfg) => callAndParse(cfg, SYSTEM_PROMPT_R2, r2UserTextBase + `\n\nYou are ${cfg.key}. Reconsider and vote.`, validIds, signal)));
|
|
28107
28126
|
const successfulR2 = r2.filter((r) => isVote(r.vote));
|
|
28108
|
-
if (successfulR2.length < 2) return {
|
|
28127
|
+
if (successfulR2.length < 2) return withDerivedNotes({
|
|
28109
28128
|
verdict: "no_consensus",
|
|
28110
28129
|
recommendation: null,
|
|
28111
28130
|
confidence: 0,
|
|
28112
28131
|
votes: voteRecord(r1, r2),
|
|
28113
28132
|
notes: `Only ${successfulR2.length} of 3 models returned a parseable round-2 vote; deferring to user.`
|
|
28114
|
-
};
|
|
28133
|
+
}, r1, r2);
|
|
28134
|
+
const nmiR2 = gapAbstainVerdict(successfulR2, r1, r2);
|
|
28135
|
+
if (nmiR2) return nmiR2;
|
|
28115
28136
|
const r2Decision = aggregateVotes(successfulR2);
|
|
28116
|
-
if (r2Decision.verdict === "consensus") return {
|
|
28137
|
+
if (r2Decision.verdict === "consensus") return withDerivedNotes({
|
|
28117
28138
|
verdict: "consensus",
|
|
28118
28139
|
recommendation: r2Decision.winner,
|
|
28119
28140
|
confidence: round2(r2Decision.meanConfidence),
|
|
28120
28141
|
votes: voteRecord(r1, r2),
|
|
28121
28142
|
notes: `All three models picked ${r2Decision.winner} in round 2.`
|
|
28122
|
-
};
|
|
28143
|
+
}, r1, r2);
|
|
28123
28144
|
if (r2Decision.verdict === "majority") {
|
|
28124
28145
|
const dissenters = successfulR2.filter((r) => r.vote.choice !== r2Decision.winner).map((r) => `${r.key} picked ${r.vote.choice ?? "abstain"} (${r.vote.reasoning})`).join("; ");
|
|
28125
|
-
return {
|
|
28146
|
+
return withDerivedNotes({
|
|
28126
28147
|
verdict: "majority",
|
|
28127
28148
|
recommendation: r2Decision.winner,
|
|
28128
28149
|
confidence: round2(r2Decision.meanConfidence),
|
|
28129
28150
|
votes: voteRecord(r1, r2),
|
|
28130
28151
|
notes: `Majority (2 of 3) picked ${r2Decision.winner}. Dissent: ${dissenters}.`
|
|
28131
|
-
};
|
|
28152
|
+
}, r1, r2);
|
|
28132
28153
|
}
|
|
28133
|
-
return {
|
|
28154
|
+
return withDerivedNotes({
|
|
28134
28155
|
verdict: "no_consensus",
|
|
28135
28156
|
recommendation: null,
|
|
28136
28157
|
confidence: 0,
|
|
28137
28158
|
votes: voteRecord(r1, r2),
|
|
28138
28159
|
notes: `Models did not converge in round 2 (votes split). Defer to user.`
|
|
28139
|
-
};
|
|
28160
|
+
}, r1, r2);
|
|
28140
28161
|
}
|
|
28141
|
-
async function callAndParse(cfg, instructions, userText, signal) {
|
|
28162
|
+
async function callAndParse(cfg, instructions, userText, validIds, signal) {
|
|
28142
28163
|
const model = cfg.key === "gpt-5.6-sol" ? resolveOpenAiFrontier() ?? cfg.model : cfg.model;
|
|
28143
28164
|
let raw;
|
|
28144
28165
|
try {
|
|
@@ -28159,7 +28180,7 @@ async function callAndParse(cfg, instructions, userText, signal) {
|
|
|
28159
28180
|
}
|
|
28160
28181
|
};
|
|
28161
28182
|
}
|
|
28162
|
-
const first = tryParseVote(raw);
|
|
28183
|
+
const first = tryParseVote(raw, validIds);
|
|
28163
28184
|
if (first.ok) return {
|
|
28164
28185
|
key: cfg.key,
|
|
28165
28186
|
vote: first.vote
|
|
@@ -28183,7 +28204,7 @@ async function callAndParse(cfg, instructions, userText, signal) {
|
|
|
28183
28204
|
}
|
|
28184
28205
|
};
|
|
28185
28206
|
}
|
|
28186
|
-
const second = tryParseVote(retryRaw);
|
|
28207
|
+
const second = tryParseVote(retryRaw, validIds);
|
|
28187
28208
|
if (second.ok) return {
|
|
28188
28209
|
key: cfg.key,
|
|
28189
28210
|
vote: second.vote
|
|
@@ -28197,7 +28218,7 @@ async function callAndParse(cfg, instructions, userText, signal) {
|
|
|
28197
28218
|
}
|
|
28198
28219
|
};
|
|
28199
28220
|
}
|
|
28200
|
-
function tryParseVote(raw) {
|
|
28221
|
+
function tryParseVote(raw, validIds) {
|
|
28201
28222
|
if (!raw || !raw.trim()) return {
|
|
28202
28223
|
ok: false,
|
|
28203
28224
|
error: "empty response"
|
|
@@ -28225,11 +28246,16 @@ function tryParseVote(raw) {
|
|
|
28225
28246
|
error: "parsed value is not an object"
|
|
28226
28247
|
};
|
|
28227
28248
|
const obj = parsed;
|
|
28228
|
-
const
|
|
28229
|
-
if (
|
|
28249
|
+
const rawChoice = obj.choice === null ? null : typeof obj.choice === "string" && obj.choice.length > 0 ? obj.choice : void 0;
|
|
28250
|
+
if (rawChoice === void 0) return {
|
|
28230
28251
|
ok: false,
|
|
28231
28252
|
error: "missing or invalid 'choice' field (string or null required)"
|
|
28232
28253
|
};
|
|
28254
|
+
if (rawChoice !== null && !validIds.has(rawChoice)) return {
|
|
28255
|
+
ok: false,
|
|
28256
|
+
error: "'choice' must be one of the provided option ids or null"
|
|
28257
|
+
};
|
|
28258
|
+
const choice = rawChoice;
|
|
28233
28259
|
const confidenceRaw = obj.confidence;
|
|
28234
28260
|
const confidence = typeof confidenceRaw === "number" && Number.isFinite(confidenceRaw) ? Math.max(0, Math.min(1, confidenceRaw)) : void 0;
|
|
28235
28261
|
if (confidence === void 0) return {
|
|
@@ -28241,13 +28267,15 @@ function tryParseVote(raw) {
|
|
|
28241
28267
|
ok: false,
|
|
28242
28268
|
error: "missing or empty 'reasoning' field"
|
|
28243
28269
|
};
|
|
28270
|
+
const needMoreInfo = choice === null && typeof obj.need_more_info === "string" && obj.need_more_info.trim().length > 0 ? obj.need_more_info.trim() : void 0;
|
|
28244
28271
|
return {
|
|
28245
28272
|
ok: true,
|
|
28246
28273
|
vote: {
|
|
28247
28274
|
choice,
|
|
28248
28275
|
confidence,
|
|
28249
28276
|
reasoning,
|
|
28250
|
-
needMoreInfo
|
|
28277
|
+
needMoreInfo,
|
|
28278
|
+
alternative: choice === null && !needMoreInfo && typeof obj.alternative === "string" && obj.alternative.trim().length > 0 ? obj.alternative.trim() : void 0
|
|
28251
28279
|
}
|
|
28252
28280
|
};
|
|
28253
28281
|
}
|
|
@@ -28310,13 +28338,70 @@ function buildRound2UserTextBase(input, r1) {
|
|
|
28310
28338
|
for (const r of r1) if (isVote(r.vote)) {
|
|
28311
28339
|
const choiceText = r.vote.choice === null ? "abstain" : r.vote.choice;
|
|
28312
28340
|
const gapText = r.vote.needMoreInfo ? ` (needs: ${r.vote.needMoreInfo})` : "";
|
|
28313
|
-
|
|
28341
|
+
const altText = r.vote.alternative ? ` [proposed unlisted alternative: ${r.vote.alternative}]` : "";
|
|
28342
|
+
summaries.push(`- ${r.key} picked ${choiceText}, confidence ${r.vote.confidence.toFixed(2)}, reasoning: ${r.vote.reasoning}${gapText}${altText}`);
|
|
28314
28343
|
} else summaries.push(`- ${r.key} did not return a valid round-1 vote (${r.vote.error}).`);
|
|
28315
28344
|
return base + "\n" + summaries.join("\n");
|
|
28316
28345
|
}
|
|
28317
28346
|
function isVote(v) {
|
|
28318
28347
|
return !("error" in v);
|
|
28319
28348
|
}
|
|
28349
|
+
function gapAbstainVerdict(successful, r1, r2) {
|
|
28350
|
+
const gapVotes = successful.filter((r) => r.vote.choice === null && r.vote.needMoreInfo);
|
|
28351
|
+
if (gapVotes.length < 2) return null;
|
|
28352
|
+
const gaps = gapVotes.map((r) => `- ${r.key}: ${r.vote.needMoreInfo}`).join("\n");
|
|
28353
|
+
const header = gapVotes.length === STAND_IN_MODELS.length ? "All three models reported they need more context to decide:" : `${gapVotes.length} of 3 models reported they need more context to decide:`;
|
|
28354
|
+
return withDerivedNotes({
|
|
28355
|
+
verdict: "need_more_info",
|
|
28356
|
+
recommendation: null,
|
|
28357
|
+
confidence: 0,
|
|
28358
|
+
votes: voteRecord(r1, r2),
|
|
28359
|
+
notes: `${header}\n${gaps}`
|
|
28360
|
+
}, r1, r2);
|
|
28361
|
+
}
|
|
28362
|
+
/**
|
|
28363
|
+
* Freshest parsed vote per model (round 2 if it parsed, else round 1) — the
|
|
28364
|
+
* basis for deriving alternative / gap notes without double-counting a model
|
|
28365
|
+
* across rounds.
|
|
28366
|
+
*/
|
|
28367
|
+
function freshestVotes(r1, r2) {
|
|
28368
|
+
const out = [];
|
|
28369
|
+
for (const cfg of STAND_IN_MODELS) {
|
|
28370
|
+
const r2Entry = r2?.find((r) => r.key === cfg.key);
|
|
28371
|
+
const r1Entry = r1.find((r) => r.key === cfg.key);
|
|
28372
|
+
const vote = r2Entry && isVote(r2Entry.vote) ? r2Entry.vote : r1Entry && isVote(r1Entry.vote) ? r1Entry.vote : null;
|
|
28373
|
+
if (vote) out.push({
|
|
28374
|
+
key: cfg.key,
|
|
28375
|
+
vote
|
|
28376
|
+
});
|
|
28377
|
+
}
|
|
28378
|
+
return out;
|
|
28379
|
+
}
|
|
28380
|
+
/**
|
|
28381
|
+
* Append derived notes to a verdict WITHOUT touching the verdict / tally:
|
|
28382
|
+
* - panel-proposed unlisted `alternative`s (surfaced on every verdict);
|
|
28383
|
+
* - partial missing-context gaps (surfaced only on no_consensus — the
|
|
28384
|
+
* dedicated need_more_info path already lists its own gaps).
|
|
28385
|
+
* Purely additive to `notes`; never changes verdict / recommendation / isError.
|
|
28386
|
+
* This is what lets the alternative + partial-gap signals ride along while the
|
|
28387
|
+
* abstain and blind-R1 invariants stay untouched.
|
|
28388
|
+
*/
|
|
28389
|
+
function withDerivedNotes(result, r1, r2) {
|
|
28390
|
+
const fresh = freshestVotes(r1, r2);
|
|
28391
|
+
const extras = [];
|
|
28392
|
+
const alts = fresh.filter((v) => v.vote.alternative);
|
|
28393
|
+
if (alts.length > 0) extras.push("The panel also flagged unlisted option(s):\n" + alts.map((v) => `- ${v.key}: ${v.vote.alternative}`).join("\n"));
|
|
28394
|
+
if (result.verdict === "no_consensus") {
|
|
28395
|
+
const gaps = fresh.filter((v) => v.vote.choice === null && v.vote.needMoreInfo);
|
|
28396
|
+
if (gaps.length > 0) extras.push("Some models cited missing context:\n" + gaps.map((v) => `- ${v.key}: ${v.vote.needMoreInfo}`).join("\n"));
|
|
28397
|
+
}
|
|
28398
|
+
if (extras.length === 0) return result;
|
|
28399
|
+
const notes = [result.notes, ...extras].filter(Boolean).join("\n\n");
|
|
28400
|
+
return {
|
|
28401
|
+
...result,
|
|
28402
|
+
notes
|
|
28403
|
+
};
|
|
28404
|
+
}
|
|
28320
28405
|
function voteRecord(r1, r2) {
|
|
28321
28406
|
const record = {};
|
|
28322
28407
|
for (const cfg of STAND_IN_MODELS) {
|
|
@@ -31289,10 +31374,14 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
31289
31374
|
toolNameHttp: "stand_in",
|
|
31290
31375
|
group: "decide",
|
|
31291
31376
|
capability: "stand_in",
|
|
31292
|
-
description: "Three-lab away-mode decision tiebreak advisor for moments when the user is unavailable and the agent is stuck between two or more concrete options. It polls gpt-5.6-sol, Opus 4.7, and gemini-3.1-pro-preview across blind and informed voting rounds, then returns a ranked-choice verdict such as consensus, majority, no_consensus, or need_more_info. Use when work would otherwise halt on a bounded choice the user would normally make. Not for code review, open-ended exploration, single-model second opinions, or bypassing confirmation on irreversible actions such as push, delete, drop, or deploy; use peer-review-coordinator or the individual critics for review and still ask the user for destructive actions.",
|
|
31377
|
+
description: "Three-lab away-mode decision tiebreak advisor for moments when the user is unavailable and the agent is stuck between two or more concrete options. It polls gpt-5.6-sol, Opus 4.7, and gemini-3.1-pro-preview across blind and informed voting rounds, then returns a ranked-choice verdict such as consensus, majority, no_consensus, or need_more_info. Use when work would otherwise halt on a bounded choice the user would normally make. If every provided option is inadequate, the panel may flag a concrete better unlisted option in `notes` so you can re-invoke with a revised set. The three panel models are cold-start — no repo, transcript, or memory access — and see only your decision, options, and context, so the `context` argument must carry all the background they need to judge. Not for code review, open-ended exploration, single-model second opinions, or bypassing confirmation on irreversible actions such as push, delete, drop, or deploy; use peer-review-coordinator or the individual critics for review and still ask the user for destructive actions.",
|
|
31293
31378
|
inputSchema: {
|
|
31294
31379
|
type: "object",
|
|
31295
|
-
required: [
|
|
31380
|
+
required: [
|
|
31381
|
+
"decision",
|
|
31382
|
+
"options",
|
|
31383
|
+
"context"
|
|
31384
|
+
],
|
|
31296
31385
|
additionalProperties: false,
|
|
31297
31386
|
properties: {
|
|
31298
31387
|
decision: {
|
|
@@ -31303,7 +31392,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
31303
31392
|
type: "array",
|
|
31304
31393
|
minItems: 2,
|
|
31305
31394
|
maxItems: 6,
|
|
31306
|
-
description: "2-6 concrete options for the panel to vote on.
|
|
31395
|
+
description: "2-6 concrete options curated by the caller for the panel to vote on. The panel may surface a gated unlisted alternative in `notes`, but does not replace the caller's option set. The verdict cites the chosen option by `id`.",
|
|
31307
31396
|
items: {
|
|
31308
31397
|
type: "object",
|
|
31309
31398
|
required: ["id", "summary"],
|
|
@@ -31326,7 +31415,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
|
|
|
31326
31415
|
},
|
|
31327
31416
|
context: {
|
|
31328
31417
|
type: "string",
|
|
31329
|
-
description: "
|
|
31418
|
+
description: "REQUIRED. The three panel models are cold-start: no access to your repository, prior transcript, or memory — they see ONLY this decision + options + context. Include everything needed to decide well: the constraints that matter, the relevant code or excerpts, prior decisions not to relitigate, and what a good outcome looks like. Thin context yields a weak verdict. (On the JSON transport a ~32KB size guard applies; the SSE transport has no such limit.)"
|
|
31330
31419
|
}
|
|
31331
31420
|
}
|
|
31332
31421
|
},
|
|
@@ -31663,11 +31752,11 @@ async function runStandInToolCall(args, signal) {
|
|
|
31663
31752
|
detail
|
|
31664
31753
|
});
|
|
31665
31754
|
}
|
|
31666
|
-
const context =
|
|
31667
|
-
if (context
|
|
31755
|
+
const context = typeof args.context === "string" ? args.context : "";
|
|
31756
|
+
if (!context.trim()) return {
|
|
31668
31757
|
content: [{
|
|
31669
31758
|
type: "text",
|
|
31670
|
-
text: "stand_in: arguments.context
|
|
31759
|
+
text: "stand_in: arguments.context is required (non-empty string). The panel is cold-start and sees only decision + options + context; include the constraints, relevant code, and success criteria needed to decide."
|
|
31671
31760
|
}],
|
|
31672
31761
|
isError: true
|
|
31673
31762
|
};
|
|
@@ -31684,4 +31773,4 @@ async function runStandInToolCall(args, signal) {
|
|
|
31684
31773
|
|
|
31685
31774
|
//#endregion
|
|
31686
31775
|
export { isAdvisorRequested as $, cacheCopilotVersion as $t, liveExec as A, provisionBrowserAssets as At, withNoOutputRetry as B, DEFAULT_CODEX_MODEL as Bt, fileReviewDebounce as C, resolveMcpToolTimeoutMs as Ct, stopGateEnabledForRepo as D, MAX_RESPONSE_BODY_BYTES as Dt, repoRoot as E, createChatCompletions as Et, IMPLEMENT_DEFAULT_MODEL as F, shouldUseInsecureTls as Ft, vscodeRipgrepPath as G, generateRandomPort as Gt, buildToolbeltAwareness as H, DEFAULT_PORT as Ht, PLAN_DEFAULT_MODEL as I, ArtifactClient as It, searchWeb as J, withInstallLock as Jt, TOOLBELT_TOOLS$1 as K, pickClaudeDefault as Kt, REVIEW_DEFAULT_MODEL as L, collapsePathKeys as Lt, BROWSE_DEFAULT_MODEL as M, provisionAndIndexColbert as Mt, DEFAULT_MODEL as N, extractTarGzMember as Nt, stopReviewStateDir as O, readResponseBodyCapped as Ot, EXPLORE_DEFAULT_MODEL as P, extractZipMember as Pt, injectAdvisorTool as Q, tryRefreshAndRetry as Qt, appendPlanReminder as R, toolbeltPathOverride as Rt, fileLastPromptStore as S, assembleResponsesPayload as St, repoFingerprint as T, createResponses as Tt, toolbeltEnabled as U, UPSTREAM_FETCH_TIMEOUT_MS as Ut, availableToolCommands as V, DEFAULT_CODEX_MODEL_FALLBACKS as Vt, toolbeltSkipSet as W, UPSTREAM_INACTIVITY_TIMEOUT_MS as Wt, ADVISOR_TOOL_INSTRUCTIONS as X, setupGitHubAgentToken as Xt, ADVISOR_INTERNAL_TOOL_NAME as Y, setupCopilotToken as Yt, buildAdvisorStream as Z, setupGitHubToken as Zt, stopGateId as _, workerToolsEnabled as _t, buildPeerAwarenessSnippet as a, resolveModel as an, relayAnthropicStream as at, fileBaselineStore as b, createMessages as bt, buildArtifactOpenHookCommand as c, fetchWithTransientRetry as cn, agentToolsEnabled as ct, captureLaunchBaseline as d, GITHUB_API_BASE_URL as dn, browserCompoundToolsEnabled as dt, cacheModels as en, buildAnthropicErrorEvent as et, decideStopHook as f, copilotBaseUrl as fn, browserToolsEnabled as ft, stopGateDisabled as g, standInToolEnabled as gt, launchBaselineKey as h, state as hn, nativeSubagentModel as ht, buildAgentPrompt as i, resolveCodexModel as in, readIteratorWithTimeout as it, resolveSealedGate as j, hasSupportedBrowserInstalled as jt, trustRepo as k, parseJsonOrDiagnose as kt, buildSessionBindHookCommand as l, HTTPError as ln, artifactToolsEnabled as lt, injectStopHookIntoSettingsFile as m, githubHeaders as mn, geminiAvailable as mt, MCP_GROUPS as n, filterBetaHeader as nn, isControllerClosedError as nt, buildPeerAwarenessSummary as o, sleep as on, handleMcpDelete as ot, fileBlockBudget as p, copilotHeaders as pn, fleetToolsEnabled as pt, assetFor as q, getPackageVersion as qt, assertMcpToolSurfaceConsistent as r, isNullish as rn, logStreamError as rt, personasFor as s, getModels as sn, handleMcpPost as st, GROUP_META as t, cacheVSCodeVersion as tn, buildOpenAIErrorEvent as tt, buildStopHookCommand as u, forwardError as un, browseAgentEnabled as ut, stopGatePlanMode as v, shimDefaultsToXhigh as vt, isSubagentContext as w, pickEndpoint as wt, fileFindingsStore as x, getTokenCount as xt, stopReviewEnabled as y, countTokens as yt, runWorkerAgent as z, DEFAULT_CLAUDE_MODEL_FALLBACKS as zt };
|
|
31687
|
-
//# sourceMappingURL=peer-mcp-personas-
|
|
31776
|
+
//# sourceMappingURL=peer-mcp-personas-B1-1mVPB.js.map
|