Memory Phase 2 cannot create its gix baseline under WSL /mnt/c (DrvFS/9p)
Summary
When Codex runs as a WSL app-server while CODEX_HOME is the normal Windows
Desktop home exposed at /mnt/c/..., memory Phase 2 deterministically fails at
workspace preparation. The same installed Codex binary and workspace succeed
on WSL-native storage.
The persisted job error is only:
failed_prepare_workspace
An earlier run can first finish the consolidation agent and then fail the
post-success baseline reset as failed_workspace_commit. The next retry sees
the resulting unborn repository and fails earlier asfailed_prepare_workspace.
The app-server stderr has the actionable context:
failed preparing memory workspace: load tree .../memories/extensions/ad_hoc
With a real memory tree the failing child wasextensions/ad_hoc/notes.
Environment
- Windows 11 with WSL2 Ubuntu
- Codex Desktop configured to run the app-server in WSL
- WSL agent:
codex-cli 0.144.0-alpha.4 - Source checked against current main commit
9e552e9d15ba52bed7077d5357f3e18e330f8f38; the reproduced local snapshot was
54b8f112a3815ead40ebcd50f9c2f2fc786e26fb, and intervening commits do not
modify the baseline implementation
gix 0.81.0- Memory root filesystem: WSL DrvFS/9p for the Windows-backed Codex home
Reproduction
Using isolated Codex homes and SQLite state with the same installed binary:
- Start a root app-server turn with memories enabled.
- Let Phase 2 prepare a memory root containing a nested directory.
- On a WSL-native temporary directory, the baseline commit succeeds and Phase
2 advances to the consolidation agent.
- On
/mnt/c, Phase 2 fails atload tree <nested child>, leaving an unborn
repository and loose child objects.
The failure also reproduces from an empty memory directory after Codex seeds
only its standard extensions/ad_hoc/instructions.md. It does not require user
notes or unusual filenames.
Command-line Git can initialize and commit the full same workspace on /mnt/c,
so this is not a general Git/content failure.
Likely cause
codex-rs/git-utils/src/baseline.rs::write_tree writes each child tree and then
immediately reopens it solely to test whether it is empty:
let oid = write_tree(repo, &path)?;
let tree = repo.find_tree(oid)
.with_context(|| format!("load tree {}", path.display()))?;
if tree.decode()?.entries.is_empty() {
continue;
}
The write succeeds and the loose tree is present afterward, but the immediatefind_tree fails on DrvFS/9p. WSL-native ext4 does not fail.
Suggested fix
Avoid reopening the just-written child object. Have the recursive function
return the object ID plus whether its entry vector was empty, or returnOption<ObjectId> for non-root children. The caller already has enough
information to omit empty directories.
Please add a nested-directory baseline test and, if available, a WSL DrvFS/9p
integration test. It would also help if the full error chain were persisted or
surfaced by the memory diagnostics instead of reducing it tofailed_prepare_workspace.
Impact
Phase 2 cannot consolidate ad-hoc notes into MEMORY.md ormemory_summary.md for the common Windows Desktop plus WSL layout. Retrying on
the same path repeats the failure, and manually creating one baseline is not
durable because successful consolidation resets .git through the same code.