Codex Security completion rereads unbounded rollout history before Workbench commit
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
Summary
A Codex Security diff scan completed analysis and wrote sealed canonical
artifacts, but the Workbench remained running because finalization performed
an unbounded rollout-token usage scan before committing status=complete.
The affected task graph contained 262 rollout JSONL files totaling about
128.0 GB. The completion command ran after the report was sealed, then returned
a generic workbench_db.py complete-scan command failure without reaching the
Workbench completion transaction.
Environment
- Windows NT 10.0.26200.0
- Codex CLI 0.147.0
- Codex Security plugin 0.1.22
- Bundled Python 3.12.13
- Scan mode: exact Git revision-range diff
The public plugin changelog currently documents 0.1.20 as the latest public
version; I did not downgrade the installed 0.1.22 plugin.
Observed state split
The completion attempt produced valid local artifacts:
report.mdfindings.jsoncoverage.json- sealed
scan-manifest.json - SARIF export
The manifest had a valid sealedAt timestamp and described the scan as
completed. The Workbench database still reported:
status: running
completed_at: null
seal_manifest_digest: null
cost_json: null
The failed scan was preserved. I did not retry completion, cancel/fail it, or
edit the Workbench database.
Root-cause evidence in plugin 0.1.22
complete_scan_locked() currently performs these steps in this order:
- prepare and write/seal the canonical artifacts;
- call
collect_scan_usage()when no explicit cost JSON exists; - only afterward begin the transaction that records artifacts/findings and
updates the Workbench scan tostatus=complete.
collect_scan_usage() recursively discovers the root task and all descendant
tasks, then reads every rollout file from its beginning. It has no wall-time,
total-byte, single-file, or task-count budget.
A metadata-only preflight of the affected graph took under 0.2 seconds and
reported:
threads: 262
rollout files: 262
total bytes: 128,025,586,270
largest file: 5,229,307,791 bytes
No rollout contents are required to detect that this measurement is too large
to run synchronously during completion.
Reproduction
- Use a long-lived Codex task with many descendant tasks and multi-gigabyte
rollout history. - Start a Codex Security diff scan and complete all analysis/reporting phases.
- Save the complete semantic draft.
- Call completion once.
- Observe that canonical artifacts are sealed before rollout usage collection
finishes. - Observe that the completion command fails or is interrupted while the
Workbench row remainsrunningwith no completion timestamp or usage.
As a control, I repeated the exact scan in a brand-new non-forked task. Its
three rollout files totaled about 8 MB. Both metadata capacity checks passed,
completion succeeded on its first and only call, and Workbench status, seal,
report, SARIF, and usage coverage all became complete.
Expected behavior
- A valid sealed report should reach an atomic Workbench
completestate even
if usage measurement is too large or unavailable. - Usage measurement should be bounded and best-effort. Budget exhaustion should
recordpartialorunavailable, not fail scan completion. - Completion should commit the canonical result before optional usage
reconciliation, or use a crash-consistent transaction/state transition. - Usage collection should read only scan-owned data from scan-start byte
offsets rather than replaying complete historical rollouts. - A later bounded reconciliation should be able to update usage for an already
completed scan without rewriting its sealed report.
Suggested regression tests
- Complete a scan whose root rollout exceeds a byte budget.
- Complete a scan whose descendant graph exceeds a task budget.
- Terminate the process after artifact sealing but before usage reconciliation.
- Verify the scan remains completed with
usage.coverage=unavailableor
partial. - Verify later usage reconciliation is idempotent and does not alter sealed
report artifacts.
Related issues
- #37587 covers a different finalization/schema recovery failure.
- #24510 covers broader unbounded local-history processing and performance.
No repository contents, rollout contents, task titles, task IDs, absolute local
paths, credentials, user identifiers, or private findings are included here.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the workbench_db.py complete-scan entry point through complete_scan_locked() and collect_scan_usage(), then review the suggested capacity and interruption regression cases. Done means a sealed scan reaches Workbench status=complete even when bounded usage collection is partial or unavailable, and later reconciliation is idempotent without changing sealed report artifacts.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- cli, database, performance, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100