fix(kernel): require tool activity for produce-less stage completion
A stage declaring no `produces` passed verifyProduces vacuously, letting an agent stage_complete with zero work. Gate on allowedTools: a produce-less stage with tools available must have >=1 ToolInvocationRequestedEvent scoped to its stageId, else Failure(retryable). Produce-less + no tools is exempt (only stage_complete is ever offered), so pure-reasoning stages aren't bricked.
This commit is contained in:
+15
-1
@@ -705,7 +705,21 @@ abstract class SessionOrchestrator(
|
||||
stageId: StageId,
|
||||
stageConfig: StageConfig,
|
||||
): StageExecutionResult {
|
||||
if (stageConfig.produces.isEmpty()) return StageExecutionResult.Success(emptyList())
|
||||
if (stageConfig.produces.isEmpty()) {
|
||||
if (stageConfig.allowedTools.isEmpty()) return StageExecutionResult.Success(emptyList())
|
||||
val ranTool = eventStore.read(sessionId).any {
|
||||
(it.payload as? ToolInvocationRequestedEvent)?.stageId == stageId
|
||||
}
|
||||
if (ranTool) return StageExecutionResult.Success(emptyList())
|
||||
log.error(
|
||||
"[Orchestrator] stage declared no artifacts and ran no tools " +
|
||||
"session=${sessionId.value} stage=${stageId.value}",
|
||||
)
|
||||
return StageExecutionResult.Failure(
|
||||
"stage ${stageId.value} declared no artifacts and ran no tools",
|
||||
retryable = true,
|
||||
)
|
||||
}
|
||||
val producedIds = stageConfig.produces.map { it.name }.toSet()
|
||||
val present = eventStore.read(sessionId)
|
||||
.mapNotNull { (it.payload as? ArtifactCreatedEvent)?.artifactId }
|
||||
|
||||
Reference in New Issue
Block a user