Problem
The mode field on the Control chat request is validated server-side and rejected with a 400. The permissions field is not. It is a free-form string compared by exact match against "Skip Permissions". Any drift (casing, whitespace, a stale client) silently downgrades every worker to AUTO.
AUTO maps to Codex workspace-write, which keeps Git metadata read-only. Workers write files but cannot commit, so delivery fails with "Untracked files remain". The code comment already says this. The user is never told that "Approve Edits" plus a Codex worker cannot deliver.
Where
app/api/control/chat/_lib/authorized-request.ts:37-48 validates mode only.
app/api/control/chat/_lib/types.ts:46: permissions?: string | null.
lib/control/types.ts:10-16: MissionPermissions and MISSION_PERMISSION_OPTIONS are the allowed values.
lib/agents/orchestrator/tools/planning-impl.ts:28-38 (resolveWorkerExecutionMode).
lib/harness/codex-permissions.ts:10-14 maps AUTO to workspace-write.
Fix
- In
authorized-request.ts, validate permissions against MISSION_PERMISSION_OPTIONS exactly like mode. Return 400 with "Invalid control permissions." on anything else. Type the field as MissionPermissions | null in types.ts.
- In the composer, when permissions is "Approve Edits" and the selected worker agent is Codex, show an inline note under the picker: "Codex workers cannot commit in this mode. Choose Skip Permissions to allow delivery." Do not block sending.
Exit criteria
Out of scope
Making Codex commit in workspace-write. That is a harness limitation.
https://claude.ai/code/session_01SQ4nS96XYRztd5w9QkubPf
Problem
The
modefield on the Control chat request is validated server-side and rejected with a 400. Thepermissionsfield is not. It is a free-form string compared by exact match against"Skip Permissions". Any drift (casing, whitespace, a stale client) silently downgrades every worker toAUTO.AUTOmaps to Codexworkspace-write, which keeps Git metadata read-only. Workers write files but cannot commit, so delivery fails with "Untracked files remain". The code comment already says this. The user is never told that "Approve Edits" plus a Codex worker cannot deliver.Where
app/api/control/chat/_lib/authorized-request.ts:37-48validatesmodeonly.app/api/control/chat/_lib/types.ts:46:permissions?: string | null.lib/control/types.ts:10-16:MissionPermissionsandMISSION_PERMISSION_OPTIONSare the allowed values.lib/agents/orchestrator/tools/planning-impl.ts:28-38(resolveWorkerExecutionMode).lib/harness/codex-permissions.ts:10-14mapsAUTOtoworkspace-write.Fix
authorized-request.ts, validatepermissionsagainstMISSION_PERMISSION_OPTIONSexactly likemode. Return 400 with"Invalid control permissions."on anything else. Type the field asMissionPermissions | nullintypes.ts.Exit criteria
tests/unit/for the Control chat route: a body withpermissions: "skip permissions"(wrong case) returns 400. Must fail onmain."Skip Permissions"and"Approve Edits"are both accepted.tests/e2e/control-composer.spec.ts: select Approve Edits and a Codex worker, assert the note; switch to Skip Permissions, assert it is gone.pnpm lint,pnpm typecheck,pnpm test,pnpm test:unitpass.Out of scope
Making Codex commit in
workspace-write. That is a harness limitation.https://claude.ai/code/session_01SQ4nS96XYRztd5w9QkubPf