feat(03-01): implement synthesis contracts and formatter pipeline

- Add synthesis result contracts with agreement, provenance, and Athena assessment fields\n- Add synthesis prompt builder and council-response formatter with failure-aware provenance output
This commit is contained in:
ismeth 2026-02-12 13:53:47 +01:00 committed by YeonGyu-Kim
parent d4e20b9311
commit 95f133ff63
4 changed files with 126 additions and 0 deletions

View File

@ -3,4 +3,7 @@ export * from "./model-parser"
export * from "./council-prompt"
export * from "./council-orchestrator"
export * from "./council-result-collector"
export * from "./synthesis-types"
export * from "./synthesis-prompt"
export * from "./synthesis-formatter"
export * from "../../config/schema/athena"

View File

@ -0,0 +1,48 @@
import type { CouncilExecutionResult } from "./types"
export function formatCouncilResultsForSynthesis(result: CouncilExecutionResult): string {
const completedResponses = result.responses.filter((response) => response.status === "completed")
if (completedResponses.length === 0) {
return [
"# Council Responses for Synthesis",
`Question: ${result.question}`,
"No successful responses from council members.",
"Review failed member details below for provenance.",
...result.responses.map((response) => {
const memberName = response.member.name ?? response.member.model
return [
`## Member: ${memberName} (${response.status})`,
`Model: ${response.member.model}`,
`Status: ${response.status}`,
`Duration: ${response.durationMs}ms`,
`Error: ${response.error ?? "No error message provided"}`,
].join("\n")
}),
].join("\n\n")
}
const sections = result.responses.map((response) => {
const memberName = response.member.name ?? response.member.model
const header = [
`## Member: ${memberName} (${response.status})`,
`Model: ${response.member.model}`,
`Status: ${response.status}`,
`Duration: ${response.durationMs}ms`,
]
if (response.status === "completed") {
const responseBody = response.response?.trim() ? response.response : "No response content provided"
return [...header, "Response:", responseBody].join("\n")
}
return [...header, `Error: ${response.error ?? "No error message provided"}`].join("\n")
})
return [
"# Council Responses for Synthesis",
`Question: ${result.question}`,
`Completed responses: ${result.completedCount}/${result.totalMembers}`,
...sections,
].join("\n\n")
}

View File

@ -0,0 +1,44 @@
export function buildSynthesisPrompt(formattedResponses: string, question: string, completedCount: number): string {
return `You are Athena, the synthesis lead for a multi-model council. Your job is to merge independent model outputs into a single, evidence-grounded synthesis.
## Original Question
${question}
## Council Responses
${formattedResponses}
## Your Responsibilities
1. Identify distinct findings across all completed member responses.
2. Group findings that refer to the same underlying issue (semantic similarity, not exact wording).
3. Classify agreementLevel for each finding using ${completedCount} completed member(s):
- unanimous: all completed members reported the finding
- majority: more than 50% of completed members reported the finding
- minority: 2 or more members reported it, but not a majority
- solo: only 1 member reported it
4. Add AthenaAssessment for each finding:
- agrees: whether you agree with the finding
- rationale: concise reason for agreement or disagreement
5. Set isFalsePositiveRisk:
- true for solo findings (likely false positives unless strongly supported)
- false for findings reported by multiple members
## Output Contract
Return JSON only with this shape:
{
"findings": [
{
"summary": "string",
"details": "string",
"agreementLevel": "unanimous | majority | minority | solo",
"reportedBy": ["model/name"],
"assessment": {
"agrees": true,
"rationale": "string"
},
"isFalsePositiveRisk": false
}
]
}
The finding object must match the SynthesizedFinding type exactly. Keep findings concise, concrete, and tied to source responses.`
}

View File

@ -0,0 +1,31 @@
import type { AgreementLevel, CouncilMemberConfig, CouncilMemberStatus } from "./types"
export interface AthenaAssessment {
agrees: boolean
rationale: string
}
export interface SynthesizedFinding {
summary: string
details: string
agreementLevel: AgreementLevel
reportedBy: string[]
assessment: AthenaAssessment
isFalsePositiveRisk: boolean
}
export interface MemberProvenance {
member: CouncilMemberConfig
status: CouncilMemberStatus
rawResponse?: string
durationMs: number
}
export interface SynthesisResult {
question: string
findings: SynthesizedFinding[]
memberProvenance: MemberProvenance[]
totalFindings: number
consensusCount: number
outlierCount: number
}