aiki-cli 0.3.1 → 0.3.2
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/CHANGELOG.md +12 -5
- package/README.md +9 -11
- package/dist/bench/idea-v3-rating.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/run.js +1 -1
- package/dist/council/view.js +52 -12
- package/dist/orchestration/context.js +3 -3
- package/dist/orchestration/decision-dossier.js +417 -88
- package/dist/orchestration/decision-graph.js +31 -0
- package/dist/orchestration/legacy-idea-adapter.js +3 -0
- package/dist/orchestration/modes.js +15 -9
- package/dist/orchestration/preflight.js +17 -3
- package/dist/orchestration/quick-analysis.js +21 -4
- package/dist/orchestration/stages/s10-render.js +167 -79
- package/dist/orchestration/stages/s4-analyze.js +3 -1
- package/dist/orchestration/stages/s6-positions.js +18 -0
- package/dist/orchestration/stages/s7-decision-graph.js +3 -0
- package/dist/orchestration/stages/s8-verify.js +26 -9
- package/dist/orchestration/stages/s8b-rebuttal.js +11 -4
- package/dist/orchestration/stages/s9-judge.js +36 -13
- package/dist/orchestration/stages/s9b-plan.js +192 -42
- package/dist/schemas/index.js +67 -3
- package/dist/skills/idea-refinement/analyst.md +5 -5
- package/dist/skills/idea-refinement/chair.md +18 -0
- package/dist/skills/idea-refinement/economics-delivery.md +11 -0
- package/dist/skills/idea-refinement/market-adoption.md +12 -0
- package/dist/skills/idea-refinement/planner.md +25 -19
- package/dist/skills/idea-refinement/rebuttal.md +15 -0
- package/dist/skills/idea-refinement/verifier.md +17 -0
- package/dist/workflows/idea-refinement.js +42 -14
- package/package.json +1 -1
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
// S6 — preserve validated analyst submissions for graph compilation. No lexical merging: positions
|
|
2
2
|
// keep their original text and are grouped only by stable references in S7.
|
|
3
|
+
/** A surviving scout seat with little output or evidence is weak. ponytail: thresholds are blunt on
|
|
4
|
+
* purpose; raise them only with benchmark evidence. */
|
|
5
|
+
export function detectWeakSeat(positions, mode) {
|
|
6
|
+
if (mode === 'quick')
|
|
7
|
+
return [];
|
|
8
|
+
const seats = new Map();
|
|
9
|
+
for (const position of positions) {
|
|
10
|
+
const provider = position.id.split('/')[0].replace(/-coverage-fill$/, '');
|
|
11
|
+
const seat = seats.get(provider) ?? { positions: 0, evidenced: 0 };
|
|
12
|
+
seat.positions += 1;
|
|
13
|
+
if (position.evidence_ids?.length)
|
|
14
|
+
seat.evidenced += 1;
|
|
15
|
+
seats.set(provider, seat);
|
|
16
|
+
}
|
|
17
|
+
if (seats.size < 2)
|
|
18
|
+
return [];
|
|
19
|
+
return [...seats].filter(([, seat]) => seat.positions < 3 || seat.evidenced / seat.positions < 0.5).map(([provider]) => provider);
|
|
20
|
+
}
|
|
3
21
|
export function collectPositions(seats) {
|
|
4
22
|
return seats.map((seat) => ({ provider: seat.provider, source_id: seat.sample ?? seat.provider, submission: seat.output }));
|
|
5
23
|
}
|
|
@@ -4,6 +4,7 @@ import { compileDecisionGraph, coverageHoleQueue, positionId } from '../decision
|
|
|
4
4
|
import { IdeaRoleOutputModel } from '../../schemas/index.js';
|
|
5
5
|
import { isFatal } from '../context.js';
|
|
6
6
|
import { jsonCall } from '../jsonStage.js';
|
|
7
|
+
import { detectWeakSeat } from './s6-positions.js';
|
|
7
8
|
import { overlapCoefficient, tokenize } from '../cluster.js';
|
|
8
9
|
const GROUP_SIMILARITY = 0.8;
|
|
9
10
|
export function buildCoverageFillPrompt(task, holes) {
|
|
@@ -71,6 +72,8 @@ export async function s7DecisionGraph(ctx, submissions, rubric, task = '') {
|
|
|
71
72
|
const completed = await fillCoverage(ctx, submissions, rubric, task);
|
|
72
73
|
const groups = deterministicClaimGroups(completed);
|
|
73
74
|
const graph = compileDecisionGraph(completed, rubric, groups);
|
|
75
|
+
if (detectWeakSeat(graph.positions, ctx.mode ?? 'council').length)
|
|
76
|
+
ctx.addFlag('weak_seat');
|
|
74
77
|
await ctx.writer.writeJson('decision-graph', graph);
|
|
75
78
|
return graph;
|
|
76
79
|
}
|
|
@@ -4,6 +4,7 @@ import { selectEscalations } from '../decision-graph.js';
|
|
|
4
4
|
import { ClaimVerificationSet } from '../../schemas/index.js';
|
|
5
5
|
import { isFatal, StageError } from '../context.js';
|
|
6
6
|
import { jsonCall } from '../jsonStage.js';
|
|
7
|
+
import { loadSkill } from '../skills.js';
|
|
7
8
|
const S8_PROMPT = `ROLE: Independent verifier. Check each anonymous decision claim below against the
|
|
8
9
|
provided evidence cards and deterministic calculation checks. Output ONLY JSON:
|
|
9
10
|
{"verifications": [{"claim_id": "<G-id>", "status": "VERIFIED|PARTIAL|CONTRADICTED|UNVERIFIABLE",
|
|
@@ -12,8 +13,21 @@ provided evidence cards and deterministic calculation checks. Output ONLY JSON:
|
|
|
12
13
|
VERIFIED = the proposition is supported. CONTRADICTED = it is refuted. PARTIAL = evidence is mixed or
|
|
13
14
|
incomplete. UNVERIFIABLE = the supplied sources cannot decide. Cite only supplied evidence IDs. Model
|
|
14
15
|
knowledge cannot verify a current, numeric, legal, medical, financial, market, or regulatory fact.
|
|
15
|
-
Judge each item independently; no verdict quota. JSON only.
|
|
16
|
+
Judge each item independently; no verdict quota. JSON only.{{SKILL}}
|
|
16
17
|
ITEMS: {{ITEMS_JSON}}`;
|
|
18
|
+
export function selectVerificationTargets(claims, max) {
|
|
19
|
+
return claims
|
|
20
|
+
.map((claim, index) => ({ claim, index }))
|
|
21
|
+
.sort((left, right) => Number(right.claim.nature === 'FACTUAL') - Number(left.claim.nature === 'FACTUAL') || left.index - right.index)
|
|
22
|
+
.slice(0, max)
|
|
23
|
+
.map(({ claim }) => claim);
|
|
24
|
+
}
|
|
25
|
+
export function selectVerificationEscalations(graph, max = 8) {
|
|
26
|
+
const candidates = selectEscalations(graph, { max: graph.claims.length });
|
|
27
|
+
const byId = new Map(candidates.map((candidate) => [candidate.claim_id, candidate]));
|
|
28
|
+
const claims = candidates.map((candidate) => graph.claims.find((claim) => claim.id === candidate.claim_id));
|
|
29
|
+
return selectVerificationTargets(claims, max).map((claim) => byId.get(claim.id));
|
|
30
|
+
}
|
|
17
31
|
function evidenceIdsForClaim(graph, claimId) {
|
|
18
32
|
const positionById = new Map(graph.positions.map((position) => [position.id, position]));
|
|
19
33
|
const claim = graph.claims.find((item) => item.id === claimId);
|
|
@@ -25,12 +39,12 @@ function evidenceIdsForClaim(graph, claimId) {
|
|
|
25
39
|
.flatMap((calculation) => calculation.inputs.flatMap((input) => input.evidence_ids));
|
|
26
40
|
return new Set([...positionEvidence, ...calculationEvidence]);
|
|
27
41
|
}
|
|
28
|
-
function verifierInput(graph) {
|
|
42
|
+
function verifierInput(graph, skill = '') {
|
|
29
43
|
const positionById = new Map(graph.positions.map((position) => [position.id, position]));
|
|
30
44
|
const evidenceRefs = new Map(graph.evidence.map((evidence, index) => [`E${index + 1}`, evidence.id]));
|
|
31
45
|
const aliasByEvidence = new Map([...evidenceRefs].map(([alias, id]) => [id, alias]));
|
|
32
46
|
const evidenceById = new Map(graph.evidence.map((evidence) => [evidence.id, evidence]));
|
|
33
|
-
const items =
|
|
47
|
+
const items = selectVerificationEscalations(graph).map((escalation) => {
|
|
34
48
|
const claim = graph.claims.find((item) => item.id === escalation.claim_id);
|
|
35
49
|
const linkedEvidenceIds = evidenceIdsForClaim(graph, claim.id);
|
|
36
50
|
return {
|
|
@@ -64,13 +78,16 @@ function verifierInput(graph) {
|
|
|
64
78
|
evidence_hole: graph.holes.evidence.find((hole) => hole.claim_id === claim.id)?.reason,
|
|
65
79
|
};
|
|
66
80
|
});
|
|
67
|
-
|
|
81
|
+
const prompt = S8_PROMPT
|
|
82
|
+
.replace('{{SKILL}}', skill ? `\n\n${skill}` : '')
|
|
83
|
+
.replace('{{ITEMS_JSON}}', JSON.stringify(items, null, 2));
|
|
84
|
+
return { prompt, evidenceRefs };
|
|
68
85
|
}
|
|
69
|
-
export function buildVerifierPrompt(graph) {
|
|
70
|
-
return verifierInput(graph).prompt;
|
|
86
|
+
export function buildVerifierPrompt(graph, skill = '') {
|
|
87
|
+
return verifierInput(graph, skill).prompt;
|
|
71
88
|
}
|
|
72
89
|
/** Validate every S8 claim/evidence reference before the chair can see it. */
|
|
73
|
-
export function claimVerificationRefIssues(graph, verifications, expectedIds =
|
|
90
|
+
export function claimVerificationRefIssues(graph, verifications, expectedIds = selectVerificationEscalations(graph).map((item) => item.claim_id)) {
|
|
74
91
|
const expected = new Set(expectedIds);
|
|
75
92
|
const evidence = new Map(graph.evidence.map((item) => [item.id, item]));
|
|
76
93
|
const seen = new Set();
|
|
@@ -111,7 +128,7 @@ export function claimVerificationRefIssues(graph, verifications, expectedIds = s
|
|
|
111
128
|
return issues;
|
|
112
129
|
}
|
|
113
130
|
export async function s8Verify(ctx, graph) {
|
|
114
|
-
const escalations =
|
|
131
|
+
const escalations = selectVerificationEscalations(graph);
|
|
115
132
|
if (escalations.length === 0) {
|
|
116
133
|
const empty = { verifications: [] };
|
|
117
134
|
await ctx.writer.writeJson('verifications', empty);
|
|
@@ -138,7 +155,7 @@ export async function s8Verify(ctx, graph) {
|
|
|
138
155
|
return skipped;
|
|
139
156
|
}
|
|
140
157
|
try {
|
|
141
|
-
const input = verifierInput(graph);
|
|
158
|
+
const input = verifierInput(graph, loadSkill('idea-refinement', 'verifier'));
|
|
142
159
|
// Optional work gets no model repair: one logical optional call must remain one call.
|
|
143
160
|
const result = await jsonCall(ctx, ctx.handle(ctx.roles.verifier), 'S8', input.prompt, ClaimVerificationSet, { repair: false });
|
|
144
161
|
const translated = {
|
|
@@ -5,6 +5,7 @@ import { selectRebuttalEscalations, } from '../decision-graph.js';
|
|
|
5
5
|
import { isFatal, StageError } from '../context.js';
|
|
6
6
|
import { jsonCall } from '../jsonStage.js';
|
|
7
7
|
import { IDEA_MODE_PLANS } from '../modes.js';
|
|
8
|
+
import { loadSkill } from '../skills.js';
|
|
8
9
|
/** Internal protocol caps only. R6 owns exposing modes and changing the surrounding topology. */
|
|
9
10
|
export const REBUTTAL_LIMITS = {
|
|
10
11
|
quick: { maxNodes: 0, optionalCalls: 0 },
|
|
@@ -22,7 +23,7 @@ Output ONLY JSON:
|
|
|
22
23
|
CONCEDE = your position changes. COUNTER = retain it using a cited supplied card or a precise logical
|
|
23
24
|
rebuttal. NARROW = state the smaller proposition actually supported. UNRESOLVED = evidence cannot decide.
|
|
24
25
|
Return exactly one event per assigned claim. Cite only evidence IDs shown for that claim. Do not invent
|
|
25
|
-
sources, URLs, claim IDs, or evidence IDs. JSON only.
|
|
26
|
+
sources, URLs, claim IDs, or evidence IDs. JSON only.{{SKILL}}
|
|
26
27
|
NODES: {{NODES_JSON}}`;
|
|
27
28
|
function claimAuthors(graph, claimId) {
|
|
28
29
|
const positionById = new Map(graph.positions.map((position) => [position.id, position]));
|
|
@@ -70,7 +71,7 @@ export function planRebuttalCalls(graph, escalations, scouts, judge) {
|
|
|
70
71
|
return claim_ids?.length ? [{ provider, claim_ids }] : [];
|
|
71
72
|
});
|
|
72
73
|
}
|
|
73
|
-
function rebuttalInput(graph, verifications, escalationById, assignment) {
|
|
74
|
+
function rebuttalInput(graph, verifications, escalationById, assignment, skill = '') {
|
|
74
75
|
const claimIds = new Set(assignment.claim_ids);
|
|
75
76
|
const positionRefs = new Map();
|
|
76
77
|
const evidenceRefs = new Map();
|
|
@@ -130,11 +131,16 @@ function rebuttalInput(graph, verifications, escalationById, assignment) {
|
|
|
130
131
|
};
|
|
131
132
|
});
|
|
132
133
|
return {
|
|
133
|
-
prompt:
|
|
134
|
+
prompt: buildRebuttalPrompt(nodes, skill),
|
|
134
135
|
evidenceRefs,
|
|
135
136
|
allowedEvidence,
|
|
136
137
|
};
|
|
137
138
|
}
|
|
139
|
+
export function buildRebuttalPrompt(nodes, skill = '') {
|
|
140
|
+
return REBUTTAL_PROMPT
|
|
141
|
+
.replace('{{SKILL}}', skill ? `\n\n${skill}` : '')
|
|
142
|
+
.replace('{{NODES_JSON}}', JSON.stringify(nodes, null, 2));
|
|
143
|
+
}
|
|
138
144
|
function translateEvents(graph, assignment, input, output, startIndex) {
|
|
139
145
|
const expected = new Set(assignment.claim_ids);
|
|
140
146
|
const seen = new Set();
|
|
@@ -189,8 +195,9 @@ export async function s8bRebuttal(ctx, graph, verifications, mode = ctx.mode) {
|
|
|
189
195
|
const assignments = planned.slice(0, optionalCalls);
|
|
190
196
|
const escalationById = new Map(escalations.map((item) => [item.claim_id, item]));
|
|
191
197
|
const events = [];
|
|
198
|
+
const skill = loadSkill('idea-refinement', 'rebuttal');
|
|
192
199
|
for (const assignment of assignments) {
|
|
193
|
-
const input = rebuttalInput(graph, verifications, escalationById, assignment);
|
|
200
|
+
const input = rebuttalInput(graph, verifications, escalationById, assignment, skill);
|
|
194
201
|
try {
|
|
195
202
|
const output = await jsonCall(ctx, ctx.handle(assignment.provider), `S8b-${assignment.provider}`, input.prompt, RebuttalResponseSet, { repair: false });
|
|
196
203
|
events.push(...translateEvents(graph, assignment, input, output, events.length));
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// S9 — chair adjudication over graph-selected escalations. Consensus and shared concerns are
|
|
2
2
|
// read-only context; anonymous position text and the verifier record cross the boundary unchanged.
|
|
3
|
-
import { selectEscalations } from '../decision-graph.js';
|
|
4
3
|
import { IdeaChairReportModel } from '../../schemas/index.js';
|
|
5
4
|
import { isFatal, StageError } from '../context.js';
|
|
6
5
|
import { jsonCall } from '../jsonStage.js';
|
|
7
|
-
import {
|
|
6
|
+
import { claimShortLabel } from '../decision-dossier.js';
|
|
7
|
+
import { loadSkill } from '../skills.js';
|
|
8
|
+
import { claimVerificationRefIssues, selectVerificationEscalations } from './s8-verify.js';
|
|
8
9
|
const EMPTY_REBUTTALS = {
|
|
9
10
|
round: 1,
|
|
10
11
|
selected_claim_ids: [],
|
|
@@ -39,7 +40,7 @@ Output ONLY JSON matching the judge schema:
|
|
|
39
40
|
- key_points: 4-8 standalone decision-relevant bullets.
|
|
40
41
|
- dissent: a JSON array of strings (an array even when there is only one) — the strongest arguments
|
|
41
42
|
against your verdict.
|
|
42
|
-
- confidence_notes: explain calibrated confidence.
|
|
43
|
+
- confidence_notes: explain calibrated confidence.{{SKILL}}
|
|
43
44
|
ESCALATED CLAIMS + VERIFICATION: {{ESCALATIONS_JSON}}
|
|
44
45
|
APPEND-ONLY REBUTTAL EVENTS: {{REBUTTALS_JSON}}
|
|
45
46
|
SETTLED/UNRESOLVED CONTEXT: {{CONTEXT_JSON}}`;
|
|
@@ -173,19 +174,40 @@ export function adjudicableClaimIds(graph, ids, judgeProvider) {
|
|
|
173
174
|
return [...ids].filter((id) => !claimById.get(id)?.position_ids
|
|
174
175
|
.some((positionId) => positionById.get(positionId)?.provider === judgeProvider));
|
|
175
176
|
}
|
|
177
|
+
/** One condition per distinct claim behind an evidence hole, claim-labeled instead of a generic
|
|
178
|
+
* placeholder reason. Deduped by claim_id and capped at 4 so the fallback conditions list doesn't
|
|
179
|
+
* drown in near-identical entries. */
|
|
180
|
+
export function evidenceHoleConditions(graph) {
|
|
181
|
+
const claimById = new Map(graph.claims.map((claim) => [claim.id, claim]));
|
|
182
|
+
const seen = new Set();
|
|
183
|
+
const out = [];
|
|
184
|
+
for (const hole of graph.holes.evidence) {
|
|
185
|
+
if (seen.has(hole.claim_id))
|
|
186
|
+
continue;
|
|
187
|
+
seen.add(hole.claim_id);
|
|
188
|
+
const claim = claimById.get(hole.claim_id);
|
|
189
|
+
out.push(`Obtain independent evidence for: "${claimShortLabel(claim?.proposition ?? 'a load-bearing claim')}".`);
|
|
190
|
+
if (out.length === 4)
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
return out;
|
|
194
|
+
}
|
|
176
195
|
function fallbackConditions(graph, adjudications) {
|
|
177
196
|
const claimById = new Map(graph.claims.map((claim) => [claim.id, claim]));
|
|
178
197
|
const upheld = adjudications
|
|
179
198
|
.filter((item) => item.ruling === 'UPHOLD')
|
|
180
199
|
.map((item) => `Proceed only if you can resolve: ${claimById.get(item.id)?.proposition ?? item.id}.`);
|
|
181
200
|
const holes = graph.holes.coverage.map((hole) => `Proceed only after examining the ${hole.label} gap.`);
|
|
182
|
-
const evidenceHoles = graph
|
|
201
|
+
const evidenceHoles = evidenceHoleConditions(graph);
|
|
183
202
|
return [...upheld, ...holes, ...evidenceHoles, 'Proceed only after one cheap test confirms the core user need.'].slice(0, 6);
|
|
184
203
|
}
|
|
185
|
-
export function buildJudgePrompt(contract, graph, verifications, rubric, rebuttals = EMPTY_REBUTTALS, judgeProvider) {
|
|
186
|
-
return judgeInput(contract, graph, verifications, rubric, rebuttals, judgeProvider).prompt;
|
|
204
|
+
export function buildJudgePrompt(contract, graph, verifications, rubric, rebuttals = EMPTY_REBUTTALS, judgeProvider, skill = '') {
|
|
205
|
+
return judgeInput(contract, graph, verifications, rubric, rebuttals, judgeProvider, skill).prompt;
|
|
206
|
+
}
|
|
207
|
+
export function buildChairRepairPrompt(basePrompt, corrections) {
|
|
208
|
+
return `${basePrompt}\n\n---\nCorrect these problems:\n${corrections}Output ONLY corrected JSON.`;
|
|
187
209
|
}
|
|
188
|
-
function judgeInput(contract, graph, verifications, rubric, rebuttals, judgeProvider) {
|
|
210
|
+
function judgeInput(contract, graph, verifications, rubric, rebuttals, judgeProvider, skill = '') {
|
|
189
211
|
const positionById = new Map(graph.positions.map((position) => [position.id, position]));
|
|
190
212
|
const verificationById = new Map(verifications.verifications.map((item) => [item.claim_id, item]));
|
|
191
213
|
const citedEvidence = [...new Set([
|
|
@@ -194,7 +216,7 @@ function judgeInput(contract, graph, verifications, rubric, rebuttals, judgeProv
|
|
|
194
216
|
])];
|
|
195
217
|
const evidenceRefs = new Map(citedEvidence.map((id, index) => [`E${index + 1}`, id]));
|
|
196
218
|
const aliasByEvidence = new Map([...evidenceRefs].map(([alias, id]) => [id, alias]));
|
|
197
|
-
const selectedIds =
|
|
219
|
+
const selectedIds = selectVerificationEscalations(graph).map((item) => item.claim_id);
|
|
198
220
|
const eligibleIds = judgeProvider ? adjudicableClaimIds(graph, selectedIds, judgeProvider) : selectedIds;
|
|
199
221
|
const escalationIds = new Set(eligibleIds);
|
|
200
222
|
const escalations = graph.claims.filter((claim) => escalationIds.has(claim.id)).map((claim) => {
|
|
@@ -234,6 +256,7 @@ function judgeInput(contract, graph, verifications, rubric, rebuttals, judgeProv
|
|
|
234
256
|
...(event.narrowed_proposition ? { narrowed_proposition: event.narrowed_proposition } : {}),
|
|
235
257
|
}));
|
|
236
258
|
const prompt = S9_PROMPT
|
|
259
|
+
.replace('{{SKILL}}', skill ? `\n\n${skill}` : '')
|
|
237
260
|
.replace('{{RUBRIC_JSON}}', JSON.stringify(rubric.map((item) => item.label)))
|
|
238
261
|
.replace('{{ESCALATIONS_JSON}}', JSON.stringify(escalations, null, 2))
|
|
239
262
|
.replace('{{REBUTTALS_JSON}}', JSON.stringify(rebuttalContext, null, 2))
|
|
@@ -242,13 +265,13 @@ function judgeInput(contract, graph, verifications, rubric, rebuttals, judgeProv
|
|
|
242
265
|
return { prompt, evidenceRefs };
|
|
243
266
|
}
|
|
244
267
|
export async function s9Judge(ctx, contract, graph, verifications, rubric, rebuttals = EMPTY_REBUTTALS) {
|
|
245
|
-
const selectedIds =
|
|
268
|
+
const selectedIds = selectVerificationEscalations(graph).map((item) => item.claim_id);
|
|
246
269
|
const verificationIssues = claimVerificationRefIssues(graph, verifications, selectedIds);
|
|
247
270
|
if (verificationIssues.length)
|
|
248
271
|
throw new StageError('S9', 'BAD_OUTPUT', `invalid verification references: ${verificationIssues.join('; ')}`);
|
|
249
272
|
const ids = adjudicableClaimIds(graph, selectedIds, ctx.roles.judge);
|
|
250
273
|
const selfAuthored = new Set(selectedIds.filter((id) => !ids.includes(id)));
|
|
251
|
-
const input = judgeInput(contract, graph, verifications, rubric, rebuttals, ctx.roles.judge);
|
|
274
|
+
const input = judgeInput(contract, graph, verifications, rubric, rebuttals, ctx.roles.judge, loadSkill('idea-refinement', 'chair'));
|
|
252
275
|
const basePrompt = input.prompt;
|
|
253
276
|
const judge = ctx.handle(ctx.roles.judge);
|
|
254
277
|
const positionById = new Map(graph.positions.map((position) => [position.id, position]));
|
|
@@ -291,13 +314,13 @@ export async function s9Judge(ctx, contract, graph, verifications, rubric, rebut
|
|
|
291
314
|
];
|
|
292
315
|
if ((violations.length || evidenceViolations.length || report.dissent.length === 0 || recIssues.length || chairIssues.length)
|
|
293
316
|
&& ctx.budget.limit - ctx.budget.used > 1) {
|
|
294
|
-
const
|
|
317
|
+
const corrections = ''
|
|
295
318
|
+ (violations.length ? `- adjudications may reference only [${ids.join(', ')}], not ${violations.join(', ')}\n` : '')
|
|
296
319
|
+ (evidenceViolations.length ? `- evidence reference errors: ${evidenceViolations.join('; ')}\n` : '')
|
|
297
320
|
+ (report.dissent.length === 0 ? '- dissent must contain at least one item\n' : '')
|
|
298
321
|
+ (recIssues.length ? `- ${recIssues.join('; ')}\n` : '')
|
|
299
|
-
+ (chairIssues.length ? `- chair contract errors: ${chairIssues.join('; ')}\n` : '')
|
|
300
|
-
|
|
322
|
+
+ (chairIssues.length ? `- chair contract errors: ${chairIssues.join('; ')}\n` : '');
|
|
323
|
+
const repair = buildChairRepairPrompt(basePrompt, corrections);
|
|
301
324
|
try {
|
|
302
325
|
report = translateChairReport(await jsonCall(ctx, judge, 'S9-repair', repair, IdeaChairReportModel, {
|
|
303
326
|
repair: ctx.budget.limit - ctx.budget.used > 2,
|