Context
On 2026-07-12, the operator traced weeks of severe WebStorm indexing pressure to hundreds of disposable Git worktrees nested under the resident Codex checkout's ignored tmp/ directory. Before cleanup, live Git metadata reported 840 worktrees: 521 below the repository tmp/, 316 below /private/tmp, one resident checkout, and two other entries. git worktree prune --dry-run --verbose classified 839 registrations as stale.
The operator manually deleted the repository tmp/ directory. The same incident pass then pruned Git's stale registrations and removed the final unused external Codex worktree. Live post-cleanup state is one clean worktree: the resident checkout on dev.
This is not the same scope as #12677 / PR #12678. That cleanup is deliberately limited to .claude/worktrees/; its current JSDoc explicitly says Codex does not create this disk-growth pattern. The incident falsifies that premise. #13241 / PR #13242 also told Codex to keep identity-sensitive worktrees below the clone root. That addressed identity drift, but in Codex Desktop Local mode it turned review isolation into nested, IDE-indexed repository growth.
The Problem
Codex Desktop Local mode already has one identity-bound resident checkout. It can fetch and switch branches in place. Manually creating a worktree or clone for each review adds no required isolation in this mode and leaks persistent nested repositories when lifecycle cleanup is missed.
Three surfaces made the leak durable:
.codex/CODEX.md currently directs worktrees beneath the identity-mapped clone root without distinguishing Local mode from host-managed Worktree mode.
.codex/rules/pr-lifecycle.rules does not prohibit git worktree add or git clone.
/tmp is intentionally ignored, so nested repositories remain invisible to ordinary git status while IDE indexing still sees them.
The result is a recurrent machine-health regression, not a request for a better cleanup schedule.
The Architectural Reality
- Local mode: one resident checkout; review exact heads by fetching and switching or detaching in place, then restore the prior branch.
- Worktree mode: a separate host-managed Codex surface. The app owns placement and lifecycle; an agent must not emulate it with shell-created nested worktrees.
.codex/CODEX.md is the existing Codex-only turn-loaded guard card.
.codex/rules/pr-lifecycle.rules is the existing trusted-project command-policy surface. Codex rule resolution is most-restrictive-wins, so a project forbidden decision remains effective even when a user rule previously allowed the command.
- The Claude cleanup from #12677 remains valid for Claude's explicitly worktree-based harness; broadening it into an automatic delete loop for Codex Local mode would preserve the wrong creation model.
The Fix
- Rewrite the worktree bullet in
.codex/CODEX.md to state the Local-mode invariant: use the resident checkout, fetch/switch in place, and never create a manual clone or worktree inside it. Name host-managed Worktree mode as a distinct lifecycle owner.
- Add project command-policy rules that:
- forbid direct
git worktree add;
- forbid direct
git clone;
- allow non-destructive
git worktree list and git worktree prune diagnostics;
- allow ordinary
git worktree remove, while forbidding git worktree remove --force.
- Verify the policy with
codex execpolicy check and verify the turn-loaded guard-card path.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Evidence |
| Codex Local-mode checkout behavior |
.codex/CODEX.md via the trusted prompt hook |
Fetch and switch/detach in the resident checkout; never shell-create nested clones/worktrees |
Host-managed Worktree mode owns its own external checkout lifecycle |
Hook-path read + card text |
| Direct worktree/clone creation |
.codex/rules/pr-lifecycle.rules |
git worktree add and git clone are forbidden |
Use git fetch + git switch in place |
codex execpolicy check |
| Worktree diagnostics/cleanup |
.codex/rules/pr-lifecycle.rules |
list, prune, and non-force remove remain available; force removal is forbidden |
Inspect dirty state before removal |
codex execpolicy check |
Decision Record impact
Aligned with ADR 0007's compaction taxonomy: this is high-severity, harness-local, and mechanically enforceable, so the right shape is one compact turn-loaded trigger plus command policy. No ADR amendment is required.
Acceptance Criteria
Out of Scope
- Host-managed Codex Worktree mode implementation or lifecycle.
- Claude's
.claude/worktrees/ cleanup contract from #12677.
- Fleet checkout provisioning and peer onboarding.
- IDE exclusion rules, a cleanup daemon, or recreating
tmp/.
Avoided Traps
- Do not hide the symptom from WebStorm. Excluding the leaked directory preserves disk/process waste and makes recurrence quieter.
- Do not automate deletion of a creation pattern Local mode does not need. Prevent creation instead.
- Do not weaken exact-head review. Fetch and switch/detach in place preserves exact-head discipline without parallel repositories.
- Do not globalize this into
AGENTS.md. The mode distinction and command policy are Codex-harness-specific.
Related
- #12677 / PR #12678 — Claude-scoped worktree pruning; its Codex premise was falsified here.
- #13241 / PR #13242 — predecessor identity-safe placement rule; corrected rather than duplicated.
- #15045 / PR #15046 — resident-neutral Codex guard card.
Origin Session ID: 2ad10d40-681f-41aa-b9cf-e09ddaa23e2b
Handoff Retrieval Hints: Codex Local mode nested review worktree leak WebStorm tmp; .codex/CODEX.md; .codex/rules/pr-lifecycle.rules; git worktree list --porcelain.
Authored by GPT-5.6 Sol (Codex Desktop).
Context
On 2026-07-12, the operator traced weeks of severe WebStorm indexing pressure to hundreds of disposable Git worktrees nested under the resident Codex checkout's ignored
tmp/directory. Before cleanup, live Git metadata reported 840 worktrees: 521 below the repositorytmp/, 316 below/private/tmp, one resident checkout, and two other entries.git worktree prune --dry-run --verboseclassified 839 registrations as stale.The operator manually deleted the repository
tmp/directory. The same incident pass then pruned Git's stale registrations and removed the final unused external Codex worktree. Live post-cleanup state is one clean worktree: the resident checkout ondev.This is not the same scope as #12677 / PR #12678. That cleanup is deliberately limited to
.claude/worktrees/; its current JSDoc explicitly says Codex does not create this disk-growth pattern. The incident falsifies that premise. #13241 / PR #13242 also told Codex to keep identity-sensitive worktrees below the clone root. That addressed identity drift, but in Codex Desktop Local mode it turned review isolation into nested, IDE-indexed repository growth.The Problem
Codex Desktop Local mode already has one identity-bound resident checkout. It can fetch and switch branches in place. Manually creating a worktree or clone for each review adds no required isolation in this mode and leaks persistent nested repositories when lifecycle cleanup is missed.
Three surfaces made the leak durable:
.codex/CODEX.mdcurrently directs worktrees beneath the identity-mapped clone root without distinguishing Local mode from host-managed Worktree mode..codex/rules/pr-lifecycle.rulesdoes not prohibitgit worktree addorgit clone./tmpis intentionally ignored, so nested repositories remain invisible to ordinarygit statuswhile IDE indexing still sees them.The result is a recurrent machine-health regression, not a request for a better cleanup schedule.
The Architectural Reality
.codex/CODEX.mdis the existing Codex-only turn-loaded guard card..codex/rules/pr-lifecycle.rulesis the existing trusted-project command-policy surface. Codex rule resolution is most-restrictive-wins, so a projectforbiddendecision remains effective even when a user rule previously allowed the command.The Fix
.codex/CODEX.mdto state the Local-mode invariant: use the resident checkout, fetch/switch in place, and never create a manual clone or worktree inside it. Name host-managed Worktree mode as a distinct lifecycle owner.git worktree add;git clone;git worktree listandgit worktree prunediagnostics;git worktree remove, while forbiddinggit worktree remove --force.codex execpolicy checkand verify the turn-loaded guard-card path.Contract Ledger Matrix
.codex/CODEX.mdvia the trusted prompt hook.codex/rules/pr-lifecycle.rulesgit worktree addandgit cloneare forbiddengit fetch+git switchin placecodex execpolicy check.codex/rules/pr-lifecycle.ruleslist,prune, and non-forceremoveremain available; force removal is forbiddencodex execpolicy checkDecision Record impact
Aligned with ADR 0007's compaction taxonomy: this is high-severity, harness-local, and mechanically enforceable, so the right shape is one compact turn-loaded trigger plus command policy. No ADR amendment is required.
Acceptance Criteria
.codex/CODEX.mddistinguishes resident-checkout Local mode from host-managed Worktree mode and forbids manual nested clones/worktrees in Local mode..codex/rules/pr-lifecycle.rulesforbids directgit worktree addandgit clone.git worktree list,git worktree prune, and non-forcegit worktree remove, while forbiddinggit worktree remove --force.codex execpolicy checkproves the forbidden/allowed decisions against the combined project and resident rule sets.tmp/directory.Out of Scope
.claude/worktrees/cleanup contract from #12677.tmp/.Avoided Traps
AGENTS.md. The mode distinction and command policy are Codex-harness-specific.Related
Origin Session ID:
2ad10d40-681f-41aa-b9cf-e09ddaa23e2bHandoff Retrieval Hints:
Codex Local mode nested review worktree leak WebStorm tmp;.codex/CODEX.md;.codex/rules/pr-lifecycle.rules;git worktree list --porcelain.Authored by GPT-5.6 Sol (Codex Desktop).