fix(t212): preserve ranked candidate identity
This commit is contained in:
+87
@@ -0,0 +1,87 @@
|
||||
package com.roubao.autopilot.procurement
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertThrows
|
||||
import org.junit.Test
|
||||
|
||||
class ExecutionCandidateIdentityPolicyTest {
|
||||
@Test
|
||||
fun `recommended candidate uses ranked first instead of source ordinal`() {
|
||||
val bindings = ExecutionCandidateIdentityPolicy.bind(
|
||||
identities = listOf(
|
||||
identity(sourceOrdinal = 3, rankedOrdinal = 1),
|
||||
identity(sourceOrdinal = 1, rankedOrdinal = 2),
|
||||
identity(sourceOrdinal = 2, rankedOrdinal = 3)
|
||||
),
|
||||
candidates = listOf(candidate(1), candidate(2), candidate(3))
|
||||
)
|
||||
|
||||
val recommended = ExecutionCandidateIdentityPolicy.recommended(bindings)
|
||||
|
||||
assertEquals(1, recommended?.ordinal)
|
||||
assertEquals(3, bindings.first().identity.sourceOrdinal)
|
||||
assertEquals("evidence-1", recommended?.evidenceLocalIDs?.single())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `filtered source ordinals keep continuous ranked identities`() {
|
||||
val bindings = ExecutionCandidateIdentityPolicy.bind(
|
||||
identities = listOf(
|
||||
identity(sourceOrdinal = 2, rankedOrdinal = 1),
|
||||
identity(sourceOrdinal = 5, rankedOrdinal = 2)
|
||||
),
|
||||
candidates = listOf(candidate(1), candidate(2))
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
listOf(2, 5),
|
||||
bindings.map { it.identity.sourceOrdinal }
|
||||
)
|
||||
assertEquals(
|
||||
listOf(1, 2),
|
||||
bindings.map { it.candidate.ordinal }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `empty candidates have no recommendation`() {
|
||||
assertNull(
|
||||
ExecutionCandidateIdentityPolicy.recommended(
|
||||
ExecutionCandidateIdentityPolicy.bind(
|
||||
identities = emptyList(),
|
||||
candidates = emptyList()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `missing ranked ordinal is rejected instead of falling back`() {
|
||||
assertThrows(IllegalArgumentException::class.java) {
|
||||
ExecutionCandidateIdentityPolicy.bind(
|
||||
identities = listOf(
|
||||
identity(sourceOrdinal = 3, rankedOrdinal = 1)
|
||||
),
|
||||
candidates = listOf(candidate(2))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun identity(
|
||||
sourceOrdinal: Int,
|
||||
rankedOrdinal: Int
|
||||
): ExecutionCandidateSourceIdentity =
|
||||
ExecutionCandidateSourceIdentity(
|
||||
sourceOrdinal = sourceOrdinal,
|
||||
rankedOrdinal = rankedOrdinal,
|
||||
evidenceSha256 = sourceOrdinal.toString(16).padStart(64, '0')
|
||||
)
|
||||
|
||||
private fun candidate(ordinal: Int): ExecutionCandidateDraft =
|
||||
ExecutionCandidateDraft(
|
||||
ordinal = ordinal,
|
||||
title = "candidate-$ordinal",
|
||||
evidenceLocalIDs = listOf("evidence-$ordinal")
|
||||
)
|
||||
}
|
||||
+31
-2
@@ -6,7 +6,7 @@ import org.junit.Test
|
||||
class CandidateTopFivePolicyTest {
|
||||
@Test
|
||||
fun `sorts eligible matches and limits result to five`() {
|
||||
val selected = CandidateTopFivePolicy.select(
|
||||
val ranked = CandidateTopFivePolicy.rank(
|
||||
batch(
|
||||
assessment(1, score = 0.80, confidence = 0.90),
|
||||
assessment(2, score = 0.90, confidence = 0.80),
|
||||
@@ -24,7 +24,18 @@ class CandidateTopFivePolicyTest {
|
||||
)
|
||||
)
|
||||
|
||||
assertEquals(listOf(3, 2, 5, 6, 7), selected.map { it.ordinal })
|
||||
assertEquals(
|
||||
listOf(3, 2, 5, 6, 7),
|
||||
ranked.map { it.sourceOrdinal }
|
||||
)
|
||||
assertEquals(
|
||||
listOf(1, 2, 3, 4, 5),
|
||||
ranked.map { it.rankedOrdinal }
|
||||
)
|
||||
assertEquals(
|
||||
ranked.map { it.assessment.evidenceSha256 },
|
||||
ranked.map { it.evidenceSha256 }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -45,6 +56,24 @@ class CandidateTopFivePolicyTest {
|
||||
assertEquals(listOf(1), selected.map { it.ordinal })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `original third candidate becomes stable first ranked candidate`() {
|
||||
val ranked = CandidateTopFivePolicy.rank(
|
||||
batch(
|
||||
assessment(1, score = 0.80, confidence = 0.90),
|
||||
assessment(2, score = 0.85, confidence = 0.90),
|
||||
assessment(3, score = 0.95, confidence = 0.95)
|
||||
)
|
||||
)
|
||||
|
||||
assertEquals(3, ranked.first().sourceOrdinal)
|
||||
assertEquals(1, ranked.first().rankedOrdinal)
|
||||
assertEquals(
|
||||
3.toString(16).padStart(64, '0'),
|
||||
ranked.first().evidenceSha256
|
||||
)
|
||||
}
|
||||
|
||||
private fun batch(vararg assessments: CandidateAssessment): CandidateReviewBatch =
|
||||
CandidateReviewBatch(
|
||||
assessments = assessments.toList(),
|
||||
|
||||
Reference in New Issue
Block a user