Skip to content

Codex Security 0.1.22: finalization resurrects resolved checkpoint deferrals and produces inconsistent durable coverage #741

Description

@kokonl06-design

Summary

Codex Security 0.1.22 reproducibly retains an interim deferred checkpoint in terminal durable coverage after that checkpoint has been explicitly resolved before completion.

This was reproduced with a minimal synthetic target consisting of one 214-byte file. It does not depend on the original application repository.

No durable artifacts were manually edited.

Environment

  • Codex Security plugin: 0.1.22
  • Platform: macOS
  • Fresh workbench state: yes
  • Fresh scan state: yes

Minimal reproduction

Synthetic target:

  • Files: 1
  • Bytes: 214
  • SHA-256: 3d06033bffeb0b451f0d1360430b46e281e4ef78bcdeb8487fca9a8ed44e4838

Scan ID:

71fee081-86ab-4d7a-9125-aa28f01b3321

Checkpoint ID:

synthetic-fixture-full-read

Lifecycle

  1. Start a fresh scan/workbench.
  2. Create an interim checkpoint with:
    • complete=false
    • completeness=partial
    • deferred=[synthetic-fixture-full-read]
  3. Complete the required review work.
  4. Submit the final semantic draft with:
    • complete=true
    • completeness=complete
    • deferred=[]
    • openQuestions=[]
    • checkpoint state RESOLVED_COVERED
  5. Finalize normally using the standard completion flow.
  6. Read back the durable artifacts.

Expected result

The resolved checkpoint should remain preserved in historical checkpoint evidence, but it should no longer count as a terminal deferral.

Expected terminal state:

  • coverage: complete
  • unresolved terminal deferrals: 0
  • synthetic-fixture-full-read: RESOLVED_COVERED
  • no open follow-up for that checkpoint

report.md, coverage.json, and scan-manifest.json should agree.

Actual result

After normal finalization:

  • coverage.json reports partial
  • synthetic-fixture-full-read is reintroduced as a terminal deferred item
  • the same surface is also represented as RESOLVED_COVERED
  • report.md renders both the resolved state and an open follow-up

The final semantic draft immediately before completion was explicitly:

  • complete=true
  • completeness=complete
  • deferred=[]
  • openQuestions=[]

So the resolved deferred ID is reintroduced during terminal finalization/projection.

Observed invariant violation

An interim checkpoint may remain in historical evidence, but once its terminal state is RESOLVED_COVERED, it should not remain in the final:

  • deferred list
  • open questions
  • unresolved follow-ups
  • unresolved terminal-deferral count

A genuinely unresolved terminal item should still remain deferred; the expected behavior is terminal-state reconciliation, not unconditional deletion of deferrals.

Additional notes

  • Reproduced using fresh scan/workbench state.
  • No application/private repository source is required to reproduce the issue.
  • No credentials, production data, secrets, or customer data are involved.
  • No product binaries or plugin internals were modified or reverse-engineered.
  • No manual post-finalization editing of durable artifacts was performed.

I have a sanitized minimal reproduction package and final report available if useful.

Activity

  1. bclandry commented on Sep 18, 2026

    @bclandry

    Related symptom on Windows in the Codex desktop app with the Codex Security plugin version 0.1.24, but importantly BEFORE finalization. I am not claiming the same root cause as this issue.

    Retained sequence:

    1. An interim semantic checkpoint was accepted with complete=false, partial coverage and a temporary closeout deferral.
    2. After the remaining review was completed, record_codex_security_scan_draft accepted a final semantic checkpoint with complete=true, complete coverage and no deferred entries. The response was draft_written / operation replace.
    3. Canonical coverage nevertheless retained the earlier partial state and stale closeout deferral. The scan remains running and unsealed.

    No finalization was attempted, so there is no finalization error. No canonical artifacts were manually edited, and no rerun, forced failure/cancellation, replacement scan or plugin modification was performed. Zero findings are not being treated as proof of complete coverage.

    Expected: accepted checkpoint replacement and canonical coverage should agree while preserving history and any genuinely unresolved items. If this sequence is unsupported, please identify the supported contract.

    Please provide a maintainer-supported, owner-bound in-place recovery procedure for this running/unsealed state, including preconditions and evidence-preservation requirements, or confirm that no such procedure exists. Any recovery will be reviewed and separately authorized before execution.

    This is a metadata-only report based on retained evidence, not a new reproduction or a claim about the latest release. The desktop-app build and package version were not collected for this report. No private scan/session identifiers, artifacts, source, logs or attachments are included.

  2. it-her0 commented on Oct 1, 2026

    @it-her0

    Additional observation in desktop plugin 0.1.31

    We observed a related historical-deferral reconciliation problem in the Codex Security desktop plugin 0.1.31 on macOS, during a Standard Scan. The observation and local recovery occurred on 2026-09-30.

    This is a sanitized reliability report, not disclosure of a vulnerability in the scanned repository or a claimed security-boundary bypass. No private repository source, findings, scan identifiers, customer data, credentials, or raw scan artifacts are attached.

    Expected behavior

    After review is complete, an authoritative, consistent final parent checkpoint with complete=true, coverage completeness=complete, deferred=[], and openQuestions=[] should not be overridden by obsolete interim deferrals.

    Historical evidence should remain available without counting resolved work as unresolved terminal coverage. Genuinely unresolved work, ambiguous checkpoints, and mismatched finding/review inventories must remain incomplete.

    Observed behavior and diagnostic evidence

    1. The final semantic parent checkpoint explicitly reported complete coverage, with no deferred work or open questions.
    2. Earlier Node-side draft reconciliation retained 49 historical coverage rows in canonical coverage: 37 candidate-deferred rows and 12 batch-closure rows.
    3. A read-only completion-merge projection against a temporary copy of the captured state retained completeness=partial and those 49 deferred rows, despite the complete checkpoint. The diagnostic reported no merge warnings.
    4. In the locally inspected Python completion path, scripts/workbench_saved_results.py, the unsealed canonical parent was preferred and parent checkpoints were treated as superseded when the manifest was not explicitly incomplete. The complete checkpoint therefore could not repair canonical coverage.

    This is an observation of the captured 0.1.31 state, not a claim that every scan or the current release reproduces the defect.

    Reproduction outline and limits

    The observed lifecycle was:

    1. Run a Standard Scan that records interim deferred coverage/checkpoints.
    2. Resolve the required review and retain a final complete semantic parent checkpoint with empty deferred/open-question lists.
    3. Reconcile drafts into an unsealed canonical parent that still contains historical deferred rows.
    4. Run the normal completion preparation/merge path.
    5. Inspect canonical coverage and whether the unique consistent final checkpoint is treated as superseded.

    The before/after merge behavior was checked on a temporary copy of the actual state. We have not reduced it to a fresh, standalone, synthetic reproduction package or reproduced it on the current public version. The outline above is not an independently tested fresh-start fixture. Private scan state is not being uploaded.

    Local workaround evidence and caveat

    A narrowly gated local hotfix restored the unique explicit complete root checkpoint only when substantive findings, coverage surfaces, fully reviewed files, and relevant inventory counts matched the canonical parent. It retained workbench-owned coverage-envelope fields.

    The copied-state projection then reported complete coverage, no deferred work, and no open questions. Negative controls retained the original incomplete state for a stopped scan, explicitly incomplete manifest, mismatched findings, and multiple complete checkpoints. An already-complete parent remained unchanged. Copied preparation/contract validation and normal live completion subsequently succeeded.

    The hotfix is not an upstream fix, release, or recommended broad workaround. Plugin reinstall/update may overwrite it. The shipped integrity manifest was not changed; the one local script mismatch was deliberately left visible. Neither deleting deferred rows manually nor weakening validation was used.

    Installed 0.1.31 target identity:

    • Official base SHA-256 recorded in the shipped integrity manifest: db445b651bd677359ef0a5c2bbb70e896eccd60becbd80e8c7a77aa3010f289c
    • Locally patched file SHA-256: 9b8d5786acda87229ca4ad76200f01e7bfeb93e1d708dbc68735f5f42766532c

    The pristine original file was not retained, so this report does not claim to provide an exact upstream unified diff. No patched payload is attached.

    Maintainer request

    Please confirm whether the current supported release addresses this complete-parent-checkpoint/historical-deferral interaction and, if so, identify the fixing release and the supported recovery path for affected existing scans. Please preserve fail-closed behavior for ambiguous, mismatched, explicitly incomplete, and stopped scan states.

  3. mldangelo-oai commented on Oct 8, 2026

    @mldangelo-oai
    Collaborator

    Merged #1036 looks relevant: it adds explicit deferred-task closure and preserves task identities during recovery. Could you check whether it covers the remaining legacy-checkpoint cases here?

  4. added
    area:artifactsSaved scan state, storage, sealing, recovery, history, and artifact integrity.
    bugSomething isn't working
    on Oct 8, 2026
  5. it-her0 commented on Oct 8, 2026

    @it-her0

    Summary

    Thanks — #1036's explicit ID-based closeout works, but it does not establish automatic migration of the captured legacy checkpoint history. I also reproduced a separate complete + retained-deferred inconsistency on current main and submitted a narrow fix: #1497. Its two-case regression needs only the upstream Python test environment, not a model/native scan.

    The PR preserves unresolved tasks and fixes only projected completeness. Broader closure/identity work remains with #771/#978/#1296/#1310; it does not add a competing migration API.

    Remaining policy question

    For old parent-owned candidate IDs later consolidated into findings, what supported mapping/terminal-outcome path should contributors use? I have not treated worker-owned sourceFindings as arbitrary aliases, fabricated rejections, duplicated findings, or cleared tasks just to force completion. Likewise, which old parent/checkpoint histories are intended to migrate automatically, versus requiring explicit saved-ID closure? Ambiguous, stopped, mismatched and independently pending work must remain protected.

    Results behind that conclusion
    1. Authority/supersession: the unmodified recovery component hash-matching the earlier 0.1.31 component reproduced the captured priority issue. An archived narrow workaround changed the same-input outcome. fix(plugin): close saved review tasks and simplify recovery #1036 changes head/source-order selection, but current main did not automatically reconcile that same legacy history. The entire old desktop cache/full DB is not attested.
    2. Generic closeout: current main's documented resolvedDeferred: [{id, reason}] succeeds. Old empty-list input alone leaves a saved task pending. The pinned fix(artifacts): keep resolved checkpoint deferrals closed #771 head 0a60d3a272c51f1d4deb498da23f9845f9713b88 closes its linked-surface synthetic case through its older documented route, not all rows in the captured history. fix(artifacts): close resolved generic deferrals #978 proposes a different receipt contract.
    3. Candidate consolidation: the captured parent candidate IDs and later consolidated findings lack native linkage. A supported many-to-one migration policy is still a question, not a completed fix.
    4. Diagnostics: the same legacy merge returned warnings=[] while retaining pending work. This is an array observation, not an established independent warning bug or a claim about all logs. This PR does not add warnings.
    5. Report/status: resolved surfaces and pending generic tasks coexist, but canonical JSON and the report agree on the partial result. completed with partial coverage is valid. A separate renderer bug and every original live-UI/0.1.22 fixture detail have not been established; fix(coverage): distinguish finished scans from complete requested coverage #586 is related display work, not proof of closure.
    6. Recovery scope: new closure success is not automatic legacy migration. The original scan is already completed/sealed and was preserved, not resumed or resealed. These checks used isolated copies and deterministic component/native paths; they do not establish natural AI/Jisou workflow causality.

    The separate invariant fixture has a complete canonical parent/terminal checkpoint but unresolved older work and no accepted head. Main 5ebe48db0585c5e582b0494236a01a739af13709 and the tested #1310 head project complete with retained tasks; strict finalization rejects it without sealing/replacing canonical files. The submitted patch yields truthful partial coverage without removing tasks. Identical generic/candidate regression inputs produce two completeness-assertion failures on the base and two passes after the patch. This is not a live/sealed corruption claim.

    Only the small synthetic three-file contribution is public. No private scan payloads/raw logs or optional caller adapter are attached.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:artifactsSaved scan state, storage, sealing, recovery, history, and artifact integrity.bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions