/** * FU-2 — the synthesis step with provenance. * * A third completion (judge model, FRESH session) reads both role outputs * and emits the structured merge. OK-9 W4 upgrades it to the * literature-settled shape (research/2026-08-18-switchyard-routing-fusion-deep-dive.md * §4): * * 1. COMPARE-THEN-COMPOSE: the synthesiser first produces a pairwise * comparison of the two outputs (LLM-Blender, arXiv:2306.02561 — * pairwise ranking beats pointwise scoring), then composes consensus / * divergence (kept, attributed) / discarded (with reason) / blind spots. * 2. STRONGEST SYNTHESISER, NEVER A PANEL MEMBER: {@link resolveSynthesiser} * prefers the cast's judge over the architect and never the builder — a * weak aggregator caps the whole system (MoA, arXiv:2406.04692), and a * panel member grading its own lane invites self-preference bias, which * scales with self-recognition (arXiv:2404.13076, arXiv:2305.19118). * 3. PARSE FAILURE KEEPS THE PANEL: unparseable output returns both role * outputs verbatim with `synthesisError` set instead of throwing. * * Attribution tags remain mandatory: any divergence or discard that fails to * attribute its positions throws {@link AttributionError} — an unattributed * merge is a regression to a single opinion (E016 §3.2), and it fails loudly * here, not in review. */ import type { Api, Model, StreamFunction } from "@earendil-works/pi-ai"; import { type RoleOutput, type SynthesisArtifact } from "./types.js"; /** * Pick the synthesiser model: the strongest available — the cast's judge, * else the architect; NEVER the builder or any panel member when a distinct * judge exists. Evidence (research/2026-08-18-switchyard-routing-fusion-deep-dive.md * §4): a weak aggregator caps the whole system regardless of panel strength * (MoA, arXiv:2406.04692 — best proposer ≠ best aggregator), and * self-preference bias scales with self-recognition (arXiv:2404.13076, * arXiv:2305.19118), so neither role may synthesise its own lane. The * synthesiser additionally always runs as a FRESH session (see * {@link runSynthesis}), so a distinct judge shares no context with either * panel member. */ export declare function resolveSynthesiser(models: { judgeModel?: T; architectModel: T; /** Accepted but deliberately never returned: the builder never synthesises. */ builderModel?: T; }): T; /** * Run the synthesis. The synthesiser sees the task plus both role outputs — * labelled — and nothing else: it has no access to either role's session. */ export declare function runSynthesis(streamFn: StreamFunction, model: Model, task: string, outputs: RoleOutput[]): Promise; //# sourceMappingURL=synthesis.d.ts.map