Skip to content

Operation Fork on Windows: read-only branches, .cmd verifier ENOENT, and no-op landings #268

Description

@SethGammon

Summary

Live Operation Fork runs against a fresh demo repository surfaced three
related Windows defects that together prevent forked Codex branches from ever
landing code. Each is reproduced below; all three have verified local fixes.

Environment

  • Windows 11, Node 22.17, git 2.x
  • Codex CLI (npm shim install), Claude Code CLI (no active subscription)
  • Citadel 1.3.0 (main @ ec84f91), target: https://github.com/SethGammon/citadel-fork-demo
  • Full evidence: docs/FINDINGS-run-2026-08-22.md in the demo repository

Finding 1 — fork branches are read-only on Windows

runtimeInvocationForProfile passes --ignore-user-config (defensible,
fail-closed), but on Windows the Codex CLI needs user config
([windows] sandbox = "elevated") to obtain workspace-write enforcement.
Without it, agents explore, spend tokens, then report:
"this session's filesystem is read-only, and approval settings prohibit writes."
A controlled CODEX_HOME override does not restore write access.

Verified fix: append -c windows.sandbox=elevated on win32. Probe result:
file creation succeeds; without it, refused.

Finding 2 — verifier commands that are .cmd shims cannot spawn

Workflow verifier { command: "npm", args: ["test"] } fails shell-free on
Windows (spawnSync('npm')ENOENT), so even successful agent runs get
status: failed with zero evidence credit. Executors already route through
platformInvocation; verifiers did not.

Verified fix: resolve verifier invocations through platformInvocation
and extend nodeEntrypoint with npm/npx mappings.

Finding 3 — no-op landing reports success

Evidence counts working-tree diffs, but selection/landing is revision-bound.
Agents under sandbox isolation cannot run git commit (worktree index.lock
lives outside the writable root), so their changes can never become commits —
and landing a branch whose tip equals the base revision reported landed
with result_revision == target_revision, changing nothing.

Verified fix: applyLanding now reads the selected branch tip and throws
FORK_LANDING_EMPTY when it equals the base revision, plus a regression test.

After the first two fixes

Fork showcase-004 (dual-model: gpt-5.6-sol vs gpt-5.6-luna) produced the
first fully comparable run: both branches passed with 2/2 evidence, and the
comparison honestly returned tie with recommendation: null. Offline
receipt verification returned verified/passed, and replay export leaked no
paths, usernames, objectives, or signer material.

Remaining design question

Sandboxed agents cannot create commits inside worktrees (index.lock is outside
the writable boundary). Landing therefore needs either (a) a Citadel-managed
post-run commit step with its own receipt, or (b) worktree-local git metadata.
Until then, FORK_LANDING_EMPTY converts silent success into an honest block.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions