openai/codex
A deep, specific AGENTS.md and a serious CI gate; nothing written down about why, and no single command to prove a change. Below is the run the agent did and the AINE-REPORT.md it wrote.
- 30 passed
- 16 failed
- 0 n/a
- Rust · Cargo + Bazel · just · Python · GitHub Actions
Run 13 August 2026 · main at a7b8c07
The agent run
I cloned openai/codex into a temp folder, audited it against all 46 checks and wrote the full report to AINE-REPORT.md in the repo.
AI-Native Readiness — openai/codex
30 passed · 16 failed · 0 not applicable
High priority — fix these first
- Fix the four stale paths in
AGENTS.md—mcp_connection_manager.rs→connection_manager.rs(line 35),protocol/v2.rs→protocol/v2/(lines 276, 287),core/suite→core/tests/suite(line 114),core/context→core/src/context(line 100). Why: an agent told to route MCP tool-call changes through a file that does not exist will invent its own place to put them. - Clear the stale exception so the repo's own verifier is green on
main— drop thecodex-rs/code-modeentry fromMANIFEST_FEATURE_EXCEPTIONSin.github/scripts/verify_cargo_workspace_manifests.py. Why: that check is merge-blocking and it exits 1 on an untouched checkout, so an agent cannot tell its own damage from the baseline. - Add a "requires a human" block to
AGENTS.mdnaming the release tag pushes (rust-v*,python-v*), pushes under.github/**, and the fulljust testsweep. Why:.github/workflows/rust-release.ymlhands outgit push origin rust-v0.1.0with no fence around it, and that command ships signed binaries to the public. - Add a
secret-scanjob toblocking-ci.ymlnext tocodespell, allowlisting the three files that hold key-shaped test fixtures. Why: nothing scans today, and the codebase deliberately contains key-shaped fixtures, so a real key would not stand out in a diff. - Add a
checktarget tojustfilechainingfmt-check,clippy,test,bazel-lock-checkand the three.github/scripts/verify_*.pyverifiers. Why:AGENTS.mdcurrently spells out seven commands and four conditionals an agent has to carry itself before pushing. - Add a layout section to
AGENTS.md— one line per top-level area, includingsdk/,scripts/,tools/,codex-cli/andthird_party/, none of which the instruction set mentions at all. Why: 5,755 files undercodex-rsand five unmentioned sibling trees; an agent landing insdk/has no guidance. - Start
docs/adr/with aTEMPLATE.md, seeding it with the four decisions that exist today only as lint reasons and CI-script docstrings. Why: this one root fix unblocks six failing checks — specs freshness, spec scaffolding, machine-checkable acceptance criteria, failure-and-rollback criteria, non-goals and traceability.
Low priority — worth doing
- Add
npm,uvandtools/argument-comment-lintblocks to.github/dependabot.yaml— six of nine lockfiles are unwatched, including the tree published to PyPI. - Pick one convention for in-flight state (for example
plans/<pr-number>.md) and name it inAGENTS.md, so a fresh session can resume without re-reading the diff. - Split the TUI styling, app-server API and Python sections out of
AGENTS.md— it is 22,519 bytes (~5.6k tokens) loaded in full every session, and roughly 40% of it is irrelevant to any given task.
One blind spot, stated in the affected proofs: the machine running the audit had no cargo, just, bazel or pnpm, so the Rust and Bazel suites and clippy could not be executed. The Python suites and the three CI verifiers were run, and their results are in the file.
The report it wrote
AI-Native Readiness Report
Repo: openai/codex, a fresh clone of main at commit a7b8c07 (2026-08-13)
Date: 2026-08-13
Stack: Rust monorepo — a ~170-crate Cargo workspace under codex-rs/ (edition pinned to 1.95.0 via rust-toolchain.toml), built by both Cargo and Bazel 9.0.0 (MODULE.bazel, BUILD.bazel); just as the task runner; Python 3 for repo tooling (scripts/, .github/scripts/, uv-locked) and for the SDK under sdk/; pnpm 10.33.0 workspace for the npm packaging and formatting layer; Nix flake and devcontainer for environments; GitHub Actions for CI. Test runners: cargo nextest, bazel test, insta snapshots, unittest.
Result: 30 passed, 16 failed, 0 not applicable
How to read this. Every item is a numbered question about this repo, answered from evidence in this repo. Proof is what was actually found — a path, a file, a command and its output. An item with no proof is not an answer. The italic line under each question says how to check it; it stays in the report so the next run checks the same way.
FAIL vs N/A. FAIL means the practice would help here and it is missing — including when a whole artifact is missing, so several questions about it fail together with a one-line proof pointing at the item that found it missing. N/A means the question could never apply to a project of this kind, and the proof says why. "It does not exist" is a FAIL, never an N/A.
Priority is fixed by the template, not by the person filling it in. High means an agent working here will hit this on day one, or the risk is real. Low means it makes things better but nothing breaks without it.
1. Context
-
1. Does an agent instruction file exist (AGENTS.md, CLAUDE.md, .cursorrules, .github/copilot-instructions.md, or this ecosystem's equivalent), and what does it point at? Look for a file whose purpose is to be loaded into a coding agent's context at the start of every session. That file is the entry point. Then follow its pointers: instructions are commonly spread across several files, with the entry point routing to them — "commands are in docs/development.md", "conventions in .claude/rules/". The entry point plus every file it points at is the instruction set, and every other agent-instruction question is answered against that whole set, so list it here in the proof. Follow pointers as deep as they go, but a pointer only counts when it names a target and says what is in it: "test commands are in CONTRIBUTING.md" counts, a bare "see the docs" does not, and a file nothing points at is outside the set however good it is. A README is not an entry point, however good — it gets its credit at the README item and the specs-and-architecture item — but a README the entry point explicitly routes to is inside the set. Vendored skill libraries are not instructions either.
- Status: PASS
- Proof: Entry point is
AGENTS.mdat the repo root (22,519 bytes). A second, directory-scoped file exists atcodex-rs/tui/src/bottom_pane/AGENTS.md(paste-burst and chat-composer doc-sync rules). Pointers out of the entry point that name a target and say what is in it:codex-rs/tui/styles.md("TUI style conventions"), the$remote-testsskill resolving to.codex/skills/remote-tests/SKILL.md(cross-OS app-server/exec-server integration testing),codex-rs/app-server/README.md(app-server API docs to update when behaviour changes), andcodex-rs/core/config.schema.json(regenerated viajust write-config-schema). Instruction set = those five files. Outside the set: the rootREADME.md,docs/contributing.mdanddocs/install.mdare never routed to fromAGENTS.md, and the 13 skills under.codex/skills/other thanremote-testsare not pointed at either. Note.gitignorelines 33-35 ignoreCLAUDE.md,.claude/andAGENTS.override.md, so a Claude-family agent inherits none of this harness from a clean clone. - Recommendation: —
- Priority: High
-
2. Do the agent instructions name the commands to build, test and check this project? Answer this against the instruction set mapped at the entry-point item and nothing outside it. If no entry point exists, FAIL with a one-line proof pointing at that item. The commands may sit in a file the entry point routes to rather than in the entry point itself — that is progressive disclosure working as intended, and it passes. What fails is a command an agent would have to guess its way to: if the commands live only in the README or the manifest and nothing in the set points at them, that is a FAIL, because the question measures what an agent can reach without being told where to look. Name the file each command was found in.
- Status: PASS
- Proof: All in
AGENTS.md, all verified againstjustfile:just fmt(line 64),just testandjust test -p codex-tui(lines 66-68),just fix -p <project>(line 70),just argument-comment-lint(line 20),just write-config-schema(line 34),just write-app-server-schema(line 303),just bazel-lock-update(line 37),just bench/just bench-smoke(lines 206-208), pluscargo insta pending-snapshots/show/accept -p codex-tui(lines 194-198).AGENTS.md:66also carries the negative rule that matters most here: "Do not runcargo testdirectly. Usejust test". Gap worth naming: no build command is in the set —cargo buildand the from-source setup live only indocs/install.md, which nothing in the set points at. - Recommendation: —
- Priority: High
-
3. Does everything the agent instructions name still exist — the commands, the paths, the libraries, and the files they point at? If no entry point exists, FAIL with a one-line proof pointing at the entry-point item. Verify, do not trust: check every named command against the manifest or build file, spot-check the paths, run the cheap read-only ones. Then resolve every pointer in every file of the set — a link to a moved or deleted file is the most common rot in a multi-file instruction set, and it fails silently: the agent reads the entry point, follows nothing, and carries on without the rules.
- Status: FAIL
- Proof: Commands verified: all 9
justtargets named inAGENTS.mdexist injustfile(checked target by target). Cheap read-only runs that pass:python3 .github/scripts/verify_bazel_clippy_lints.py→ exit 0. Paths mostly resolve (codex-rs/tui/styles.md,codex-rs/core/config.schema.json,codex-rs/app-server/README.md,codex-rs/app-server-protocol/src/protocol/common.rs,codex-rs/tui/src/app.rs,chatwidget.rs,bottom_pane/chat_composer.rs,footer.rs,bottom_pane/mod.rs,tui/src/wrapping.rs,.codex/skills/remote-tests/SKILL.mdall present), but four are stale:AGENTS.md:35namescodex-rs/codex-mcp/src/mcp_connection_manager.rs, which does not exist — the real file iscodex-rs/codex-mcp/src/connection_manager.rs;AGENTS.md:276and:287nameapp-server-protocol/src/protocol/v2.rs, which is now a directory,codex-rs/app-server-protocol/src/protocol/v2/;AGENTS.md:114says integration tests are "undercore/suite", but the real path iscodex-rs/core/tests/suite/;AGENTS.md:100requires fragments be "defined as structs incore/context", real pathcodex-rs/core/src/context/. - Recommendation: Fix the four paths in
AGENTS.md:mcp_connection_manager.rs→connection_manager.rs(line 35),protocol/v2.rs→protocol/v2/(lines 276, 287),core/suite→core/tests/suite(line 114),core/context→core/src/context(line 100). - Priority: High
-
4. Are the agent instructions specific to this repo, rather than advice that would read the same in any codebase? If no entry point exists, FAIL with a one-line proof pointing at the entry-point item. The test: could this be pasted into another project unchanged? "Write clean code" and "add tests for new features" would fit anywhere and count for nothing. Judge the whole set, but weigh the files differently: an entry point that is mostly a routing table is fine, even good, when what it routes to is specific — while generic filler in the entry point costs more than generic filler three hops down, because it is loaded into every session whether it is needed or not. Say which files carried the specifics.
- Status: PASS
- Proof: Almost nothing here would survive a copy-paste into another repo. From
AGENTS.md: theCODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR/CODEX_SANDBOX_ENV_VARprohibition and the Seatbelt early-exit rationale (lines 8-10); "resist adding code to codex-core" with the reason it got bloated (lines 72-83); the/*param_name*/argument_comment_lintconvention with its exemptions (lines 15-20); the 500/800-LoC module ceiling naming six specific high-touch files includingcodex-rs/tui/src/chatwidget.rs(lines 49-61); the app-server v2 rules (#[ts(optional = nullable)]only on*Params, neverskip_serializing_ifon v2 payloads,#[ts(export_to = "v2/")], camelCase-on-the-wire with the config-RPC snake_case exception) (lines 270-296); the Bazelcompile_datarule forinclude_str!/sqlx::migrate!(lines 40-43). The specifics are carried by the entry point itself and bycodex-rs/tui/styles.md. The only generic filler is a handful of test-hygiene lines such as "prefer comparing the equality of entire objects" — and even those are tied topretty_assertionsand named helpers. - Recommendation: —
- Priority: High
-
5. Do the agent instructions explain where things live and how this project is laid out? If no entry point exists, FAIL with a one-line proof pointing at the entry-point item. The map may live in a routed-to file. Judge coverage against the real tree, not against what the files mention: if the set maps one package well but is silent about sibling packages or directories an agent would land in, that is a FAIL with the omission named. In a multi-file set, check the routing too — a layout document nothing points at is a document the agent never opens.
- Status: FAIL
- Proof:
AGENTS.mdnames individual files and crates as it needs them (codex-rs/core/,codex-rs/tui/,codex-rs/app-server-protocol/,codex-rs/codex-mcp/) but never maps the tree, and coverage against the real tree is thin:git ls-filescounts 5,755 tracked files undercodex-rsacross roughly 170 crates, plus five sibling top-level areas the set is completely silent about —sdk/(117 files, published to PyPI by.github/workflows/python-sdk-release.yml),scripts/(50 files, a Python package with its ownpyproject.tomlanduv.lock),tools/(31 files, the custom Dylint linter),codex-cli/andthird_party/.grep -iE 'sdk|codex-cli|third_party' AGENTS.mdreturns nothing. The obvious candidate for a map,codex-rs/README.md, is three lines long and only links to the public docs site, and nothing in the set points at it anyway. - Recommendation: Add a short layout section to
AGENTS.md— one line per top-level area (codex-rs/Rust workspace,sdk/Python and TS SDKs,scripts/repo tooling,tools/argument-comment-lint/custom lint,.github/CI,docs/user docs) — or write it intocodex-rs/README.mdand route to it fromAGENTS.md. - Priority: High
-
6. Do the agent instructions state the rules that are not obvious from the code — the things never to do here? If no entry point exists, FAIL with a one-line proof pointing at the entry-point item. These are the tribal-knowledge traps: the flag that must be exactly this string, the import that breaks the build, the directory that is generated and must not be edited. Rules in a routed-to file count. Two extra checks in a multi-file set: that the entry point signposts the rules clearly enough for an agent to open them before it needs them, since a trap found afterwards has already been sprung; and that the files do not contradict each other, because nothing tells the agent which one wins.
- Status: PASS
- Proof: Real traps, not advice. From
AGENTS.md: never touchCODEX_SANDBOX_NETWORK_DISABLED_ENV_VARorCODEX_SANDBOX_ENV_VAR(line 8); "Do not runcargo testdirectly" (line 66); "Do not add general product or user-facing documentation to thedocs/folder" (line 32); ifConfigTomlchanges, runjust write-config-schema(line 34); ifCargo.toml/Cargo.lockchange, runjust bazel-lock-updateor CI fails on lockfile drift (lines 37-39); Bazel will not see compile-time file reads unless the crate'sBUILD.bazelis updated (lines 40-43); "never try to kill them using the PID" for slow Rust commands (line 62). Signposting is adequate because all of it sits in the single top-level bullet list an agent reads before doing anything. No contradictions found betweenAGENTS.md,codex-rs/tui/styles.mdandcodex-rs/tui/src/bottom_pane/AGENTS.md; the styles file and the entry point's TUI section agree (both ban.white(), andcodex-rs/clippy.tomlenforces it viadisallowed-methods). One trap that is written down but sits outside the instruction set:.codex/skills/pushing-ci-changes/SKILL.mddocuments that pushes touching.github/**/*.ymlare rejected without an out-of-band approval. - Recommendation: —
- Priority: Low
-
7. Has the agent instruction file been updated recently enough to still be true, given how active the repo is? If no agent instruction file exists, FAIL with a one-line proof pointing at the entry-point item. Compare the last commit touching the file against the repo's tempo, then spot-check two or three of its claims against the code — a recently touched file can still lie.
- Status: PASS
- Proof:
git log -1 --format=%ad -- AGENTS.md→ 2026-08-12, one day beforeHEAD(2026-08-13, commit a7b8c07), against a tempo of 30 commits in the last 14 days. Spot-checks of its claims:just fmt/just test/just fixall exist injustfile; the ban on.white()is really enforced incodex-rs/clippy.toml(ratatui::style::Stylize::white, with a reason string);codex-rs/tui/styles.mdexists as claimed;instasnapshot tests exist undercodex-rs/tui/tests/. Third spot-check failed — thecodex-mcppath is stale — which is recorded at the everything-still-exists item rather than here. - Recommendation: —
- Priority: Low
-
8. Is the agent instruction file small enough to load into every session without crowding out the actual task? If no agent instruction file exists, FAIL with a one-line proof pointing at the entry-point item. Measure it:
wc -c, and bytes divided by four is a fair token estimate. Under ~5k tokens is comfortable; past ~10k it is eating the context window.- Status: FAIL
- Proof:
wc -c AGENTS.md→ 22,519 bytes, roughly 5,600 tokens, past the ~5k comfortable line. It is one flat file with almost no progressive disclosure, so every session loads the ratatuiStylizestyling rules (lines 133-163), the app-server serde/ts-rs annotation rules (lines 260-306) and the Python 3 section (lines 308-316) whether the task touches those areas or not — that is roughly 40% of the file. The repo already knows how to do this properly:codex-rs/tui/styles.mdand.codex/skills/remote-tests/SKILL.mdare exactly the pattern the rest of the file is not following. - Recommendation: Move the three domain sections out of
AGENTS.mdinto routed-to files — the TUI code/styling conventions into the existingcodex-rs/tui/styles.md, the app-server API rules intocodex-rs/app-server/README.md(already referenced), and the Python section intosdk/— leaving one-line pointers behind. That gets the always-loaded file back under ~3k tokens. - Priority: Low
-
9. Can a fresh session pick up a half-finished task — is there a file or convention where progress, decisions and what is left get written down? This is not about the agent instruction file. Any durable place in-flight state gets written counts: a TODO.md, a plans or notes directory, task files, linked issues, a specs folder whose entries carry progress and open questions, an agent memory file or directory, a scratchpad or working-notes convention. The test is whether a fresh session could read it and know what was decided and what is left — not what the place is called. Git history alone does not count: it records what happened, not what was decided or what remains.
- Status: FAIL
- Proof: No durable place for in-flight state.
git ls-filesfinds noTODO.md, no plans, notes or tasks directory, no specs folder carrying progress, and no agent memory file (thecodex-rs/memories/andcodex-rs/core/src/tasks/hits are product source, not repo state).CHANGELOG.mdis a single line pointing at the GitHub releases page. What exists records what happened, not what was decided or what is left: every commit carries a PR number (Add the Guardian V2 Luna sampler (#38368)) and.github/pull_request_template.mdasks for a linked issue. Closest near-miss is.codex/skills/babysit-pr/, which watches a PR through CI viascripts/gh_pr_watch.pybut persists nothing a fresh session could resume from. - Recommendation: Adopt one convention and name it in
AGENTS.md— for example aplans/<pr-number>.mdfile per in-flight change holding the decision, what is done and what is left — so a fresh session can resume without re-reading the diff. - Priority: Low
-
10. Is there a README that says what this project is and how to run it? This is where a good README earns its credit. It needs three things: what the project is, how to run it, and how to check a change. Judge what is on the page, not the file's existence.
- Status: PASS
- Proof:
README.mdsays what it is ("Codex CLI is a coding agent from OpenAI that runs locally on your computer", line 1) and how to run it (install viacurl/PowerShell one-liners,npm install -g @openai/codex, orbrew install --cask codex, then "simply runcodex", lines 16-50), including how to pick a platform binary from a GitHub Release. How to check a change is not on the page itself; it is one clearly-named link away under a## Docsheading —[**Contributing**](./docs/contributing.md)and[**Installing & building**](./docs/install.md)(lines 77-78), anddocs/install.mdcarries the full build-and-test sequence (cargo build,just fmt,just fix -p <crate>,just test -p codex-tui). The README is written for users, and it routes contributors correctly rather than guessing. - Recommendation: —
- Priority: High
2. Specs
-
11. Is the thinking behind this system written down somewhere durable — a specs, RFC, proposals, design-doc or ADR directory, or architecture notes that record not just what but why? Look for the place and for the convention:
specs/,docs/adr/,rfcs/,proposals/,.specify/, a docs or design folder, architecture notes anywhere in the tree, or this ecosystem's equivalent. Judge substance, not location: "we use X because Y" is a decision, a list of technologies is not, an essay about specs is not a spec, and a docs folder of usage guides with no reasoning is a FAIL whose proof says what was in there instead. Other items are answered against whatever this item finds, so name it precisely — and where forward-looking specs and after-the-fact architecture records live in different places, name both, since a decision log cannot answer a question about acceptance criteria.- Status: FAIL
- Proof: No decision record of any kind. There is no
specs/,rfcs/,docs/adr/,proposals/or.specify/directory —git ls-files | grep -Ei '(^|/)(specs?|rfcs?|adr|proposals?|design)(/|s/)'returns nothing. What is indocs/instead: 15 files that are usage guides and policy, not reasoning —config.md,example-config.md,exec.md,execpolicy.md,sandbox.md,authentication.md,getting-started.md,slash_commands.md,agents_md.md,skills.md(three lines, a link to the docs site), pluscontributing.md,install.md,CLA.md,license.md,open-source-fund.md.codex-rs/docs/holds three interface references (bazel.md,codex_mcp_interface.md,protocol_v1.md) — what, not why. Real "X because Y" reasoning does exist in this repo, but it is scattered into places that cannot serve as a decision log:AGENTS.md:72-83(why to resistcodex-core),.github/scripts/verify_cargo_workspace_manifests.py("Workspace crate features are disallowed because our Bazel build setup does not honor them today"), areason =string on every entry incodex-rs/clippy.toml, andcodex-rs/.config/nextest.tomlcomments. No forward-looking spec convention and no after-the-fact architecture record exists anywhere in the tree. - Recommendation: Create
docs/adr/with one file per decision already made and re-litigated in code comments — start with the four that are load-bearing today: why workspace crate features are banned, whycodex-tuimust not importcodex-core, why Bazel and Cargo clippy flags must stay in lockstep, and why new code stays out ofcodex-core. Each one currently lives only as a lint reason or a CI script docstring. - Priority: High
-
12. Does the specs directory hold recent entries, or is it an archive nobody has touched? If no specs directory exists, FAIL with a one-line proof pointing at the specs-and-architecture item. Otherwise compare the newest entry's date against the repo's recent activity.
- Status: FAIL
- Proof: No specs directory — see the specs-and-architecture item.
- Recommendation: Blocked by the missing specs directory.
- Priority: Low
-
13. Is there a spec template, or an SDD framework, so every spec comes out the same shape? Scaffolding can exist even where no specs directory does — look for a TEMPLATE.md, a
.specify/directory, or framework config. If neither a directory nor any scaffolding exists, FAIL.- Status: FAIL
- Proof: No spec scaffolding of any kind: no
TEMPLATE.md, no.specify/, no SDD framework config anywhere ingit ls-files. Templates that do exist are intake forms, not spec shapes —.github/pull_request_template.md(three paragraphs, mostly the external-contribution policy) and six.github/ISSUE_TEMPLATE/*.ymlforms.codex-rs/collaboration-mode-templates/templates/plan.mdis product source the CLI ships to its own users, not repo scaffolding. - Recommendation: Add
docs/adr/TEMPLATE.mdwith the sections a decision needs here — context, decision, why not the alternatives, what breaks if it is reverted — alongside the newdocs/adr/directory. - Priority: Low
-
14. Do the specs state acceptance criteria a machine could check? If no specs exist, FAIL with a one-line proof pointing at the specs-and-architecture item. Otherwise open the two newest specs and quote a criterion: "the endpoint returns 403 for expired tokens" is checkable; "the feature works well" is not.
- Status: FAIL
- Proof: No specs — see the specs-and-architecture item.
- Recommendation: Blocked by the missing specs directory.
- Priority: High
-
15. Open the newest spec: do its criteria go past the happy path — what happens when a step fails, and how the change gets undone? If no specs exist, FAIL with a one-line proof pointing at the specs-and-architecture item. Look for error cases, edge inputs, and a rollback or undo story, not just the success flow.
- Status: FAIL
- Proof: No specs — see the specs-and-architecture item.
- Recommendation: Blocked by the missing specs directory.
- Priority: Low
-
16. Do the specs state non-goals, so an agent knows where to stop? If no specs exist, FAIL with a one-line proof pointing at the specs-and-architecture item. Non-goals written elsewhere (a README's "what this is not" list) are worth naming in the proof, but they do not turn this into a PASS — the question is whether specs carry them.
- Status: FAIL
- Proof: No specs — see the specs-and-architecture item. Non-goals are written elsewhere and worth naming:
docs/contributing.md("Pull requests that have not been explicitly invited by a member of the Codex team will be closed without review") andAGENTS.md:32("Do not add general product or user-facing documentation to thedocs/folder"). Neither is a spec. - Recommendation: Blocked by the missing specs directory.
- Priority: Low
-
17. Can recent shipped work be traced back to a spec? If no specs exist, FAIL with a one-line proof pointing at the specs-and-architecture item. Otherwise take the last few substantial commits or PRs and look for a reference to a spec, an issue, or a design doc in the message or description.
- Status: FAIL
- Proof: No specs — see the specs-and-architecture item.
- Recommendation: Blocked by the missing specs directory. Worth knowing that the tracing habit is already there: all 15 most recent commits carry a PR number, e.g.
72fa74f Persist security risk scores in rollout history (#38363), and the PR template asks for a linked issue — so once decision records exist, referencing them from the PR body is a small step. - Priority: Low
3. Verification
-
18. Does this project have an automated test suite, in whatever form this ecosystem uses? Work out this ecosystem's convention before concluding anything is missing — check the manifest, the build file, the CI config, the README. A shell script that diffs output files is a test suite. If you find one, run it and record the result.
- Status: PASS
- Proof: Several suites, in three ecosystems. Rust:
cargo nextestviajust test(justfile:81), configured bycodex-rs/.config/nextest.toml(retries, slow-timeout, per-group thread caps); integration tests undercodex-rs/core/tests/suite/(60+ files) andcodex-rs/app-server/tests/suite/; unit tests in*_tests.rssiblings;instasnapshot tests incodex-rs/tui/tests/. Bazel:just bazel-test→bazel test --test_tag_filters=-argument-comment-lint //... --keep_going. Python:scripts/codex_package/test_*.py,scripts/install/test_install_sh.py,.github/scripts/test_*.py,scripts/mcp_conformance/test_*.py. Ran what this machine could:python3 -m unittest discover -s scripts/codex_package -p 'test_*.py'→ 13 tests, OK;-s scripts/install→ 17 tests, OK;-s .github/scripts→ OK. The Rust and Bazel suites could not be run here —which cargo rustc just bazelall return not-found on this machine, so their result is unverified rather than assumed. - Recommendation: —
- Priority: High
-
19. Can the test command be discovered without guessing — is it written down where an agent reads? If no test suite exists, FAIL with a one-line proof pointing at the test-suite item. Otherwise check the places an agent looks: the agent instruction file, the README, the manifest's scripts or targets.
- Status: PASS
- Proof:
just testis named in the instruction set (AGENTS.md:66-68, with the crate-scoped formjust test -p codex-tuiand the rule not to usecargo test), indocs/install.md("just testruns the test suite via nextest"), indocs/contributing.md("Run all checks locally...just test -p codex-tuiorjust test"), and discoverable from the tool itself —just helprunsjust -l, and every target injustfilecarries a doc comment. - Recommendation: —
- Priority: High
-
20. Do the tests assert real behaviour, rather than asserting that a mock was called? If no test suite exists, FAIL with a one-line proof pointing at the test-suite item. Otherwise open the largest test files and read the assertions: calling real code on real inputs passes;
expect(mock).toHaveBeenCalled()as the main dish fails.- Status: PASS
- Proof: Real behaviour, and the mocking that exists is at the network edge rather than over the code under test.
codex-rs/core/tests/suite/drives a real Codex session built byTestCodexBuilderagainst a mock SSE/responsesendpoint, then asserts on the payloads the real code actually produced —AGENTS.md:226-250documents the pattern and the helpers (ResponseMock::single_request(),request.function_call_output(call_id),request.body_json()). Sampledcodex-rs/core/tests/suite/approvals.rs: assertions compare real session state, e.g.assert_eq!(test.session_configured.active_permission_profile.as_ref().map(|profile| profile.id.as_str()), Some(BUILT_IN_PERMISSION_PROFILE_WORKSPACE))at line 726.instasnapshots assert rendered TUI output.AGENTS.md:212-214mandatespretty_assertions::assert_eqon whole objects and forbids mutating process environment in tests;AGENTS.md:114-121requires integration tests over unit tests for agent changes and bans test-only functions in implementation files. Noexpect(mock).toHaveBeenCalled()-style pattern found as the main assertion. - Recommendation: —
- Priority: High
-
21. Is there a linter or static analysis configured for this language, and does it pass on a clean checkout? Configured is not enough — run it. A linter that exits non-zero on an untouched checkout is a FAIL with the error count in the proof, because an agent cannot tell its own damage from the baseline noise.
- Status: FAIL
- Proof: Static analysis is unusually thorough:
codex-rs/clippy.toml(disallowed-methods with a reason on each,await-holding-invalid-types,large-error-threshold),[workspace.lints.clippy]incodex-rs/Cargo.toml, a custom Dylint pass attools/argument-comment-lint/with its own UI tests,cargo-shearandcargo-deny(codex-rs/deny.toml),codespell(.codespellrc),markdownlint-cli2,prettier, plus three bespoke verifiers in.github/scripts/. But one blocking check does not pass on this untouched checkout ofmain(a7b8c07):python3 .github/scripts/verify_cargo_workspace_manifests.pyexits 1 with "codex-rs/code-mode/Cargo.toml: - remove the stale[features]exception fromMANIFEST_FEATURE_EXCEPTIONS". That check is wired into the merge-blocking suite viarepo-checks.yml, so an agent running the repo's own checks sees a red baseline it did not cause. Clippy itself could not be run here — nocargoon this machine — so its clean-checkout status is unverified; the failure above is reproducible withpython3alone. - Recommendation: Clear the stale exception: drop the
codex-rs/code-modeentry fromMANIFEST_FEATURE_EXCEPTIONSin.github/scripts/verify_cargo_workspace_manifests.py(or remove the[features]block fromcodex-rs/code-mode/Cargo.toml, whichever the migration intended) so the verifier is green onmain. - Priority: High
-
22. Is there a formatter, so an agent's diffs do not churn on style? Look for the config file and the dependency in this ecosystem's form — .prettierrc, rustfmt, gofmt, black, an .editorconfig doing real work. If the language ships one formatting standard with the toolchain, that is a PASS and the proof says so.
- Status: PASS
- Proof:
just fmt→scripts/format.py, which covers the justfile, Rust (rustfmt with--config imports_granularity=Item), Bazel/Starlark via buildifier, and Python;just fmt-checkis the non-mutating form..prettierrc.tomlplus.prettierignorecover JSON, Markdown, YAML and JS, wired topnpm format/format:fixinpackage.json. Formatting is enforced pre-merge:.github/workflows/rust-ci.ymlrunscargo fmt -- --config imports_granularity=Item --check.AGENTS.md:64tells the agent to runjust fmtafter every change without asking for approval. - Recommendation: —
- Priority: Low
-
23. Is there a compile-time or type-level gate, if this language offers one? N/A only when the language genuinely has no such gate. If the language offers one and the repo does not use it — no strict mode, no typecheck script, no compiler step — that is a FAIL. Run the gate if it exists and record the result.
- Status: PASS
- Proof: Rust's compiler is the gate and the repo pins and configures it:
codex-rs/rust-toolchain.tomlpins channel 1.95.0 withclippy,rustfmt,rust-src;[workspace.lints.clippy]incodex-rs/Cargo.tomlis enforced workspace-wide, and.github/scripts/verify_cargo_workspace_manifests.pyexists specifically to catch crates that forget[lints] workspace = true("Without that opt-in,cargo clippycan miss violations that Bazel clippy catches"). The Bazel and Cargo lint sets are kept in lockstep by.github/scripts/verify_bazel_clippy_lints.py, which I ran: exit 0, "Bazel clippy flags in .bazelrc match codex-rs/Cargo.toml [workspace.lints.clippy]." On the wire side,ts-rsgenerates TypeScript from the Rust types with committed schema fixtures undercodex-rs/app-server-protocol/schema/, regenerated byjust write-app-server-schema. Compilation itself could not be run here (nocargo). - Recommendation: —
- Priority: Low
-
24. Can an agent prove its own work before it pushes — one command, task-runner target or commit hook that runs every check this project has? One command, not a list to remember: a
checkorverifytarget, aprecommitscript, a Makefile target that chains them. Separate commands documented side by side are close but FAIL — the question is whether the agent can run the whole gauntlet without knowing its parts.- Status: FAIL
- Proof: No single entry point.
justfilehas 40+ targets but none of them is acheck,verifyorprecommitthat chains the others —grep -nE '^[a-z][a-z0-9-]*( \*args)?:' justfileshowsfmt,fmt-check,fix,clippy,test,bazel-test,bazel-clippy,argument-comment-lint,bazel-lock-checkall as separate leaves. There are no git hooks either: no.pre-commit-config.yaml, nohusky, no.githooksanywhere ingit ls-files. SoAGENTS.mdhas to spell out a conditional sequence the agent must carry itself —just fmtalways (line 64), thenjust test -p <crate>and possibly fulljust test(lines 66-68), thenjust fix -p <project>(line 70), plusjust bazel-lock-updateif Cargo deps changed (line 37),just write-config-schemaif config types changed (line 34),just write-app-server-schemaif API shapes changed (line 302), andjust argument-comment-lintfor positional literals (line 20). Documented side by side, but seven commands and four conditionals is exactly what this question is about. - Recommendation: Add a
checktarget tojustfilethat chainsfmt-check,clippy,test,bazel-lock-checkand the three.github/scripts/verify_*.pyverifiers, then pointAGENTS.mdatjust checkas the one command to run before pushing. - Priority: High
-
25. Is there continuous integration, and does it run before a change lands rather than after? A deploy pipeline that runs on push to the default branch runs after the change has landed — that is a FAIL with the trigger quoted, not a PASS with a caveat. Look for a pre-merge trigger: pull_request events, merge trains, or this forge's equivalent.
- Status: PASS
- Proof:
.github/workflows/blocking-ci.ymlis the single merge gate and triggers pre-merge:on: pull_request: {}withpush: branches: [main]alongside it, described in the file as "the single entrypoint for checks that block a PR merge". It fans out to seven reusable workflows —bazel,blob-size-policy,cargo-deny,codespell,repo-checks,rust-ci,sdk— and aggregates them into arequiredjob carryingif: ${{ always() }}with the comment "Withoutalways(), GitHub skips this job after a failed dependency and a required check can appear successful instead of reporting the failure." Post-merge work is deliberately separated into.github/workflows/postmerge-ci.yml(rust-ci-full,v8-canary) rather than being mistaken for the gate. - Recommendation: —
- Priority: High
-
26. Does CI actually run the tests and the checks that exist in this repo? If no pipeline of any kind exists, FAIL with a one-line proof pointing at the CI item. Otherwise list what the pipeline runs and diff it against every check found in the Verification section — name each check that exists in the repo but is missing from the pipeline.
- Status: PASS
- Proof: Diffed the pipeline against every check found in this section. Tests:
bazel.ymlrunsbazel test //...across a Linux/macOS/Windows matrix plus a 4-way shardedx86_64-pc-windows-gnullvmjob, andrust-ci-full.ymlruns the full nextest matrix post-merge. Formatter:rust-ci.yml→cargo fmt -- --config imports_granularity=Item --check. Linters:cargo_shearjob inrust-ci.yml,argument_comment_lint_prebuiltacross all three platforms,cargo-deny.yml,codespell.yml. Type/lint parity and the bespoke verifiers:repo-checks.ymlrunsverify_cargo_workspace_manifests.py,verify_tui_core_boundary.py,verify_bazel_clippy_lints.py, thescripts/codex_packageandscripts/installunittest suites, the macOS notarization tests,asciicheck.py README.mdand the README ToC check. Lockfile drift:bazel.ymlruns./scripts/check-module-bazel-lock.shand the rusty_v8 checksum check. Benchmarks:just bench-smokeinrust-ci.yml. Every job also ends with thecheck-clean-worktreeaction, which catches generated files a change forgot to commit. Nothing found in the repo is missing from the pipeline. - Recommendation: —
- Priority: High
-
27. Does anything here get an LLM to read a change and go looking for problems — a review skill, a saved review prompt, or an AI reviewer on the pull requests? Look for a committed review skill or slash command, a CI step calling an AI reviewer, or bot config. Human review rules are a Safety item; this one is specifically about machine review.
- Status: PASS
- Proof: Machine review is committed and structured.
.codex/skills/code-review/SKILL.mdis an orchestrator that fans out one subagent per dimension at xhigh reasoning and requires a file path and line number on every finding; the dimensions are.codex/skills/code-review-breaking-changes/,code-review-change-size/,code-review-context/andcode-review-testing/, and they mirror the "Code Review Rules" section ofAGENTS.md:85-131. On the forge side,.github/codex/labels/codex-review.md,codex-rust-review.md,codex-attempt.mdandcodex-triage.mdare saved review prompts wired to label-triggered workflows, with.github/workflows/issue-labeler.ymlandissue-deduplicator.ymlrunning Codex against issues from a protectedissue-triageenvironment. - Recommendation: —
- Priority: Low
4. Tooling
-
28. Can an agent reach the outside systems this project depends on, with that access committed to the repo rather than set up per laptop? MCP servers are one form: look for a committed
.mcp.jsonor this ecosystem's equivalent. A CLI is another and often the better one —aws,gh,psql,kubectl,stripe, a vendor's own tool — and it counts when the repo names which tools the work needs and how to authenticate, so an agent is not guessing at a tool it cannot see. Judge the axis, not the mechanism: access that exists only in someone's shell history or laptop config is a FAIL, and so is a committed config that turns out to be gitignored, with the distinction in the proof. Project task scripts have their own item; this one is about reaching past the repo's edge. If this project genuinely talks to nothing outside itself, N/A with that as the reason.- Status: PASS
- Proof: GitHub is the outside system, the CLI is the mechanism, and it is committed rather than living in a shell history:
.codex/skills/babysit-pr/scripts/gh_pr_watch.pyand.codex/skills/codex-issue-digest/scripts/collect_issue_digest.pyboth drivegh, each with a sibling test file, and.codex/skills/babysit-pr/references/github-api-notes.mddocuments the API surface they rely on. Authentication isgh's own login locally andGH_TOKEN: ${{ github.token }}inrepo-checks.yml..codex/environments/environment.tomlcommits the cloud dev-environment run command. There is no committed.mcp.jsonor equivalent —git ls-files | grep -iE 'mcp.json|\.mcp'returns nothing, and.github/codex/home/config.tomlis two lines:model = "gpt-5.1"and the comment "# Consider setting [mcp_servers] here!" — so the MCP route is an acknowledged blank rather than a hidden dependency. The CLI route covers the work that actually happens here. - Recommendation: —
- Priority: Low
-
29. Is there a skills, commands or reusable-prompt library in the repo? Look for .claude/skills, .agents/skills, .claude/commands, or a prompts directory. Committed and pinned beats committed; note whether anything ties the copies to a source.
- Status: PASS
- Proof:
.codex/skills/holds 13 skills across 24 tracked files:babysit-pr,code-reviewplus fourcode-review-*dimensions,codex-bug,codex-issue-digest,codex-pr-body,path-types,pushing-ci-changes,remote-tests,test-tui,update-v8-version. Three carry per-agent config (agents/openai.yaml), two ship executable scripts with their own unit tests (test_gh_pr_watch.py,test_collect_issue_digest.py), andbabysit-prhas areferences/directory withgithub-api-notes.mdandheuristics.md. All committed and first-party, so there is nothing vendored to pin — no lock or manifest ties them to an upstream source, which is the right call here but worth noting..claude/andCLAUDE.mdare gitignored, so this library is reachable by Codex-family agents only. - Recommendation: —
- Priority: Low
-
30. Do the skills, servers and tools that exist cover the work this team plainly repeats? First identify the repeated work from the README and the commit history. If skills, servers or documented tooling exist but miss it, FAIL naming the gap. If none exist at all and the repo plainly repeats work, FAIL pointing at the outside-systems item and the skills-library item. If the project is too small to repeat anything, N/A.
- Status: PASS
- Proof: The repeated work is legible from
git logand the workflow set, and the skills line up against it almost one-to-one. Shepherding a PR through a seven-job blocking suite →babysit-pr(withgh_pr_watch.pyandheuristics.md). Reviewing a change against the four house rules →code-reviewplus its four dimension skills. Issue triage at volume →codex-issue-digestplus theissue-labelerandissue-deduplicatorworkflows. Bumping V8, a recurring chore visible inv8-canary.yml,rusty-v8-release.yml,.github/scripts/rusty_v8_bazel.pyandv8_canary_changes.py→update-v8-version. Cross-OS app-server/exec-server integration testing →remote-testsplusscripts/test-remote-env.sh. TUI testing →test-tui. Writing PR bodies →codex-pr-body. Filing a repro →codex-bug. Getting a CI-config push approved →pushing-ci-changes. No obvious repeated job is left uncovered. - Recommendation: —
- Priority: Low
-
31. Are there project CLI scripts or task-runner targets for the common jobs? Check the manifest's scripts, the Makefile, the justfile, or this ecosystem's equivalent. The test: does routine work need a raw multi-flag command that someone has to remember?
- Status: PASS
- Proof:
justfilecarries 40+ documented targets covering run (codex,exec,file-search,code-mode-host,mcp-server-run,tui-with-exec-server), check (fmt,fmt-check,fix,clippy,test,bazel-test,bazel-clippy,argument-comment-lint), codegen (write-config-schema,write-app-server-schema,write-hooks-schema), release (build-for-release), benchmarks (bench,bench-smoke,bench-e2e) and debugging (log, which tails the state SQLite database). Alongside it:package.jsonscripts for formatting,scripts/as a proper Python package withpyproject.tomlanduv.lock,.github/scripts/for CI-side jobs, andtools/argument-comment-lint/for the custom lint. Routine work is a named target throughout — the multi-flag Bazel invocations that would otherwise have to be remembered are wrapped, e.g.bench-e2e-smokehides four--@rules_rust//...flags behind one name. - Recommendation: —
- Priority: High
-
32. Are those scripts named somewhere the agent will actually read them? If no scripts exist, FAIL with a one-line proof pointing at the task-scripts item. Otherwise check the agent instruction file, the README, and whether the manifest itself is self-explanatory.
- Status: PASS
- Proof: Named in all three places an agent looks.
AGENTS.mdnames nine of them inline with the conditions for running each.docs/install.mdrepeats the core loop (just fmt,just fix -p <crate>,just test -p codex-tui,just test) anddocs/contributing.mdsays to "Use the rootjusthelpers so you stay consistent with the rest of the workspace". The runner is self-describing:just helprunsjust -l, and every target injustfilehas a#doc comment above it thatjust -lprints. - Recommendation: —
- Priority: High
-
33. Can an agent get this project running — is there a reproducible environment or a documented setup path? Look for a pinned runtime (.nvmrc, .tool-versions, rust-toolchain), a lockfile, a container or nix file, and written setup steps. Try the first step if it is cheap and safe. This one bites hardest the moment work happens in a fresh git worktree or a new clone — the normal way to run agents in parallel. A new worktree has no installed dependencies, no
.env, no build cache, so anything that works today only because of untracked state sitting on someone's machine simply does not run there. The test: would a bare checkout plus the written steps get this project up? Name any prerequisite nothing creates — an env file someone hand-made, a seeded database, a manual login — because each one is a wall a worktree hits on its first command.- Status: PASS
- Proof: The pinning is comprehensive:
codex-rs/rust-toolchain.toml(1.95.0 plus components),.bazelversion(9.0.0),package.jsonengines(node >=22, pnpm >=10.33.0) and apackageManagerfield carrying a sha512, and eight tracked lockfiles —codex-rs/Cargo.lock,tools/argument-comment-lint/Cargo.lock,pnpm-lock.yaml,.devcontainer/codex-install/pnpm-lock.yaml,MODULE.bazel.lock,flake.lock,scripts/uv.lock,sdk/python/uv.lock,sdk/python-runtime/uv.lock. Environments:flake.nixdev shell for all four Linux/macOS arches, and.devcontainer/with two Dockerfiles,init-firewall.shandpost-start.sh. Written setup:docs/install.mdgives the full sequence fromgit clonethroughrustup,cargo install --locked just/dotslash/cargo-nextest,cargo build,cargo run. Worktree angle: nothing here needs untracked hand-made state — no.envis tracked and none is required (the CLI reads~/.codex/config.tomlat runtime, documented indocs/config.md), no seeded database, no manual login for a build. The repo has explicitly thought about worktrees:.worktreeincludelistsuser.bazelrcas the one untracked file a new worktree should carry over. The prerequisite a bare checkout does hit is the fourcargo installtool fetches, andAGENTS.md:7covers it ("Install any commands the repo relies on (for examplejust,rg, orcargo-insta) if they aren't already available"). I could not run the first step to confirm — no Rust toolchain on this machine. - Recommendation: —
- Priority: High
-
34. Can an agent see the results of a failed run — do the tools here produce output it can read and act on? Judge from the runs you already did in Verification: does a failure print a path, a line, a name — something actionable — or a wall of noise? If nothing could be run, FAIL saying why.
- Status: PASS
- Proof: Judged from the runs I did.
verify_cargo_workspace_manifests.pyfailed with the exact file and the exact remedy — "codex-rs/code-mode/Cargo.toml: - remove the stale[features]exception fromMANIFEST_FEATURE_EXCEPTIONS" — preceded by a paragraph explaining why the rule exists at all.verify_bazel_clippy_lints.pyprinted a one-line confirmation naming both files it compared. The unittest runs printed counts and status ("Ran 17 tests in 20.671s / OK"). Lint messages are written to be actionable by design: every entry incodex-rs/clippy.tomlcarries areasonthat names the replacement, e.g. "Create SQLite pools through codex-state's sqlite shim" and "Use ANSI colors, which work better in various terminal themes".codex-rs/.config/nextest.tomlwritesjunit.xml, andbazel.ymluploads execution logs as artifacts. - Recommendation: —
- Priority: Low
5. Safety
-
35. Are credentials kept out of the repo — nothing secret committed, ignore rules in place, an example env file for the shape? Three checks: grep tracked files for key-shaped strings, read the ignore rules for env and key patterns, and look for an example env file. Report each of the three separately.
- Status: PASS
- Proof: Three checks, separately. (a) Key-shaped strings in tracked files:
git grep -nIE '(sk-[A-Za-z0-9]{20,}|AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{30,}|-----BEGIN (RSA|OPENSSH|PRIVATE) )'returns five hits, all deliberate test material —codex-rs/secrets/src/sanitizer.rs:48,52("Bearer sk-abcdefghijklmnopqrst+secret_suffix", "Bearer AKIAABCDEFGHIJKLMNOP/~secret_suffix" as sanitizer inputs),codex-rs/memories/write/src/phase1.rs:763,773(a fake token plus the assertion that it is not serialized),codex-rs/agent-identity/src/lib.rs:832(a test PEM). No live credential found. (b) Ignore rules:.gitignorecarries.env*with a!.env.examplenegation, plus.venv/andpersonal/. (c) Example env file: none tracked — the!.env.examplenegation has nothing to match. That sub-check is satisfied in this repo's own idiom instead: runtime configuration is~/.codex/config.toml, and its shape is documented at length indocs/config.mdanddocs/example-config.md. - Recommendation: —
- Priority: High
-
36. Does anything scan for secrets automatically? Look for gitleaks, trufflehog, detect-secrets or this ecosystem's equivalent, wherever it is wired in — a CI step, a pre-commit hook, or forge-level push protection visible from the repo. CI is where this normally lives, and that is a PASS; a local hook on top is better, because it catches the key before it is pushed rather than after, but its absence is a line in the proof, not a FAIL. Say where the scan runs. "Nothing secret exists today" does not make this N/A — the scan is for the day that changes.
- Status: FAIL
- Proof: Nothing scans.
grep -rilE 'gitleaks|trufflehog|detect-secrets|secret-scan|ggshield' .github scriptsreturns no hits. The seven jobs inblocking-ci.ymlarebazel,blob-size-policy,cargo-deny,codespell,repo-checks,rust-ci,sdk—cargo-denycovers advisories and licences,blob-size-policycovers blob size, neither looks at content for keys. There is no local hook either: no.pre-commit-config.yaml, nohusky, no.githooksingit ls-files. Org-level GitHub push protection may well be enabled, but nothing visible from the repo shows it. This matters more here than in most repos, because the codebase deliberately contains key-shaped test fixtures (see the credentials item), so a real key would not stand out to a human skimming a diff. - Recommendation: Add a
secret-scanjob to.github/workflows/blocking-ci.ymlnext tocodespell— agitleaksaction over the PR diff — and addcodex-rs/secrets/src/sanitizer.rs,codex-rs/memories/write/src/phase1.rsandcodex-rs/agent-identity/src/lib.rsto its allowlist so the known test fixtures do not make it noisy. - Priority: High
-
37. Are dependencies pinned, so a build is reproducible? Look for lockfiles in every package of the repo, exact versions for load-bearing dependencies, a pinned runtime, and an install command that respects the lock (npm ci, not npm install).
- Status: PASS
- Proof: Eight lockfiles, all tracked:
codex-rs/Cargo.lock,tools/argument-comment-lint/Cargo.lock,pnpm-lock.yaml,.devcontainer/codex-install/pnpm-lock.yaml,MODULE.bazel.lock,flake.lock,scripts/uv.lock,sdk/python/uv.lock,sdk/python-runtime/uv.lock. Runtime pinned bycodex-rs/rust-toolchain.toml(1.95.0),.bazelversion(9.0.0), andpackage.jsonpackageManager: pnpm@10.33.0+sha512.... Install respects the lock:repo-checks.ymlrunspnpm install --frozen-lockfile, andjust installrunscargo fetchagainst the committed lock. Above the bar in two more ways — every GitHub Action is pinned to a commit SHA rather than a tag (actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2), andpackage.jsonresolutionspins 16 transitive dependencies to exact versions (esbuild: 0.28.1,hono: 4.12.25,flatted: 3.4.2, ...). Drift is actively policed:just bazel-lock-checkfails with "MODULE.bazel.lock is out of date",bazel.ymlrunsscripts/check-module-bazel-lock.sh,AGENTS.md:37-39tells agents to runjust bazel-lock-updatein the same change, andcargo-deny(codex-rs/deny.toml) runs in the blocking suite. - Recommendation: —
- Priority: High
-
38. Is anything watching those dependencies for known vulnerabilities? Look for dependabot or renovate config, an audit step in CI, or this ecosystem's equivalent. Check every lockfile in the repo is covered, not just the root one.
- Status: FAIL
- Proof: Something is watching, but not everything.
.github/dependabot.yamlcovers six ecosystems weekly with a 7-day cooldown:bun(.github/actions/codex),cargo(codex-rsandcodex-rs/*),devcontainers(/),docker(codex-cli),github-actions(/),rust-toolchain(codex-rs);cargo-denyadds advisory checking for the Rust workspace in blocking CI. Checked every lockfile against that list, and six of the nine are uncovered: the rootpnpm-lock.yamland.devcontainer/codex-install/pnpm-lock.yaml(no npm or pnpm ecosystem entry at all), all three Python locks —scripts/uv.lock,sdk/python/uv.lock,sdk/python-runtime/uv.lock— andtools/argument-comment-lint/Cargo.lock, which thecodex-rs/*glob does not reach. Thesdk/gap is the sharpest one, because.github/workflows/python-sdk-release.ymlpublishes that tree to PyPI. - Recommendation: Add three blocks to
.github/dependabot.yaml:package-ecosystem: npmfor/and/.devcontainer/codex-install,package-ecosystem: uvfor/scripts,/sdk/pythonand/sdk/python-runtime, and extend the cargodirectorieslist withtools/argument-comment-lint. - Priority: Low
-
39. Are the review rules written down — who reads a change, and what they check? Look for CONTRIBUTING, a PR template, or a review checklist in the agent instruction set. On a solo repo the "who" is N/A-shaped but the "what gets checked before it lands" still matters — judge that half.
- Status: PASS
- Proof: Written down in four places, and they agree. Who:
docs/contributing.md("One maintainer will be assigned as a primary reviewer", squash-and-merge, invitation-only, CLA flow) plus.github/CODEOWNERS, which assigns@openai/codex-core-agent-teamto the core crates (core/,codex-mcp/,exec-server/,arg0/,prompts/), to the macOS signing paths, and toCODEOWNERSitself. What gets checked:.github/pull_request_template.mdasks for What/Why/How plus a linked issue;docs/contributing.mdlists the pre-PR bar (run all checks locally, atomic commits, tests that fail before and pass after); andAGENTS.md:85-131is a full review checklist — keep crate API surfaces small, the six model-visible-context rules with "Highlight new individual items that can cross >1k tokens as P0", the five breaking-change surfaces to search, integration tests mandatory for agent-logic changes, and the 800-line/500-line change-size ceilings with staging guidance. The four.codex/skills/code-review-*skills encode the same list for machines. - Recommendation: —
- Priority: Low
-
40. Are the operations that need a human named somewhere an agent will read them? Look for a "never without asking" list in the agent instruction file or the README. Docs that hand out production commands with no fence around them count against, and the proof should quote one.
- Status: FAIL
- Proof: Several ask-first operations are named where an agent reads them:
AGENTS.md:68("project-specific or individual tests can be run without asking the user, but do ask the user before running the complete test suite"),AGENTS.md:64marksjust fmtas explicitly not needing approval,.codex/skills/code-review/SKILL.md("Do not leave GitHub comments unless explicitly asked"), and.codex/skills/pushing-ci-changes/SKILL.mdexplains that pushes touching.github/**/*.ymlare rejected until a human obtains an approval the agent cannot request itself. What is missing is any fence around the one operation in this repo that ships software to the public:.github/workflows/rust-release.ymlopens with the recipe, unqualified — "To release, follow a workflow like:git tag -a rust-v0.1.0 -m \"Release 0.1.0\"/git push origin rust-v0.1.0" — and neitherAGENTS.mdnorREADME.mdnordocs/contributing.mdsays that pushing arust-v*tag is a human-only act. There is no consolidated "never without asking" list anywhere in the instruction set. - Recommendation: Add a short "requires a human" block to
AGENTS.mdnaming the three operations an agent must not perform unattended: pushing arust-v*orpython-v*tag (both trigger public signed releases), pushing changes under.github/**(see.codex/skills/pushing-ci-changes/SKILL.md), and running the fulljust testsweep. - Priority: High
-
41. Does every action that spends money, destroys data or changes production have a human in the way? Start from the damage, not from the tooling: list what in reach of this repo could charge a card, drop or overwrite data, or alter what users are running. Then trace the shortest route an agent could take to each one — a push that auto-deploys, a script carrying live credentials, a migration that runs on merge, an infrastructure apply with no plan-and-approve step. PASS when every route meets a human first, whether that is a review, a manual trigger or a protected environment. FAIL when even one route runs start to finish unattended, and quote that route in the proof so the fix is obvious.
- Status: PASS
- Proof: Traced every route from the damage backwards. Public release of signed binaries:
.github/workflows/rust-release.ymlfires only onpush: tags: rust-v*.*.*— a deliberate human act — and its header records that "Tag releases sign macOS binaries and DMGs through the protectedcodesigningGitHub environment and Azure Key Vault", so a protected environment gates the signing keys. CDN publish:.github/workflows/r2-release.ymlisworkflow_callonly, never triggered directly, and runs in the protectedenvironment: codex-r2-publisher. PyPI publish:python-sdk-release.ymlonpush: tags: python-v*, additionally fenced byif: github.repository == 'openai/codex'. Reachingmainat all:blocking-ci.ymlonpull_requestwith arequiredaggregate check,CODEOWNERSreview on the core crates, and an invitation-only contribution policy. CI configuration: a push restriction on.github/**/*.ymlthat needs an out-of-band approval.postmerge-ci.ymlruns on push tomainbut only runs tests and the V8 canary — it deploys nothing. There is no migration-on-merge, noterraform apply, no infrastructure apply anywhere in the repo. Every route meets a human. - Recommendation: —
- Priority: High
-
42. If a prompt injection landed tonight, how far would it reach — are the credentials an agent can get to here scoped to the job, with nothing production-grade in reach? Inventory what an agent in this repo can reach: env files, cloud CLI profiles, tokens named in docs or config, deploy commands that work from a laptop. Scoped-or-absent passes; production-grade reach fails with the item named.
- Status: PASS
- Proof: Inventory of what an agent in a local checkout can actually reach: no
.envis tracked and none is required; no cloud CLI profile or service-account file is committed;.github/codex/home/config.tomlholds onlymodel = "gpt-5.1"; CI secrets aresecrets: inheritinside GitHub Actions, reachable only from a workflow run, not from a checkout on disk; and the release path needs a signed tag plus a protected environment, so a laptop cannot deploy. The one real reach isghauthentication for the PR and issue skills — repo-scoped, and its most dangerous target (.github/**) is separately fenced by the CI-push restriction. Nothing production-grade is in reach. Worth noting that the product this repo builds is itself a sandbox:codex-rs/linux-sandbox,codex-rs/bwrap, Seatbelt integration,codex-rs/network-proxy,codex-rs/execpolicy, andAGENTS.md:8forbids touching the sandbox environment variables at all. - Recommendation: —
- Priority: High
-
43. Can a change reach production a slice at a time — a feature flag that defaults to off, a canary, a staged rollout — rather than everyone at once? Look for a flag system and check the default, or canary and staged-rollout config in the deploy pipeline. Flags that need a rebuild to flip are worth naming in the proof — they gate exposure but they are not a kill switch.
- Status: PASS
- Proof:
codex-rs/features/is a real flag registry, not a boolean scattered through the code:src/lib.rsdefines aStageenum withUnderDevelopment("still under development, not ready for external use"),Experimental(carrying a menu name, description and announcement, surfaced through the/experimentalmenu),Stable,DeprecatedandRemoved, andsrc/feature_configs.rsholds the per-feature TOML config types (CodeModeConfigToml,MultiAgentV2ConfigToml,NetworkProxyConfigToml, ...). Flags resolve from config-like inputs, so they flip at runtime through~/.codex/config.tomlor-c key=valueon the command line — no rebuild needed, which is the kill-switch property this question is after. On the distribution side,rust-release.ymlcomputesprerelease=true/make_latest=falsefor any version carrying a suffix afterx.y.z, so an alpha ships to people who ask for it without becoming the default download, andv8-canary.ymlgives the riskiest dependency bump its own canary lane. - Recommendation: —
- Priority: High
-
44. Once a change is live, can anyone see what it is doing — logs, metrics, traces, alerts that fire on their own, and can an agent read them too? Look for logging setup, an error tracker, analytics, alerting config — and then ask the second half: could an agent reach any of it (a CLI, an MCP server, an API named in the docs), or does observability stop at a dashboard behind a login?
- Status: PASS
- Proof: Instrumentation:
codex-rs/otel/(OTLP exporter, provider, metrics, events,trace_context.rs,targets.rs),codex-rs/analytics/,codex-rs/diagnostics/, andcodex-rs/cli/src/doctor/for self-checks;AGENTS.md:45-48mandates#[tracing::instrument(...)]on definitions rather than spans at call sites. The second half also holds — an agent can read it without a browser:just logrunscargo run -p codex-cli --bin logs_clientto tail the state SQLite database from the terminal,docs/install.mddocumentsRUST_LOGandcodex -c log_dir=./.codex-logfollowed bytail -F ./.codex-log/codex-tui.log, andcodex-rs/.config/nextest.tomlemitsjunit.xml. Server-side telemetry for OpenAI's own fleet is not visible from the repo, which is expected for a client-side CLI. - Recommendation: —
- Priority: Low
-
45. Is there a way back — can a bad change be undone without a rebuild and a redeploy, including the ones that touched a database or a queue? Look for a documented rollback path, a revert-and-redeploy story, down-migrations, or a flag that can turn the change off at runtime. Deployment docs that only say how to go forward are worth quoting.
- Status: PASS
- Proof: Three ways back, none needing a rebuild. Runtime: any feature can be turned off through
~/.codex/config.tomlor-c key=valuebecausecodex-rs/features/resolves flags from config at startup rather than at compile time. Version:README.mddocuments downloading a specific platform binary from any GitHub Release, anddocs/install.mddocuments the DotSlash idiom for pinning an executable version in source control — "makes it possible to make a lightweight commit to source control to ensure all contributors use the same version of an executable". Release-level:make_latest=falseon prereleases keeps a bad build from becoming the default download. Two honest gaps: there is no written rollback runbook —grep -ril 'rollback|revert' docs .github/workflowsfinds onlydocs/contributing.md("Keep commits atomic... This makes reviews and potential rollbacks easier") — and the local state migrations undercodex-rs/state/migrations/,goals_migrations/,logs_migrations/andmemory_migrations/are forward-only numbered SQL files with no down-migrations, so downgrading to an older binary after a schema bump is untested territory. - Recommendation: —
- Priority: Low
-
46. Does a past failure leave a check behind — is there a test or a rule in here that exists because something broke once? Look for tests, lint rules or comments that name the incident they guard against — "regression", "this broke when", a linked issue. On a very young repo with no failures yet, N/A with the age as the reason.
- Status: PASS
- Proof: Failures leave checks behind, in both forms. Named regression tests:
codex-rs/file-search/src/lib.rs:1075("Regression test for #3493: a parent directory's.gitignorewith*"),codex-rs/tui/tests/suite/status_indicator.rs:1("Regression test: ensure thatStatusIndicatorWidgetsanitises ANSI escape"), plus regression coverage incodex-rs/core/tests/suite/mcp_auth_refresh.rs,codex-rs/app-server/tests/suite/v2/remote_thread_store.rsandrealtime_conversation.rs. Whole checks that exist because something broke:.github/scripts/verify_tui_core_boundary.py(codex-tui must not import codex-core),verify_bazel_clippy_lints.py("Without that opt-in,cargo clippycan miss violations that Bazel clippy catches"),blob-size-policy.ymlwith its.github/blob-size-allowlist.txt,just bazel-lock-check, thecheck-clean-worktreeaction on every CI job,scripts/mcp_conformance/regression-baseline-v1.jsonwithreview_regressions.py, and everyreasonstring incodex-rs/clippy.toml— the sqlx pool bans and "Audited against workspace sqlx 0.9.0. Revisit this SQLite escape-hatch list when bumping sqlx" read as scar tissue.codex-rs/.config/nextest.tomlsetsretries = 1with the comment "Retry once so one transient failure does not fail full-CI outright." - Recommendation: —
- Priority: Low
Learn more: https://ainativesoftware.engineering/
Nothing here is special to openai/codex. Install the skill and ask your agent to run it — it answers the same 46 checks and writes the same file into your repo.
npx skills add alfonsograziano/skills --skill aine-readiness-analyzerAI-Native Software Engineering