Repository navigation
D: settle deferred output on the container's exit, not the acknowledgement exec - #77
Merged
Merged
Conversation
…ement exec The wrapper exits as soon as it sees the acknowledgement file, and that exit tears the container down and can SIGKILL the acknowledging `docker exec` before it reports success. The supervisor treated that exec status as a capture failure, so "delimits READY after finite newline-free stderr" failed intermittently in the real-docker job (run 36470233043). A failed acknowledgement is now retried until one succeeds, the container exits, or a stop ends the invocation, and deferred output is accepted only if the container exited with the READY status. The acknowledgement script is idempotent, so a retry repairs a file an earlier attempt left partial. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The lifecycle changes are bounded, fail closed, and covered by targeted race and integration tests.
Review effort: Balanced
Findings: None
What changed in this PR
Fixes deferred-output acknowledgement races by using the container’s exit status as the authoritative outcome.
Changes:
- Adds idempotent acknowledgement creation and retries.
- Validates container exit against the READY status.
- Adds mocked race tests and real-Docker acknowledgement tests.
| File | Description |
|---|---|
agents/adapters/supervisor.ts |
Implements acknowledgement retry and exit-based settlement. |
test/agent-deferred-acknowledgement.test.ts |
Covers acknowledgement and exit interleavings. |
test/agent-supervisor.test.ts |
Verifies acknowledgement-file behavior in Docker. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
Fixes the intermittent real-Docker failure of
container invocation supervisor > delimits READY after finite newline-free stderr(run 36470233043, commit3d52c0d).Diagnosis
The failing assertion was
stopReason(line 541), not the stderr check. "trailing-diagnostic" appears in the error only becauseresult.stderris that assertion's message. The full stderr wastrailing-diagnostic\n[codeboost: capture-failure: Deferred output acknowledgement failed.], so stderr capture worked.After READY, the supervisor writes
/run/codeboost-control/collected-<token>withdocker execand used to fail the invocation if that exec failed. The wrapper (probe.sh) polls every 50 ms and exits as soon as the file holds the token. Its exit tears the container down and SIGKILLs the exec if it has not finished yet. On real Docker, an exec that stays alive briefly after writing the file exits with 137. In production only fsync, fstat, close and Node shutdown remain after the write, so the race is rare.Change
capture-failure. The result no longer depends on the order of the exec failure and the container exit.ACKNOWLEDGEMENT_SCRIPTis idempotent. It keeps a complete file, and it unlinks and rewrites a partial one. Root has no capabilities in the container, so it cannot reopen its own0444file for writing. Symlinks are still refused.Known limit: a container killed from outside with a status equal to the READY status (for example 137) cannot be told apart. Its output was already collected in full by then, and the status already reports a failure. Closing this completely would need a "collected" frame from
probe.sh, which is out of scope here.Tests
test/agent-deferred-acknowledgement.test.ts(mocked Docker, 7 tests) covers:Against the previous supervisor, 6 of the 7 fail; the two race cases fail with the exact CI message
AssertionError: trailing-diagnostic. The nonzero-status case passes on both, because the old code handled it the same way.test/agent-supervisor.test.ts(real Docker) runs the script with--cap-drop=ALL. It checks a fresh write, a repeat, repairs of an empty and a partial file, the file's mode and owner, and that a symlink is refused. The oldO_EXCL-only script fails the repeat.Local results on
035cf59:tsc --noEmitis clean.The local real-Docker suite also shows about 10 failures that are unrelated to this change. They come from name conflicts with stale
codeboost-agent-*containers left on the local daemon, and test container names are deterministic. The exact-head CIreal-dockerresult is the one to use.Review rounds
O_EXCL).🤖 Generated with Claude Code