feat: shell execution correctness + artifact_field_equals condition
- Add field to ProcessResultArtifact ("success"/"failed")
- Materialize ToolResult.Failure as a failed ProcessResult artifact
in the orchestrator, with artifact lifecycle events emitted
- Non-recoverable ToolResult.Failure now fails the stage ("FATAL:")
instead of being silently fed back as LLM context
- Fix enterStage to return Continue on non-retryable failures,
enabling back-edge transitions (fix/retry loops)
- Add ArtifactFieldEquals transition condition with flat and
nested dot-notation field access + FieldOperator enum
(eq, neq, gt, gte, lt, lte)
- Wire artifact_field_equals through ConditionFactory and
TomlWorkflowLoader (condition_field, condition_operator)
- Cache ProcessResult artifact content for evaluation context
- Add 16 tests covering all condition operators and error cases
- DefaultTransitionResolver catches condition evaluation errors
and returns Blocked instead of crashing
This commit is contained in:
+11
@@ -5,8 +5,10 @@ import com.correx.core.transitions.conditions.AllOf
|
||||
import com.correx.core.transitions.conditions.AlwaysTrue
|
||||
import com.correx.core.transitions.conditions.AnyOf
|
||||
import com.correx.core.transitions.conditions.ArtifactAbsent
|
||||
import com.correx.core.transitions.conditions.ArtifactFieldEquals
|
||||
import com.correx.core.transitions.conditions.ArtifactPresent
|
||||
import com.correx.core.transitions.conditions.ArtifactValidated
|
||||
import com.correx.core.transitions.conditions.FieldOperator
|
||||
import com.correx.core.transitions.conditions.Not
|
||||
import com.correx.core.transitions.conditions.VariableEquals
|
||||
import com.correx.core.transitions.graph.TransitionCondition
|
||||
@@ -17,6 +19,7 @@ fun ConditionSpec.toCondition(): TransitionCondition = when (type) {
|
||||
"artifact_absent" -> buildArtifactAbsent()
|
||||
"artifact_validated" -> buildArtifactValidated()
|
||||
"variable_equals" -> buildVariableEquals()
|
||||
"artifact_field_equals" -> buildArtifactFieldEquals()
|
||||
"all_of" -> AllOf(conditions.map { it.toCondition() })
|
||||
"any_of" -> AnyOf(conditions.map { it.toCondition() })
|
||||
"not" -> Not((condition ?: error("condition required for not")).toCondition())
|
||||
@@ -37,3 +40,11 @@ private fun ConditionSpec.buildVariableEquals() =
|
||||
key ?: error("key required for variable_equals"),
|
||||
value ?: error("value required for variable_equals"),
|
||||
)
|
||||
|
||||
private fun ConditionSpec.buildArtifactFieldEquals() =
|
||||
ArtifactFieldEquals(
|
||||
artifactId = ArtifactId(artifactId ?: error("artifact_id required for artifact_field_equals")),
|
||||
field = field ?: error("field required for artifact_field_equals"),
|
||||
value = value ?: error("value required for artifact_field_equals"),
|
||||
operator = operator?.let { FieldOperator.fromString(it) } ?: FieldOperator.EQ,
|
||||
)
|
||||
|
||||
+2
@@ -5,6 +5,8 @@ data class ConditionSpec(
|
||||
val artifactId: String? = null,
|
||||
val key: String? = null,
|
||||
val value: String? = null,
|
||||
val field: String? = null,
|
||||
val operator: String? = null,
|
||||
val conditions: List<ConditionSpec> = emptyList(),
|
||||
val condition: ConditionSpec? = null,
|
||||
)
|
||||
|
||||
+4
@@ -49,6 +49,8 @@ private data class TransitionSection(
|
||||
@param:JsonProperty("condition_artifact_id") val conditionArtifactId: String? = null,
|
||||
@param:JsonProperty("condition_key") val conditionKey: String? = null,
|
||||
@param:JsonProperty("condition_value") val conditionValue: String? = null,
|
||||
@param:JsonProperty("condition_field") val conditionField: String? = null,
|
||||
@param:JsonProperty("condition_operator") val conditionOperator: String? = null,
|
||||
)
|
||||
|
||||
private const val TERMINAL = "done"
|
||||
@@ -112,6 +114,8 @@ class TomlWorkflowLoader(
|
||||
artifactId = t.conditionArtifactId,
|
||||
key = t.conditionKey,
|
||||
value = t.conditionValue,
|
||||
field = t.conditionField,
|
||||
operator = t.conditionOperator,
|
||||
).toCondition(),
|
||||
)
|
||||
}.toSet()
|
||||
|
||||
Reference in New Issue
Block a user