feat(workflow): analyst→architect→planner→implementer⇄reviewer role pipeline
This commit is contained in:
+73
@@ -0,0 +1,73 @@
|
||||
package com.correx.infrastructure.workflow
|
||||
|
||||
import com.correx.core.artifacts.kind.ConfigArtifactKind
|
||||
import com.correx.core.artifacts.kind.DefaultArtifactKindRegistry
|
||||
import com.correx.core.artifacts.kind.JsonSchema
|
||||
import com.correx.core.artifacts.kind.JsonSchemaProperty
|
||||
import com.correx.core.events.types.StageId
|
||||
import com.correx.core.transitions.conditions.ArtifactFieldEquals
|
||||
import com.correx.core.transitions.conditions.FieldOperator
|
||||
import org.junit.jupiter.api.Assumptions.assumeTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class RolePipelineWorkflowTest {
|
||||
|
||||
private fun llmKind(id: String) = ConfigArtifactKind(
|
||||
id = id,
|
||||
schema = JsonSchema(
|
||||
type = "object",
|
||||
properties = mapOf("verdict" to JsonSchemaProperty(type = "string")),
|
||||
additionalProperties = true,
|
||||
),
|
||||
llmEmitted = true,
|
||||
)
|
||||
|
||||
private val registry = DefaultArtifactKindRegistry().apply {
|
||||
register(llmKind("analysis"))
|
||||
register(llmKind("design"))
|
||||
register(llmKind("impl_plan"))
|
||||
register(llmKind("review_report"))
|
||||
}
|
||||
|
||||
// Walk up from the working dir to the repo root so the test finds the shipped file
|
||||
// regardless of which module dir Gradle runs it from.
|
||||
private fun repoFile(rel: String): Path? {
|
||||
var dir: Path? = Path.of(System.getProperty("user.dir")).toAbsolutePath()
|
||||
while (dir != null) {
|
||||
val candidate = dir.resolve(rel)
|
||||
if (candidate.exists()) return candidate
|
||||
dir = dir.parent
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `shipped role_pipeline toml parses with the full role graph`() {
|
||||
val path = repoFile("examples/workflows/role_pipeline.toml")
|
||||
assumeTrue(path != null, "role_pipeline.toml not found from ${System.getProperty("user.dir")}")
|
||||
|
||||
val graph = TomlWorkflowLoader(registry).load(path!!)
|
||||
|
||||
assertEquals(
|
||||
setOf("analyst", "architect", "planner", "implementer", "reviewer"),
|
||||
graph.stages.keys.map { it.value }.toSet(),
|
||||
)
|
||||
assertEquals(6, graph.transitions.size)
|
||||
|
||||
// Forward chaining via needs.
|
||||
assertTrue(graph.stages[StageId("reviewer")]!!.needs.map { it.value }.containsAll(listOf("patch", "impl_plan")))
|
||||
|
||||
// Verdict-gated loop: approved → done, changes → implementer.
|
||||
val approved = graph.transitions.first { it.to == StageId("done") }.condition as ArtifactFieldEquals
|
||||
assertEquals(FieldOperator.EQ, approved.operator)
|
||||
assertEquals("verdict", approved.field)
|
||||
val loop = graph.transitions
|
||||
.first { it.from == StageId("reviewer") && it.to == StageId("implementer") }
|
||||
.condition as ArtifactFieldEquals
|
||||
assertEquals(FieldOperator.NEQ, loop.operator)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user