fix(pipeline): register command-step output_artifacts for downstream injection#1491
Merged
Merged
Conversation
…injection Closes #1490. Problem ======= `type: command` steps that wrote files declared in `output_artifacts` never populated `execution.ArtifactPaths[step.ID+":"+art.Name]`. The persona/adapter dispatch path called `writeOutputArtifacts` after the adapter returned (executor.go:3572-3583); the command dispatch path returned directly from `executeCommandStep` to `validateStepContracts` without ever registering the path. Downstream `memory.inject_artifacts` lookup (executor.go:4555) missed on every command-step source, fell through to the stdout-fallback branch, and (since command scripts almost never echo the artifact bytes to stdout) wrote a **0-byte file** under `.agents/artifacts/<as-name>`. The receiving persona then read empty input and short-circuited. The pipeline reported success. Real-world hit: `ops-pr-respond 1472` posted "No findings" to the PR even though `filter-scope` had produced 15 valid security findings — because the planner persona received empty `scoped_findings`. Fix === Call `writeOutputArtifacts(execution, step, workspacePath, nil)` after `executeCommandStep` returns successfully on both dispatch paths (`executeStep` at ~1786, and the `executeGraphPipeline` callback at ~1318). The function already handles the "script wrote the file, don't overwrite" case via `os.Stat(artPath) == nil` (line 4715) — for command steps this is always the path taken. Test ==== `TestCommandStepOutputArtifactsRegisteredForInjection` reproduces the bug shape: a command step writes JSON to a declared output_artifact, then a downstream persona consumes it via `inject_artifacts`. Without the fix the injected file is 0 bytes; with the fix it contains the JSON the command produced. Verified failing without the executor.go edit and passing with it.
This was referenced Apr 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1490.
Problem
type: commandsteps that wrote files declared inoutput_artifactsnever populatedexecution.ArtifactPaths[step.ID+\":\"+art.Name]. The persona/adapter dispatch path calledwriteOutputArtifactsafter the adapter returned (executor.go:3572-3583); the command dispatch path returned directly fromexecuteCommandSteptovalidateStepContractswithout ever registering the path.Downstream
memory.inject_artifactslookup (executor.go:4555) missed on every command-step source, fell through to the stdout-fallback branch, and (since command scripts almost never echo the artifact bytes to stdout) wrote a 0-byte file under.agents/artifacts/<as-name>. The receiving persona then read empty input and short-circuited. The pipeline reported success.Real-world hit
ops-pr-respond 1472(runops-pr-respond-20260428-182026-1f67) posted "No findings" to PR #1472 — even thoughfilter-scope(a command step) had produced 15 valid security findings. The planner persona received emptyscoped_findings. Pipeline status: green. Deliverable: wrong.This is exactly the failure mode "green ≠ correct" — masked from CI, masked from web UI, only caught by reading the actual JSON outputs after the run.
Fix
Call
writeOutputArtifacts(execution, step, workspacePath, nil)afterexecuteCommandStepreturns successfully on both dispatch paths:executeStepat ~1786 (the linear walker)executeGraphPipelinecallback at ~1318 (the DAG walker)writeOutputArtifactsalready handles the "script wrote the file, don't overwrite" case viaos.Stat(artPath) == nil(line 4715) — for command steps this is always the branch taken.Test
TestCommandStepOutputArtifactsRegisteredForInjectionreproduces the bug shape: a command step writes JSON to a declared output_artifact, then a downstream persona consumes it viainject_artifacts. Without the executor.go change the injected file is 0 bytes; with the change it contains the JSON the command produced.I confirmed locally:
git stashthe executor.go fix → test fails ("0 is not greater than 0"). Restore → passes.Test plan
go test ./internal/pipeline/...— greenops-pr-respond 1472after merge — expect substantive PR comment listing real findings