fix(missions): a root-owned COMMIT_EDITMSG must not block delivery
Mission 019fcd0c produced correct work — a reviewed, tested function plus a REVIEW.md quoting a real cargo test summary — and delivered none of it: git commit → exit 128: could not open '.git/COMMIT_EDITMSG': Permission denied The agent ran `git commit` itself inside the mission container (as root), leaving that file owned by root at 0644. core.sharedRepository covers objects and refs — .git/index lands at 0666, which is why commits work at all — but not COMMIT_EDITMSG, which git writes with the default umask. Unlinking works where overwriting does not: removing a file needs write permission on the DIRECTORY, and .git/ is owned by the server. Silent on failure by design, so the commit reports the real error rather than this speculative cleanup. Third distinct instance of the same uid-split class (objects, then the capture base, now this). The pattern holds: the checkout is one directory written by two users, and each new file git touches is a new opportunity. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
deb60be98d
commit
4ff4e6f7ee
@@ -583,6 +583,7 @@ pub async fn commit_phase_work(
|
||||
String::new()
|
||||
}
|
||||
);
|
||||
clear_stale_commit_editmsg(repo);
|
||||
git(repo, &["commit", "--no-verify", "-m", &message]).await?;
|
||||
}
|
||||
|
||||
@@ -878,6 +879,34 @@ impl TestOutcome {
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove a `COMMIT_EDITMSG` the agent left behind as root.
|
||||
///
|
||||
/// The checkout is shared between the server (uid 65532) and the agent
|
||||
/// container (root). `core.sharedRepository` makes git create *objects and
|
||||
/// refs* group-writable — `.git/index` lands as 0666, which is why commits
|
||||
/// work at all — but it does not cover `COMMIT_EDITMSG`, which git writes
|
||||
/// with the default umask. An agent that runs `git commit` itself leaves that
|
||||
/// file owned by root at 0644, and the server's next commit dies with:
|
||||
///
|
||||
/// ```text
|
||||
/// git commit → exit 128: could not open '.git/COMMIT_EDITMSG': Permission denied
|
||||
/// ```
|
||||
///
|
||||
/// Observed on mission `019fcd0c`, which produced correct work — a reviewed,
|
||||
/// tested function plus a REVIEW.md quoting a real `cargo test` summary — and
|
||||
/// then delivered none of it.
|
||||
///
|
||||
/// Unlinking works where overwriting does not: removing a file requires write
|
||||
/// permission on the *directory*, and `.git/` is owned by the server. Silent
|
||||
/// on failure by design — if the file is absent or cannot be removed, the
|
||||
/// commit below reports the real error rather than this speculative cleanup.
|
||||
fn clear_stale_commit_editmsg(repo: &Path) {
|
||||
let msg = repo.join(".git/COMMIT_EDITMSG");
|
||||
if msg.exists() {
|
||||
let _ = std::fs::remove_file(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark a phase as impossible to capture, so it stops being selected.
|
||||
///
|
||||
/// A phase whose checkout has already been reaped can never be captured. It
|
||||
|
||||
Reference in New Issue
Block a user