Skip to content

feat(deep): prepare compatible readers for durable scan recovery - #919

Open
mldangelo-oai wants to merge 134 commits into
mainfrom
mdangelo/codex/deep-compatible-reader
Open

mldangelo-oai wants to merge 134 commits into
mainfrom
mdangelo/codex/deep-compatible-reader

Conversation

@mldangelo-oai

@mldangelo-oai mldangelo-oai commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Prepare compatible readers for saved Deep Scan execution and publication state before enabling the corresponding writers. Recovery preserves accepted evidence, unresolved coverage and the result conversation. Supported historical unsealed budget results complete through the existing finalizer; unsupported recovery is rejected before saved state changes.

Changes

  • Share managed session construction and audit admission while preserving existing permission differences, retry decisions and artifact ownership.
  • Read saved attempts, checkpoint references, ordered merge inputs and selected finalization state. Honor newer checkpoint rejections and retain distinct remediation and coverage reasons.
  • Restore committed execution settings through discovery and reducer launches, including resumed workers. Refresh authentication and apply current permission restrictions without borrowing settings from concurrent scans. Model-writable artifacts cannot choose recovery executables or account homes.
  • Reconcile recorded worker usage and copied rollouts while retaining known cost bounds and unknown usage. Preserve cancellation and sealed-budget replay.
  • Validate accepted bytes and publication bindings before completing old unsealed budget results. Retain unmerged coverage and valid historical duplicate projections without restoring rejected findings.
  • Bind the saved budget-recovery test fixture to its registered snapshot digest and verify completion preserves that digest.
  • Incorporate current main through an ordinary merge, including dependency, CI, UTF-8 knowledge-base and context-aware cost changes. Preserve linked plugin entrypoints and remove the unused publication crash fixture.

New scans retain the existing workflow. New attempt, frozen-checkpoint and finalization writer activation remains a separate change. The reader corrections introduce no new public command, flag or environment variable.

Testing

Reviewed head: aff95e71270c5c73fb928398dbf90e30e0288828, tree b0f2f20e6b9d8d42d1e0edaf6f624886406e6316. The latest update adds 13 test lines; production files are unchanged from 8c5b632. Two fresh native review passes and an independent verifier found no actionable issues in this update; the exact-head receipt check passed. The publication review checked bundle integrity, ancestry, every changed-path identity, main incorporation, the complete public diff and source-bound qualification records. It did not repeat product suites.

Previously recorded qualification on 8c5b632 on macOS arm64 (its production files are unchanged in the current head):

  • All five required portable checks passed: Ruff check, Ruff format check, SDK build:ci, plugin source compatibility, and the source-compatibility tests. Plugin build and all seven alias-build tests also passed.
  • Full Python passed 1342 tests / 4 skipped, with 110 passing subtests. The first full run remains recorded as 1341 passed / 4 skipped / 1 failed, with 110 passing subtests: the temporary-directory spelling prevented the macOS alias fixture from exercising its intended alias. The successful run used the alias of the same physical temporary directory; source, assertions and timeouts were unchanged.
  • The original full MCP run failed: 72 passed / 1 timed out during resumed stdio execution. Isolated source, installed and detached lifecycle controls passed. A separate full diagnostic run passed 73/73 with the same concurrency and timeouts, using TAP reporting and the qualified temporary-directory alias. The original timeout's cause remains unclassified; the diagnostic pass does not erase it.
  • The ordinary Mac-built package passed dependency-projection and member checks. Installed Codex version, detached MCP initialization and Darwin native-module loading passed. The existing 49 reader recovery cases passed in each installed and detached layout with only helper-path bindings adjusted in test copies. These are synthetic integration checks, not live-model scans.

Linux qualification ran on the merge parent's tree, 30c869f8877abd7cfb44da158acfe7d8e684af24. All shipping SDK, MCP, native and dependency files match this head. Later test-only changes remove the unused test string and correct the snapshot-recovery fixture. Portable checks and full MCP 73/73 passed. Full Python passed 1339 / 8 skipped, with 109 passing subtests, under ordinary import defaults. Its initial inherited-environment failure remains recorded as 1338 passed / 8 skipped / 1 failed. Source, installed and detached recovery/replay and rejection controls passed; their overlapping counts are not summed.

Current-head Linux SDK qualification used Node 24.15.0, pnpm 11.25.0, Bun 1.3.14, Python 3.12.13 and Git 2.43.0. Both pnpm run test --seed 12345 and ordinary pnpm run test passed 3121 tests / 50 skipped / 0 failed, with 70412 assertions each. The default run recorded seed 2117022814. Builds, types, format and the focused regression passed. All 511 members of the retained reader package match the current build; the package retains its original source identity.

The exact preceding head fails the snapshot-binding fixture. On macOS arm64, that parent case failed and the corrected full workbench module passed 35 tests / 265 assertions with seed 12345. This used the existing byte-verified bundled runtime; it is not a new package or full macOS SDK run. No production guard, assertion or timeout was weakened.

Remaining gates: current-head CI and final Windows qualification remain open. Earlier reader SDK failures, including the separate malformed-Git-config case, remain historical failures. The preceding head's Windows Node 24 package job timed out in npm install; its deeper cause remains unknown. The original intermittent Mac MCP timeout and broader Mac SDK failures are not erased by later focused passes. This update does not claim those platform gates are complete.

Risk and rollout

Release a qualified compatible reader before enabling new durable writers, including writers affecting historical workflows. Rollback must use a release that understands state already written. Supported selected-result completion does not imply support for newer discovery or reducer execution.

This reader adds migrations 45–48 and 51 without changing existing migration identities. Coordinate the separate writer's migration 44 and the two open proposals containing different migration 42 changes. The open helper-entrypoint refactor also needs composition review before landing together.

Main 7b77956c3067861559d31a3f3f791209b403643d is incorporated. The final comparison against main covers 114 files; this update from 8c5b632 changes only the snapshot-recovery test fixture. The rolling scheduler, result conversation, retry ownership and intentional Standard/Deep permission differences remain. This PR does not establish release readiness or production equivalence.

Public disclosure review

  • No customer, partner, prospect, or user identities, data, or identifying details are included.
  • No credentials, personal data, private source, scan findings, or nonpublic links or tickets are included.
  • I reviewed the branch name, title, description, commits, changes, comments, logs, screenshots, attachments, and links for public disclosure.

@github-actions github-actions Bot added the enhancement New feature or request label Sep 12, 2026
Comment thread plugins/codex-security/tests/test_publication_stop_interleavings.py Fixed
from typing import Any

import pytest
import workbench_test_support
Read committed execution settings and validate saved publication bindings before recovery. Preserve historical unsealed budget coverage through the existing finalizer, and reconcile the reader with current main.
Preserve upstream changes and saved-result recovery, including partial coverage and per-model cost attribution.
selection_before = json.loads(run_before.pop("finalization_input_json"))
selection_after = json.loads(run_after.pop("finalization_input_json"))
assert run_after == run_before
assert selection_after.pop("publicationSha256") != selection_before.pop("publicationSha256")
)
assert result.returncode == 0, result.stderr
private = json.loads(result.stdout)
assert private["deepScan"].pop("executionSettings") == (settings if bound else None)
@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current head, 8c5b632741ffa7558bbd5df8d0564a328fc6b570, against main.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-16T23:44:46.440132Z aff95e7 Draft marked ready
🔒 Security Review Completed 2026-09-16T23:43:26.382178Z aff95e7 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Use the registered target contract when authoring the saved directory snapshot. Assert its format and preservation through budget-exhausted completion.
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 8c5b632741

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review current head aff95e71270c5c73fb928398dbf90e30e0288828.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: aff95e7127

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@mldangelo-oai
mldangelo-oai marked this pull request as ready for review September 16, 2026 23:34

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aff95e7127

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +784 to +798
session.responseIds.add(responseId);
const cumulative = tokenUsage(payload["thread_token_usage"]);
if (cumulative)
session.expectedResponseTokens = Math.max(
session.expectedResponseTokens,
cumulative.total_tokens,
);
if (!session.responseUsageObserved) {
// Exact receipts include compaction and survive counter resets. Keep the
// legacy counter as an independent lower bound, never add it to receipts.
session.responseUsageObserved = true;
session.usage = null;
session.modelUsage.clear();
}
session.responseTokens += usage.total_tokens;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Filter receipts before updating attributed usage

When a shared owner session contains a token_usage_record from another turn or after the scan's completion—particularly when an older attributed turn was measured with legacy token_count events—this code records the response, clears the attributed usage/model totals, and updates cumulative receipt counters before isAttributedScanEvent rejects it below. The scan's known usage can consequently become unpriced or falsely partial, preventing reliable enforcement of a user-requested --max-cost; perform the attribution check before mutating receipt state (and apply the same ordering in the Python reader).

AGENTS.md reference: sdk/typescript/AGENTS.md:L23-L25

Useful? React with 👍 / 👎.

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant