Skip to content

fix(#2378): report failure when agent errors with no commits - #2381

Closed
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
agent/2378-status-comment-agent-error
Closed

fix(#2378): report failure when agent errors with no commits#2381
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
agent/2378-status-comment-agent-error

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

When the code agent exits non-zero (e.g., 429 RESOURCE_EXHAUSTED) but produces no commits, the status comment previously reported "Success" because runErr stayed nil — the OS-level execution succeeded even though the agent session failed.

Root cause: lastExitCode was declared after the status and post-script defers, so neither closure could read it. The post-script then hit the "no changed files — nothing to do" path and exited 0, leaving runErr nil and the status as "success".

Changes:

  • Move lastExitCode declaration before the post-script defer so both
    closures can reference it
  • Pass AGENT_EXIT_CODE env var to the post-script so it can distinguish
    agent errors from intentional no-ops
  • In post-code.sh, check AGENT_EXIT_CODE at both "nothing to do" exit
    points (no branch and no changed files); exit 1 when agent errored
  • Update report_failure_to_issue() to produce a distinct message for
    agent errors ("Code agent failed") vs post-script errors
  • Add shell tests covering agent error detection at both exit points
    and the error comment content

Intentional no-change runs (agent exits 0, no commits) are unaffected — the AGENT_EXIT_CODE check only triggers on non-zero exit codes.


Closes #2378

Post-script verification

  • Branch is not main/master (agent/2378-status-comment-agent-error)
  • Secret scan passed (gitleaks — c7ad0264ec1cd794d0f9089f4479ae7614e2321a..HEAD)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

@github-actions

Copy link
Copy Markdown

E2E tests did not run

E2E tests run automatically for org/repo members and collaborators on pull requests.

For other contributors, a maintainer must add the ok-to-test label after the latest push.

See E2E testing guide for details.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown

Site preview

Preview: https://b6544880-site.fullsend-ai.workers.dev

Commit: 503a6d88fea06a82d060cb54d807a76fab83a8c5

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 17, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:54 AM UTC · Completed 10:06 AM UTC
Commit: e385941 · View workflow run →

@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/cli/run.go 0.00% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@fullsend-ai-review

Copy link
Copy Markdown

Looks good to me

Low

  • [test-integrity] internal/scaffold/fullsend-repo/scripts/post-code-test.sh:289 — The detect_noop test helper returns 1 for error cases, but run_noop_test suppresses the exit code with || true and only checks the output prefix. Consider adding a test that verifies the return code is non-zero for error:branch and error:files cases, since the production code relies on exit 1 triggering the ERR trap.
  • [comment-style] internal/cli/run.go:510 — The 5-line comment for lastExitCode is notably longer than the similar validationPassed declaration comment. The extra length is justified by the non-obvious design decision, but could be tightened.
  • [comment-formatting] internal/cli/run.go:540 — Two-step postCmd.Env = append(...) pattern (first build base env, then add extra var) is a minor style deviation from single-append patterns elsewhere. This is a common Go idiom and reads clearly.

@@ -280,15 +289,17 @@ run_noop_test() {
local test_name="$1"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] test-integrity

The detect_noop test helper returns 1 for error cases, but run_noop_test suppresses the exit code with || true and only checks the output prefix. Consider adding a test that verifies the return code is non-zero for error:branch and error:files cases, since the production code relies on exit 1 triggering the ERR trap.

Comment thread internal/cli/run.go
// ADR 0022's zero-trust model.
var validationPassed bool

// lastExitCode is declared here (before the post-script and status

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] comment-style

The 5-line comment for lastExitCode is notably longer than the similar validationPassed declaration comment. The extra length is justified by the non-obvious design decision, but could be tightened.

Comment thread internal/cli/run.go
@@ -532,6 +540,7 @@ func runAgent(ctx context.Context, agentName, fullsendDir, outputBase, targetRep
postCmd := exec.Command(h.PostScript)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] comment-formatting

Two-step postCmd.Env = append(...) pattern (first build base env, then add extra var) is a minor style deviation from single-append patterns elsewhere. This is a common Go idiom and reads clearly.

When the code agent exits non-zero (e.g., 429 RESOURCE_EXHAUSTED) but
produces no commits, the status comment previously reported "Success"
because runErr stayed nil — the OS-level execution succeeded even
though the agent session failed.

Root cause: lastExitCode was declared after the status and post-script
defers, so neither closure could read it. The post-script then hit the
"no changed files — nothing to do" path and exited 0, leaving runErr
nil and the status as "success".

Changes:
- Move lastExitCode declaration before the post-script defer so both
  closures can reference it
- Pass AGENT_EXIT_CODE env var to the post-script so it can distinguish
  agent errors from intentional no-ops
- In post-code.sh, check AGENT_EXIT_CODE at both "nothing to do" exit
  points (no branch and no changed files); exit 1 when agent errored
- Update report_failure_to_issue() to produce a distinct message for
  agent errors ("Code agent failed") vs post-script errors
- Add shell tests covering agent error detection at both exit points
  and the error comment content

Intentional no-change runs (agent exits 0, no commits) are unaffected —
the AGENT_EXIT_CODE check only triggers on non-zero exit codes.

Closes #2378
@rh-hemartin
rh-hemartin force-pushed the agent/2378-status-comment-agent-error branch from e385941 to 503a6d8 Compare July 1, 2026 08:39
@rh-hemartin
rh-hemartin requested a review from a team as a code owner July 1, 2026 08:39
@qodo-code-review

Copy link
Copy Markdown

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: test

Failed stage: Run make lint-all [❌]

Failed test name: ""

Failure summary:

The action failed during the go vet pre-commit hook (hook id: go-vet) with exit code 1.
go vet
reported a Go compile/vet error in internal/cli/run.go:
- internal/cli/run.go:649:6: lastExitCode
redeclared in this block
- internal/cli/run.go:621:6: other declaration of lastExitCode
Because go
vet failed, the lint-all Makefile target failed at Makefile:78, causing the workflow to exit
(Process completed with exit code 2).

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

390:  detect private key.......................................................Passed
391:  check for added large files..............................................Passed
392:  check for merge conflicts................................................Passed
393:  check json...............................................................Passed
394:  check toml...............................................................Passed
395:  mixed line ending........................................................Passed
396:  ruff (legacy alias)......................................................Passed
397:  ruff format..............................................................Passed
398:  ty check.................................................................Passed
399:  bandit...................................................................Passed
400:  Detect hardcoded secrets.................................................Passed
401:  shellcheck...............................................................Passed
402:  pinact (SHA-pin check)...................................................Passed
403:  Lint GitHub Actions workflow files.......................................Passed
404:  gofmt....................................................................Passed
405:  go vet...................................................................Failed
406:  - hook id: go-vet
407:  - exit code: 1
408:  # github.com/fullsend-ai/fullsend/internal/cli
409:  ##[error]internal/cli/run.go:649:6: lastExitCode redeclared in this block
410:  ##[error]	internal/cli/run.go:621:6: other declaration of lastExitCode
411:  # github.com/fullsend-ai/fullsend/internal/cli
412:  # [github.com/fullsend-ai/fullsend/internal/cli]
413:  ##[error]vet: internal/cli/run.go:649:6: lastExitCode redeclared in this block
414:  lint mint embed sync.....................................................Passed
415:  lint ADR statuses........................................................Passed
416:  lint ADR numbers.........................................................Passed
417:  lint ADR frontmatter.....................................................Passed
418:  lint broken symlinks.....................................................Passed
419:  lint docs link scope.....................................................Passed
420:  lint markdown links......................................................Passed
421:  lint workflow file size..................................................Passed
422:  lint agent doc references................................................Passed
423:  lint-staged (web)........................................................Passed
424:  make: *** [Makefile:78: lint-all] Error 1
425:  ##[error]Process completed with exit code 2.
426:  Post job cleanup.

@ralphbean ralphbean left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an automated comment. We are moving agent content from internal/scaffold/fullsend-repo/ to https://github.com/fullsend-ai/agents -- changes should be made to agent definitions there going forwards.

@ralphbean

Copy link
Copy Markdown
Member

This needs to be on the fullsend-ai/agents repo.

@ralphbean ralphbean closed this Jul 6, 2026
@fullsend-ai-retro

fullsend-ai-retro Bot commented Jul 6, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 6:51 PM UTC · Completed 7:00 PM UTC
Commit: 503a6d8 · View workflow run →

@fullsend-ai-retro

Copy link
Copy Markdown

PR #2381 was a well-implemented fix for issue #2378 (code agent status comment falsely reporting "Success" when agent errors with no commits). The code agent produced a clean 1-commit PR on June 17 touching run.go, post-code.sh, and post-code-test.sh. The review agent approved with 3 low-severity style comments. However, the PR sat unmerged for 19 days. During that gap: (1) the fullsend-ai/agents repo was created on June 26 and post-code.sh migrated there, (2) another PR merged a lastExitCode declaration into run.go on main, and (3) a rebase on July 1 produced a go vet failure from variable redeclaration. On July 6, ralphbean closed the PR without merge, noting that script changes now belong in the agents repo. Issue #2378 remains open with ready-to-code label, risking futile re-dispatch.

Three proposals filed:

  1. Restructure Code agent status comment should reflect actual outcome when no PR is created #2378 to reflect cross-repo split and prevent futile re-dispatch
  2. Evidence for #3050ready-to-code not removed after maintainer rejection
  3. Evidence for #2004 — 19-day review gap caused PR to go stale and become obsolete

Proposals filed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-merge All reviewers approved — ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Code agent status comment should reflect actual outcome when no PR is created

1 participant