Repository navigation
[Bug]: native Windows Codex App settlement plans emit a POSIX-only Turn reference #7808
Description
Preflight
- I searched existing issues and discussions for this behavior.
- This report is not an unpatched security vulnerability.
- The report and attachments contain no credentials or private/internal material.
Issue origin
Observed or reproduced in a real environment.
LoopX version or commit
70f643153ea773b7bc1ef71bdb06095b0744bd6d (current upstream main).
Host or runtime surface
Codex App on native Windows with PowerShell 7 or Windows PowerShell 5.1.
LoopX area
Control plane (goals, todos, quota, scheduler, registry, runtime).
Problem
Impact: Native Windows Codex App admission without an explicit Turn returns a machine-readable settlement plan whose validation, writeback, spend, and terminal-closeout commands bind --turn-instance-id "${LOOPX_TURN:?}". PowerShell does not implement POSIX ${name:?} expansion, so it passes an empty argument even when $LOOPX_TURN is set; the CLI rejects that command with QUOTA_VALIDATION_FAILED. The returned closeout/recovery recipe therefore cannot settle the same Windows host that produced it without manual command rewriting.
This affects the documented no-Turn Codex App path (quota should-run --codex-app) and every generated settlement step from that plan. It is generated deterministically on each affected request, not an intermittent shell error. The native Windows path is a supported product surface and has a required windows-powershell CI lane. This is the same host-runnable-command contract repaired for onboarding and heartbeat bootstrap in #7158 / #7160: loopx/project_prompt.py already renders the heartbeat Turn argument as $LOOPX_TURN on native Windows, but the settlement-plan owner was not included.
Minimal reproduction
On native Windows at 70f643153, the pure plan builder emits the broken reference:
uv run --extra test python -c "from loopx.control_plane.quota.effect_program import build_codex_app_settlement_plan as b; p=b(goal_id='goal', agent_id='agent', todo_id='todo', scoped_cli_args='', lifecycle_actor_args=''); print(p.as_dict()['identity']['turn_instance_id']); print(next(s['command_template'] for s in p.as_dict()['ordered_steps'] if s.get('command_template') and 'spend-slot' in s['command_template']))"It prints ${LOOPX_TURN:?} as the identity and inside the quota spend-slot command. The shell behavior is independently reproducible:
$LOOPX_TURN = 'turn-repro-1'
python -c "import sys; print(sys.argv[1:])" "${LOOPX_TURN:?}"Observed: ['']. Expected: $LOOPX_TURN is forwarded as turn-repro-1.
Feeding the emptied Turn through the real quota spend-slot command returns rc 1:
error_code: QUOTA_VALIDATION_FAILED
reason: turn_instance_id must be 1-128 public-safe letters, numbers, or ._:-
state: blocked_validation
Expected behavior
A settlement plan produced on native Windows should emit PowerShell-runnable commands, using $LOOPX_TURN (and an explicit missing-value guard if required), while POSIX hosts retain the existing "${LOOPX_TURN:?}" output byte-for-byte. The returned validation/writeback/spend/closeout commands should forward the concrete Turn selected by the host rather than an empty value.
Actual behavior
The plan identity and generated commands keep the POSIX-only reference on native Windows. PowerShell treats it as an unknown variable reference and forwards an empty Turn, so the first settlement command that validates the identity fails and the remaining writeback/spend/closeout steps cannot run.
Additional context
- Historical continuation: [Bug]: native Windows onboarding and heartbeat prompts still print POSIX-only install and connect commands #7158 fixed the same platform contract for onboarding and heartbeat bootstrap in fix(cli): print host-runnable onboarding and heartbeat commands #7160, but the App settlement-plan renderer remained unchanged.
- Reachability:
build_accountable_work_item_settlement_plandeliberately creates an App settlement plan whenturn_instance_idisNone;build_codex_app_settlement_plansupplies the POSIX sentinel as its default. - Reference:
docs/book/en/chapters/06-codex-app.mddocuments thequota should-run --codex-appcross-check, anddocs/quota-allocation.mddocuments the shared quota spend route. - The equivalent host-aware rendering already exists in
loopx/project_prompt.py(render_turn_bootstrapand its Windows heartbeat guard).
Activity
coordination: record issue loopx-project#7808 for agent-m7c2