test(tasks): pin the task-tool wiring in the shipped workflows
Nothing asserted that the example workflows actually grant the task tools, so a future edit could silently drop one and stay green. Pin allowed_tools per stage for role_pipeline (analyst/implementer/reviewer), freestyle_planning (analyst), and the shipped review_loop (implement/review). The existing review_loop test loaded an inline, now-stale toml rather than the shipped file, so add one that loads the real file. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+6
@@ -69,5 +69,11 @@ class FreestylePlanningWorkflowTest {
|
|||||||
assertTrue(architectToDone.condition is ArtifactValidated)
|
assertTrue(architectToDone.condition is ArtifactValidated)
|
||||||
|
|
||||||
assertEquals(2, graph.transitions.size)
|
assertEquals(2, graph.transitions.size)
|
||||||
|
|
||||||
|
// analyst frames the work: search + open a task (the architect threads it into the plan).
|
||||||
|
assertEquals(
|
||||||
|
setOf("file_read", "ShellTool", "task_search", "task_context", "task_create"),
|
||||||
|
graph.stages[StageId("analyst")]!!.allowedTools,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
@@ -7,8 +7,11 @@ import com.correx.core.artifacts.kind.JsonSchemaProperty
|
|||||||
import com.correx.core.events.types.StageId
|
import com.correx.core.events.types.StageId
|
||||||
import com.correx.core.transitions.conditions.ArtifactFieldEquals
|
import com.correx.core.transitions.conditions.ArtifactFieldEquals
|
||||||
import com.correx.core.transitions.conditions.FieldOperator
|
import com.correx.core.transitions.conditions.FieldOperator
|
||||||
|
import org.junit.jupiter.api.Assumptions.assumeTrue
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.exists
|
||||||
import kotlin.io.path.writeText
|
import kotlin.io.path.writeText
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
@@ -93,4 +96,32 @@ class ReviewLoopWorkflowTest {
|
|||||||
val changes = graph.transitions.first { it.to == StageId("implement") }.condition as ArtifactFieldEquals
|
val changes = graph.transitions.first { it.to == StageId("implement") }.condition as ArtifactFieldEquals
|
||||||
assertEquals(FieldOperator.NEQ, changes.operator)
|
assertEquals(FieldOperator.NEQ, changes.operator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 review_loop grants the task tools to both stages`() {
|
||||||
|
val path = repoFile("examples/workflows/review_loop.toml")
|
||||||
|
assumeTrue(path != null, "review_loop.toml not found from ${System.getProperty("user.dir")}")
|
||||||
|
val graph = loader.load(path!!)
|
||||||
|
|
||||||
|
// implement claims/submits and may create a task, alongside its file write.
|
||||||
|
assertEquals(
|
||||||
|
setOf("file_write", "task_create", "task_update", "task_context", "task_search"),
|
||||||
|
graph.stages[StageId("implement")]!!.allowedTools,
|
||||||
|
)
|
||||||
|
// review reads the task and completes it on an approved verdict.
|
||||||
|
assertEquals(
|
||||||
|
setOf("task_context", "task_update"),
|
||||||
|
graph.stages[StageId("review")]!!.allowedTools,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
@@ -81,4 +81,28 @@ class RolePipelineWorkflowTest {
|
|||||||
.condition as ArtifactFieldEquals
|
.condition as ArtifactFieldEquals
|
||||||
assertEquals(FieldOperator.NEQ, loop.operator)
|
assertEquals(FieldOperator.NEQ, loop.operator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `task tools are granted to the right stages`() {
|
||||||
|
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!!)
|
||||||
|
|
||||||
|
// analyst opens + searches (read-only on files); creation is approval-gated (T2).
|
||||||
|
assertEquals(
|
||||||
|
setOf("file_read", "ShellTool", "task_search", "task_context", "task_create"),
|
||||||
|
graph.stages[StageId("analyst")]!!.allowedTools,
|
||||||
|
)
|
||||||
|
// implementer owns the lifecycle: claim/submit + the full file set.
|
||||||
|
assertEquals(
|
||||||
|
setOf("file_read", "file_write", "file_edit", "ShellTool") +
|
||||||
|
setOf("task_create", "task_update", "task_context", "task_search"),
|
||||||
|
graph.stages[StageId("implementer")]!!.allowedTools,
|
||||||
|
)
|
||||||
|
// reviewer reads the task and completes it on an approved verdict.
|
||||||
|
assertEquals(
|
||||||
|
setOf("task_context", "task_update"),
|
||||||
|
graph.stages[StageId("reviewer")]!!.allowedTools,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user