Two defects found by running a real coding mission (019fc372) rather than a
test. Both made a coding phase look like it produced nothing.
**Capture measured the wrong baseline.** It diffed the working tree against
HEAD, which is correct only while work stays uncommitted. `rust_sdlc` has a
*committer* role, so committing is the intended path — meaning a mission that
did its job properly leaves a clean tree and captured nothing. That is exactly
what happened: the agent created `DELIVERY_PROBE.md`, committed it as
`aa3be95`, and the artifact recorded `empty: true` beside a commit that
plainly contained the work.
`mission_workspace` now records the clone point in `.git/clawmates-base` (in
`.git/`, so it travels with the checkout, stays invisible to the repository,
and cannot be reached by an agent through its pinned workspace), refreshed
whenever `fetch_and_reset` moves HEAD. Capture diffs from there, covering
committed, staged and unstaged changes in one pass. Checkouts predating the
marker fall back to HEAD and say so via `base_recorded: false`.
**Agents could not create files.** `coding_readwrite` granted `file_edit` but
not `file_write`. `file_edit` replaces an exact existing string and rejects an
empty `old_string`, so creating a new file was impossible. The mission
transcript is unambiguous: "the tool rejected empty old_string... the shell is
restricted", after which the agent worked around it through `shell`. The
comment above that profile has claimed it grants file_write since the day it
was written; the list never contained it.
Also broadens capture from coding/benchmark/security_scan to every phase kind
of a repo-bearing mission: `phase_task_text` tells research phases to "save
findings under /mission/repo/research/", so filtering by kind would have
discarded every research brief such a mission produced.
Regression tests cover committed-only and committed-plus-uncommitted work
against a real git repo.
Co-Authored-By: Claude Opus 5 <[email protected]>
First half of mission delivery: the work is captured before anything is
published. A coding mission has until now produced nothing durable — the
checkout is deleted thirty minutes after completion and `register_artifact`
had no callers at all, so the only surviving output was an LLM narrative of
what the agents said they did.
`capture_phase_diff` writes `diff.patch`, `diffstat.txt` and `delivery.json`
under `<missions_root>/_outputs/<mission>/<phase>/` and registers a
`code_diff` artifact. That directory is a *sibling* of the per-mission
directories the sweeper removes, and outside every bind mount handed to a
container — so teardown cannot take the record with it and agents cannot edit
their own evidence.
Three details that decide whether this works at all:
- `git add --intent-to-add` before diffing. Untracked files are invisible to
`git diff`, and a phase that only *creates* files is the likeliest shape for
generated code — silently capturing an empty patch would be the worst
possible failure. The index is reset afterwards so capture leaves the tree
exactly as the agents left it, which the test asserts.
- Build output is excluded by pathspec (`target`, `node_modules`, `.venv`, …).
A phase that ran `cargo build` leaves a directory larger than the repo.
- An empty diff is still an artifact, flagged `empty: true`. "This coding
phase wrote no code" is currently invisible to an operator and is worth
saying out loud.
`RegisterArtifact` gains `metadata`, which the column has had since 0047 and
nothing ever wrote; the diffstat and base sha go there. No migration needed —
`kind` is unconstrained TEXT and the column already exists.
Tests run against a real `git init` repo rather than a mock: every bug in this
area so far came from git behaving differently than assumed, and a fake git
would have agreed with the assumption. `capture_phase_diff_at` takes explicit
paths so parallel tests cannot race through the process-global
CLAWMATES_MISSIONS_ROOT — the first version of these tests did exactly that
and two of four failed non-deterministically.
Co-Authored-By: Claude Opus 5 <[email protected]>