AI draft 07777112-074d-490d-83ba-aaed468e2100¶
Status: unverified worker output; review before use.
Short review report:
1. **Project changes can evade task binding.**
Evidence: `_binding()` prefers `project_name` over `project_id`; a task moved to another project with the same name produces the same digest.
Verify with two task fixtures having identical `project_name` but different `project_id`; `_preflight()` remains eligible.
2. **A pause, task change, or quota change can race provider dispatch.**
Evidence: `_run_one()` performs `_preflight()`, then marks the job `running`, then invokes `backend_runner()` without another task/capacity/pause check.
Verify by mutating the task or creating `paused` between preflight and `backend_runner`; the backend is still called.
3. **Successful empty or non-text results are accepted.**
Evidence: `_run_one()` accepts any `result` where `ok is True` and writes `str(result.get("result", ""))`, then enters `awaiting_review`.
Verify with a backend returning `{"ok": True}` or `{"ok": True, "result": None}`; the job becomes reviewable with an empty artifact.
4. **The requested model is not validated against the model actually used.**
Evidence: `_run_one()` records `actual_model` but never compares it with `requested_model`; Codex’s backend result explicitly sets `actual_model` to `None`.
Verify with a successful backend fixture reporting a different model; the job still reaches `awaiting_review`.
5. **Review accepts jobs without validating retained artifacts.**
Evidence: `review()` checks only `status == "awaiting_review"` and never verifies `artifact_dir`, `metadata.json`, or `result.md`.
Verify by deleting or corrupting `result.md` after completion, then calling `review()`; acceptance still succeeds.