Skip to content

feat: share scan settings across the CLI and SDK - #742

Draft
mldangelo-oai wants to merge 7 commits into
mainfrom
mdangelo/codex/project-configuration
Draft

feat: share scan settings across the CLI and SDK#742
mldangelo-oai wants to merge 7 commits into
mainfrom
mdangelo/codex/project-configuration

Conversation

@mldangelo-oai

@mldangelo-oai mldangelo-oai commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Reusing scan settings means repeating command-line options or translating them into SDK calls. This adds explicit YAML and JSON files that both the CLI and SDK can load, with shared types and validation.

Changes

  • Load one YAML or JSON file with scan [repository] -c FILE or --config FILE. The option is unset by default, and the CLI doesn't discover project files. The format has no version field.
  • Keep repository selection explicit, with scope paths relative to that repository. Context, instruction, validation, and output paths in the config are relative to the config directory. CLI path behavior stays the same. Overrides replace lists and scope variants.
  • Generate and ship schemas/project-config.schema.json from the input definition. The existing Ajv engine validates files without fetching schema URLs, adding defaults, coercing values, or dropping unknown wrapper keys.
  • Share all six deep defaults with the Python plugin, keep legacy TOML support, and save resolved settings in new recipes. Remove the unused fallback that parsed raw scan arguments.
  • Expose SDK loadProjectConfig() and resolveProjectConfig() helpers that return constructor configuration and scan options. Add ScanSettings, SDK prompt-file options, and ScanResult.hasFindingsAtOrAbove().
  • Share prompt-file handling and severity ordering. Document the file/CLI/SDK mappings and test equivalent configurations, native profiles, custom validation, and workflow resumption. Blank SDK prompts do not create a requirement to resupply instructions on rerun.
  • Honor models from selected native profiles when using provider flags. Preserve unrelated TOML sections when complete deep settings are written back to the ambient file.

Example

Save this as codex-security.yaml at the root of a repository with a src directory:

scan:
  scope:
    paths: [src]
codex:
  model: gpt-5.6-sol
  model_reasoning_effort: xhigh
limits:
  maxCostUsdPerScan: 10
policy:
  failOnSeverity: high

Check the config with a CLI override:

codex-security scan . -c codex-security.yaml --max-cost 5 --dry-run --json

--max-cost 5 overrides the file's $10 limit for this invocation. --dry-run checks local inputs without starting a scan.

The SDK can load the same file:

import { CodexSecurity, loadProjectConfig } from "@openai/codex-security";

const { config, options } = await loadProjectConfig("codex-security.yaml");
await using security = new CodexSecurity(config);
const result = await security.run(".", options);

Testing

Validation for this follow-up:

  • Full SDK suite with seed 12345: 2,175 passed, 39 skipped, zero failures across 117 files.
  • Randomized full SDK run with seed 3828761576: the same 2,175 passed, 39 skipped, and zero failures.
  • Focused tests for the final review fix: 180 passed, 2 skipped, zero failures. Five cases using SDK recipes in CLI reruns cover omitted prompts, empty and whitespace inline text, actual instructions, and empty files. The two blank-inline cases failed before the fix and passed afterward. The earlier contract parity suite also passed 262 tests with two platform skips.
  • Python contract, capability-profile, and source-check tests: 70 passed. All 23 MCP test scripts passed.
  • Passed 90 CLI checks and 24 comparisons between SDK and CLI results on Node 22.15.1, 24.15.0, and 26.0.0. All six CLI help/schema comparisons matched the previous package byte for byte.
  • Installed package checks passed, including the new SDK loaders, strict NodeNext types, CLI startup, credential locking, bundled Codex, MCP initialization, dashboard assets, and nested workers. The tarball has 416 entries and 123 plugin files; 16 source/schema/document comparisons matched the validated checkout.
  • YAML and JSON language services validated the examples, caught typos, and provided completions offline.
  • SDK/MCP types, SDK/docs formatting, and portable plugin source checks passed. Ruff lint and formatting passed for all 137 Python files.

Python checks used the repository's isolated pytest setup.

Risk and rollout

Deep preflight now resolves and validates applicable legacy TOML before the runtime starts, so invalid settings can fail earlier. Native profiles keep their existing precedence and restrictions.

Project files and SDK options support stopAfterConsecutiveErrors; this adds no CLI flag for it. Cost limits still apply per scan attempt. Project files cannot select a repository or turn on automatic patching or publication.

Existing CLI flags, file fields, defaults, and output remain compatible. SDK inline prompts take precedence over matching files. The SDK records the severity policy; callers decide how to handle hasFindingsAtOrAbove() results.

New recipes save resolved settings without copying source or context contents. Reruns don't reload the project file. Older partial recipes still use legacy defaults for missing settings. If a new recipe required additional scan instructions, reruns refuse to omit them silently.

Local testing covered macOS arm64. It did not include live inference, credential verification, releases, or deployments. Linux and Windows coverage depends on CI.

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 Aug 29, 2026
@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current head, e934a27a04ca703e856022956bb489f034fafa76.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 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-08-30T04:13:53.602500Z 3219d7f Manual request
ℹ️ 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.

@mldangelo-oai
mldangelo-oai requested a review from ianw-oai August 29, 2026 14:33

@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: e934a27a04

ℹ️ 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 thread sdk/typescript/src/cli.ts Outdated
(isExternalModelProvider(provider) || provider === "amazon-bedrock") &&
!("model" in result)
!("model" in result) &&
defaults?.["model"] === undefined

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor selected-profile models with --provider

When a project file selects a profile and supplies its model only through codex.profiles.<name>.model, using --provider amazon-bedrock, openrouter, or fireworks is rejected here because this checks only the root defaults.model. The existing scanModelConfiguration helper resolves the selected profile's model first, so this is a complete configuration that would otherwise run; use that effective-model logic before enforcing the explicit-model requirement.

AGENTS.md reference: sdk/typescript/AGENTS.md:L16-L20

Useful? React with 👍 / 👎.

Comment on lines +54 to +55
// Complete saved settings do not depend on today's ambient configuration.
if (!DEEP_SCAN_SETTINGS.every(([name]) => explicit[name] !== undefined)) {

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 Preserve ambient sections when writing a complete snapshot

When all six deep settings are supplied and the runtime destination aliases the ambient source—such as a supported same-home runtime—this branch skips reading the source and leaves resolved.document empty. writeDeepScanConfig then replaces that same TOML file with only [deep_scan], deleting unrelated user sections that the previous implementation preserved. Retain the source document when the destination may alias it, or merge the snapshot without discarding non-deep settings.

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

Useful? React with 👍 / 👎.

@mldangelo-oai mldangelo-oai changed the title feat(cli): add YAML and JSON project configuration feat(cli): load scan settings from YAML or JSON Aug 29, 2026
@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current head, 0ea24644ce1d3d9dbdc5fa6088eb72654bd956a1.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 0ea24644ce

ℹ️ 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".

Resolve project files and typed configuration into shared SDK scan settings.
Keep native Codex configuration separate from scan options and expose public
loadProjectConfig and resolveProjectConfig entry points.

Reuse prompt-file handling and severity comparison across SDK and CLI paths.
Preserve existing flags, file fields, defaults, output, and input protections.
Cover equivalent inputs, prompt-backed workflows, and installed package APIs.
@mldangelo-oai mldangelo-oai changed the title feat(cli): load scan settings from YAML or JSON feat: share scan settings across the CLI and SDK Aug 30, 2026
@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current head, 1e33329e85ae3d58c0d30beb8bcbbf23cadd29b5.

@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: 1e33329e85

ℹ️ 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 thread sdk/typescript/src/api.ts Outdated
deepScanConfiguration?.settings,
options.auth,
);
if (options.scanPrompt !== undefined) recipe["requiresScanPrompt"] = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Mark only effective scan prompts as non-replayable

When an SDK caller supplies scanPrompt: "" or whitespace, resolveScanPrompts preserves that explicit inline value, but the prompt builder ignores it because additionalPrompt?.trim() is empty. This condition nevertheless records requiresScanPrompt, so a later scans rerun rejects a scan that did not actually use additional instructions. Base the marker on the same nonblank check used when constructing the model prompt.

Useful? React with 👍 / 👎.

Only record additional scan instructions as required when the prompt builder
actually includes them. Empty and whitespace-only SDK inputs should remain
replayable, matching omitted prompts and empty prompt files.

Exercise saved SDK recipes through the CLI rerun path while preserving the
requirement to resupply real additional instructions.
@mldangelo-oai

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current head, 3219d7f782e587f03e2e798f9e4dc8a9a04ed016.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 3219d7f782

ℹ️ 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".

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