Clarify semantic reconciliation candidate numbers

This commit is contained in:
2026-08-29 03:16:24 +00:00
parent 917d150279
commit 7e626753bf
30 changed files with 572 additions and 196 deletions

View File

@@ -47,11 +47,14 @@ func TestPrepareBuildsContiguousCandidatesAndOwnedSourceContext(t *testing.T) {
t.Fatalf("Prepare() mutated candidates: %#v", candidates)
}
if got, want := preparation.CandidateMappings(), []CandidateMapping{
{CandidateID: 1, CandidatePosition: 0},
{CandidateID: 2, CandidatePosition: 1},
{CandidateNumber: 1, CandidatePosition: 0},
{CandidateNumber: 2, CandidatePosition: 1},
}; !reflect.DeepEqual(got, want) {
t.Fatalf("CandidateMappings() = %#v, want %#v", got, want)
}
if got, want := preparation.CandidateNumberRange(), (CandidateNumberRange{First: 1, Last: 2}); got != want {
t.Fatalf("CandidateNumberRange() = %#v, want %#v", got, want)
}
materials := preparation.Materials()
if len(materials) != 2 {
@@ -79,12 +82,15 @@ func TestPrepareBuildsContiguousCandidatesAndOwnedSourceContext(t *testing.T) {
t.Fatal(err)
}
wantCandidates := []visibleCandidate{
{CandidateID: 1, Label: "The Tavern", SourceRefs: []sourceRange{{StartUnitID: 10, EndUnitID: 20}, {StartUnitID: 90, EndUnitID: 90}}},
{CandidateID: 2, Label: "The Tavern", SourceRefs: []sourceRange{{StartUnitID: 10, EndUnitID: 20}, {StartUnitID: 90, EndUnitID: 90}}},
{CandidateNumber: 1, Label: "The Tavern", SourceRefs: []sourceRange{{StartUnitID: 10, EndUnitID: 20}, {StartUnitID: 90, EndUnitID: 90}}},
{CandidateNumber: 2, Label: "The Tavern", SourceRefs: []sourceRange{{StartUnitID: 10, EndUnitID: 20}, {StartUnitID: 90, EndUnitID: 90}}},
}
if !reflect.DeepEqual(candidatePayload.Candidates, wantCandidates) {
t.Fatalf("candidate payload = %#v, want %#v", candidatePayload.Candidates, wantCandidates)
}
if got, want := candidatePayload.CandidateNumberRange, (CandidateNumberRange{First: 1, Last: 2}); got != want {
t.Fatalf("candidate number range = %#v, want %#v", got, want)
}
var candidateObjects struct {
Candidates []map[string]json.RawMessage `json:"candidates"`
}
@@ -92,12 +98,12 @@ func TestPrepareBuildsContiguousCandidatesAndOwnedSourceContext(t *testing.T) {
t.Fatal(err)
}
for _, candidate := range candidateObjects.Candidates {
if len(candidate) != 3 || candidate["candidate_id"] == nil || candidate["label"] == nil || candidate["source_refs"] == nil {
if len(candidate) != 3 || candidate["candidate_number"] == nil || candidate["label"] == nil || candidate["source_refs"] == nil {
t.Fatalf("model-facing candidate fields = %#v", candidate)
}
}
combined := string(materials[candidateInputName].Content) + string(materials[transcriptInputName].Content)
for _, forbidden := range []string{document.ID, "application_entity_id", "private-entity-id"} {
for _, forbidden := range []string{document.ID, "application_entity_id", "private-entity-id", `"candidate_id"`, `"candidate_ids"`, `"canonical_candidate_id"`} {
if strings.Contains(combined, forbidden) {
t.Fatalf("model material leaked %q: %s", forbidden, combined)
}
@@ -192,11 +198,14 @@ func TestPrepareFiltersUnsafeCandidatesAndCoalescesAdjacentWindows(t *testing.T)
t.Fatalf("Prepare() disposition = %v, error = %v", preparation.Disposition(), err)
}
if got, want := preparation.CandidateMappings(), []CandidateMapping{
{CandidateID: 1, CandidatePosition: 0},
{CandidateID: 2, CandidatePosition: 1},
{CandidateNumber: 1, CandidatePosition: 0},
{CandidateNumber: 2, CandidatePosition: 1},
}; !reflect.DeepEqual(got, want) {
t.Fatalf("CandidateMappings() = %#v, want %#v", got, want)
}
if got, want := preparation.CandidateNumberRange(), (CandidateNumberRange{First: 1, Last: 2}); got != want {
t.Fatalf("CandidateNumberRange() after filtering = %#v, want %#v", got, want)
}
var transcript transcriptInput
if err := json.Unmarshal(preparation.Materials()[transcriptInputName].Content, &transcript); err != nil {
t.Fatal(err)
@@ -208,7 +217,7 @@ func TestPrepareFiltersUnsafeCandidatesAndCoalescesAdjacentWindows(t *testing.T)
if err != nil {
t.Fatal(err)
}
if got, want := oneCandidate.CandidateMappings(), []CandidateMapping{{CandidateID: 1, CandidatePosition: 0}}; oneCandidate.Disposition() != InsufficientCandidates || !reflect.DeepEqual(got, want) || len(oneCandidate.Materials()) != 0 {
if got, want := oneCandidate.CandidateMappings(), []CandidateMapping{{CandidateNumber: 1, CandidatePosition: 0}}; oneCandidate.Disposition() != InsufficientCandidates || !reflect.DeepEqual(got, want) || oneCandidate.CandidateNumberRange() != (CandidateNumberRange{First: 1, Last: 1}) || len(oneCandidate.Materials()) != 0 {
t.Fatalf("Prepare(one candidate) = disposition %v, mappings %#v, materials %#v", oneCandidate.Disposition(), got, oneCandidate.Materials())
}
@@ -216,7 +225,7 @@ func TestPrepareFiltersUnsafeCandidatesAndCoalescesAdjacentWindows(t *testing.T)
if err != nil {
t.Fatal(err)
}
if nilPreparation.Disposition() != InsufficientCandidates || len(nilPreparation.CandidateMappings()) != 0 || len(nilPreparation.Materials()) != 0 {
if nilPreparation.Disposition() != InsufficientCandidates || len(nilPreparation.CandidateMappings()) != 0 || nilPreparation.CandidateNumberRange() != (CandidateNumberRange{}) || len(nilPreparation.Materials()) != 0 {
t.Fatalf("Prepare(nil) = disposition %v, mappings %#v, materials %#v", nilPreparation.Disposition(), nilPreparation.CandidateMappings(), nilPreparation.Materials())
}
}