feat(kernel): label reviewer artifacts as critic feedback on back-edge re-entry
This commit is contained in:
@@ -1,11 +1,20 @@
|
||||
import com.correx.core.artifacts.kind.FileWrittenKind
|
||||
import com.correx.core.artifacts.kind.TypedArtifactSlot
|
||||
import com.correx.core.context.model.ContextLayer
|
||||
import com.correx.core.context.model.EntryRole
|
||||
import com.correx.core.events.events.RefinementIterationEvent
|
||||
import com.correx.core.events.events.RetryAttemptedEvent
|
||||
import com.correx.core.events.types.ArtifactId
|
||||
import com.correx.core.events.types.SessionId
|
||||
import com.correx.core.events.types.StageId
|
||||
import com.correx.core.events.types.TransitionId
|
||||
import com.correx.core.kernel.orchestration.buildProjectProfileEntry
|
||||
import com.correx.core.kernel.orchestration.buildRetryFeedbackEntry
|
||||
import com.correx.core.kernel.orchestration.criticArtifactIds
|
||||
import com.correx.core.sessions.BoundProjectProfile
|
||||
import com.correx.core.transitions.graph.StageConfig
|
||||
import com.correx.core.transitions.graph.TransitionEdge
|
||||
import com.correx.core.transitions.graph.WorkflowGraph
|
||||
import com.correx.testing.fixtures.EventFixtures.stored
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNull
|
||||
@@ -72,4 +81,49 @@ class ContextFeedbackTest {
|
||||
assertTrue(!entry.content.contains("### Commands"), "should not contain Commands: ${entry.content}")
|
||||
assertEquals("projectProfile", entry.sourceType)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `criticArtifactIds resolves the from-stage produces on a back-edge`() {
|
||||
val graph = graphWith(
|
||||
"implement" to producesSlots("patch"),
|
||||
"review" to producesSlots("review_report"),
|
||||
)
|
||||
val events = listOf(
|
||||
stored(payload = RefinementIterationEvent(SessionId("s"), "review->implement", 1, 3)),
|
||||
)
|
||||
assertEquals(setOf(ArtifactId("review_report")), criticArtifactIds(events, graph, StageId("implement")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no refinement events yields empty set`() {
|
||||
assertTrue(criticArtifactIds(emptyList(), graphWith(), StageId("implement")).isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `criticArtifactIds ignores events targeting a different stage`() {
|
||||
val graph = graphWith(
|
||||
"implement" to producesSlots("patch"),
|
||||
"review" to producesSlots("review_report"),
|
||||
)
|
||||
val events = listOf(
|
||||
stored(payload = RefinementIterationEvent(SessionId("s"), "review->other", 1, 3)),
|
||||
)
|
||||
assertTrue(criticArtifactIds(events, graph, StageId("implement")).isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
private fun producesSlots(vararg names: String): List<TypedArtifactSlot> =
|
||||
names.map { TypedArtifactSlot(name = ArtifactId(it), kind = FileWrittenKind) }
|
||||
|
||||
private fun graphWith(vararg stages: Pair<String, List<TypedArtifactSlot>>): WorkflowGraph {
|
||||
val stageMap = stages.associate { (id, slots) ->
|
||||
StageId(id) to StageConfig(produces = slots)
|
||||
}.toMutableMap()
|
||||
if (stageMap.isEmpty()) stageMap[StageId("start")] = StageConfig()
|
||||
return WorkflowGraph(
|
||||
id = "test-graph",
|
||||
stages = stageMap,
|
||||
transitions = emptySet(),
|
||||
start = stageMap.keys.first(),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user