Context
When multiple agents attest to the same ledger entry (two SOUND, one FLAGGED), TrustScoreJob currently treats each attestation independently — three separate Beta updates. This creates noise: the FLAGGED attestation from a less reliable peer carries the same weight as two SOUND attestations from highly trusted peers. Aggregating attestations to a consensus verdict before scoring reduces noise.
Part of: #49 (Group A epic)
What to implement
New component AttestationAggregator in the trust scoring pipeline:
@ApplicationScoped
public class AttestationAggregator {
/**
* Given multiple attestations on the same ledger entry,
* produce a single consensus verdict and confidence.
*
* Strategy: confidence-weighted majority.
* - Sum confidence-weighted SOUND/ENDORSED votes
* - Sum confidence-weighted FLAGGED/CHALLENGED votes
* - Consensus = majority verdict, confidence = margin / total
*/
public Optional<AggregatedAttestation> aggregate(List<LedgerAttestation> attestations) { ... }
public record AggregatedAttestation(
AttestationVerdict consensusVerdict,
double aggregatedConfidence,
int attestorCount
) {}
}
Update TrustScoreJob to:
- Group attestations by
ledgerEntryId
- For entries with multiple attestations, call
AttestationAggregator.aggregate()
- Use the aggregated result as a single trust update rather than N individual updates
Aggregation strategy (configurable):
WEIGHTED_MAJORITY (default) — confidence-weighted vote
UNANIMOUS_REQUIRED — only SOUND if all attestors agree
FIRST_ATTESTOR — use first attestation only (legacy behaviour)
casehub.ledger.trust.aggregation-strategy=WEIGHTED_MAJORITY
Tests
- 2 SOUND (confidence 0.8) + 1 FLAGGED (confidence 0.3) → consensus SOUND, aggregated confidence reflects margin
- 1 SOUND (confidence 0.5) + 1 FLAGGED (confidence 0.9) → consensus FLAGGED (higher total weight)
- Single attestation → aggregated result equals that attestation unchanged
UNANIMOUS_REQUIRED strategy: any FLAGGED → consensus FLAGGED
FIRST_ATTESTOR strategy: identical to current behaviour (regression)
Motivating use case
A PR is reviewed by three agents. Two highly-trusted reviewers (confidence 0.9 each) mark it SOUND. One lower-trust reviewer (confidence 0.3) marks it FLAGGED due to an overly conservative style concern. Weighted majority: SOUND wins with strong margin. The assigning agent's trust score increases rather than being dragged down by the minority FLAGGED.
Acceptance criteria
Refs #49
Context
When multiple agents attest to the same ledger entry (two SOUND, one FLAGGED),
TrustScoreJobcurrently treats each attestation independently — three separate Beta updates. This creates noise: the FLAGGED attestation from a less reliable peer carries the same weight as two SOUND attestations from highly trusted peers. Aggregating attestations to a consensus verdict before scoring reduces noise.Part of: #49 (Group A epic)
What to implement
New component
AttestationAggregatorin the trust scoring pipeline:Update
TrustScoreJobto:ledgerEntryIdAttestationAggregator.aggregate()Aggregation strategy (configurable):
WEIGHTED_MAJORITY(default) — confidence-weighted voteUNANIMOUS_REQUIRED— only SOUND if all attestors agreeFIRST_ATTESTOR— use first attestation only (legacy behaviour)casehub.ledger.trust.aggregation-strategy=WEIGHTED_MAJORITYTests
UNANIMOUS_REQUIREDstrategy: any FLAGGED → consensus FLAGGEDFIRST_ATTESTORstrategy: identical to current behaviour (regression)Motivating use case
A PR is reviewed by three agents. Two highly-trusted reviewers (confidence 0.9 each) mark it SOUND. One lower-trust reviewer (confidence 0.3) marks it FLAGGED due to an overly conservative style concern. Weighted majority: SOUND wins with strong margin. The assigning agent's trust score increases rather than being dragged down by the minority FLAGGED.
Acceptance criteria
AttestationAggregatorCDI bean implemented with weighted majority as defaultTrustScoreJobupdated to aggregate before scoringFIRST_ATTESTORstrategy, all existing trust score tests pass unchanged (regression)Refs #49