feat(missions): make copy-in/copy-out the default filesystem model
Copy mode shipped opt-in so that changing how every mission receives its
code required someone to type it. Four production missions and a
fail-closed harness later, opt-in is the riskier setting: the bind path
is the one with four documented work-loss incidents, and leaving it as
the default means the untested path runs whenever nobody sets the
variable. `CLAWMATES_MISSION_FS=bind` still selects it; anything else —
unset, empty, misspelt — gets copy mode, so a typo lands on the safer
path rather than the one being retired.
Also fixes a real leak found while scoping the deletion below: the git
helper built its `safe.directory` argument with `Box::leak`, justified as
"the process is short-lived". That is true of a CLI and false of cm-api,
which is a long-running server — so it leaked one allocation per git
call, growing with every phase of every mission.
The A5 deletion is NOT done here, and two of its items should never be
done:
- `scrub_remote_credentials` is a security control, not a uid
workaround. Copy mode uploads the whole `.git` into a container the
agent controls as root, which makes stripping the token from
`.git/config` more necessary, not less.
- `has_local_work` / `checkout_in_use` guard `fetch_and_reset` at every
phase launch and have nothing to do with who writes the checkout.
The host checkout still persists across phases under copy mode —
mission `019fcf62` shows the marker firing there. Deleting them
reintroduces PRIOR-PHASE-WORK-WAS-LOST.
The rest (`share_repository_across_uids`, `clear_stale_commit_editmsg`,
`-c safe.directory`) are genuinely obsolete under copy mode but stay
while `bind` remains selectable: a workaround may only be deleted once
the situation it works around can no longer be chosen.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3c91d0e172
commit
4f6719c80e
@@ -470,22 +470,27 @@ pub async fn capture_phase_diff_at(
|
||||
|
||||
/// Run git in `repo`, returning stdout.
|
||||
///
|
||||
/// Every invocation carries `-c safe.directory`: the server clones as uid
|
||||
/// 65532 while agents write into the same tree as root, so without it git
|
||||
/// refuses the repository outright — the failure that had the phase evaluator
|
||||
/// silently falling back to guesswork.
|
||||
/// Every invocation carries `-c safe.directory`: under `CLAWMATES_MISSION_FS=bind`
|
||||
/// the server clones as uid 65532 while agents write into the same tree as
|
||||
/// root, so without it git refuses the repository outright — the failure that
|
||||
/// had the phase evaluator silently falling back to guesswork. Copy mode makes
|
||||
/// the tree single-uid and this redundant, but it stays while the bind path is
|
||||
/// still selectable: a workaround may only be deleted once the situation it
|
||||
/// works around can no longer be chosen.
|
||||
async fn git(repo: &Path, args: &[&str]) -> Result<String, String> {
|
||||
let repo_s = repo.display().to_string();
|
||||
let mut full = vec![
|
||||
"-C",
|
||||
&repo_s,
|
||||
"-c",
|
||||
// Leaked into a `String` so it can live in a `&str` slice alongside
|
||||
// the borrowed args; the process is short-lived and this is one
|
||||
// allocation per git call.
|
||||
Box::leak(format!("safe.directory={repo_s}").into_boxed_str()),
|
||||
// Owned, not `Box::leak`. The leak was justified as "the process is
|
||||
// short-lived", which is true of a CLI and false of cm-api — it is a
|
||||
// long-running server, so that was one permanently leaked allocation per
|
||||
// git call, growing with every phase of every mission for the life of the
|
||||
// process.
|
||||
let mut full: Vec<String> = vec![
|
||||
"-C".into(),
|
||||
repo_s.clone(),
|
||||
"-c".into(),
|
||||
format!("safe.directory={repo_s}"),
|
||||
];
|
||||
full.extend_from_slice(args);
|
||||
full.extend(args.iter().map(|a| (*a).to_string()));
|
||||
let (name, email) = commit_identity();
|
||||
let out = tokio::process::Command::new("git")
|
||||
.args(&full)
|
||||
|
||||
Reference in New Issue
Block a user