Repository navigation
Codex: stage native TOML sub-agents with resolved models and fail closed before startup - #70945
Conversation
Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
…l closed before spawn Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
|
Review findings (round 2): Round 2 for this PR (#70945, issue #70939). Review findings to address:
|
…ound-trip tests; restore logs schema Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
All four items are addressed in 7084160.
Checks: the targeted JS tests (547), the typecheck and
|
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft. Design Decision Gate 🏗️Outcome: The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible. Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.
|
|
✅ PR Code Quality Reviewer completed the code quality review.
|
|
✅ Test Quality Sentinel completed test quality analysis. Test Quality SentinelOutcome: The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible. Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.
|
|
✅ Ponytail Reviewer completed successfully!
|
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅
|
There was a problem hiding this comment.
One simplification opportunity noted inline.
net: -10 lines possible.
Generated by ✂️ Ponytail Reviewer for #70945 · codex · gpt56 · 21.8 AIC · ⌖ 5.37 AIC · ⊞ 14.8K
Comment /ponytail to run again
Comment MemoryPeek at saved memory (pr-code-quality-reviewer)Note This comment is managed by comment memory.Expand the saved memory block to view or edit the persistent context for this thread.
|
There was a problem hiding this comment.
Verdict
One correctness concern was found in native Codex role staging.
Highlights
The harness writes role files into CODEX_HOME/agents but does not reconcile prior harness-generated files. A reused Codex home or retry can therefore expose stale sub-agents and models that are no longer declared, undermining the fail-closed behavior. An inline comment requests tracking and cleaning only harness-managed role files.
Static review only; tests were not run per review instructions.
🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt50 · 6.97 AIC · ⌖ 0.564 AIC · ⊞ 1.6K
Comment /review to run again
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /improve-codebase-architecture and /tdd on the Codex native-TOML sub-agent staging change (fallback triage heuristic used: pr-triage returned a classification, high-impact files were engine_subagent_models.cjs, codex_harness.cjs, engine_subagent_models.test.cjs, resolve_model_alias.cjs, and the new purelock fixture).
📋 Key Themes & Highlights
Key Themes
- One minor nit posted inline:
mkdirSyncfor the roles directory runs once per agent inside the write loop rather than once before it. Harmless givenrecursive: true, but hoisting it would make the per-agent path read as pure file-writing.
Positive Highlights
- ✅ Fail-closed semantics are implemented thoroughly and symmetrically with Claude: missing
CODEX_HOME, unreadable/unparseable staged files, blank description/instructions, unresolvable models, and endpoint-incompatible models all stop the run before CLI spawn, with no fallback to the main model. - ✅ Real-world fixtures (arXiv run, new purelock run with Copilot-provider endpoint filtering) drive the tests instead of synthetic data, and the harness test snapshots
$CODEX_HOME/agentsat spawn time so assertions reflect true pre-spawn state — a disciplined regression-test habit per/tdd. - ✅ TOML round-trip tests explicitly cover quotes, backslashes, CRLF, triple-quote/control-character edge cases, and lines that look like TOML comments/tables, which is exactly the kind of boundary coverage
/tddcalls for. - ✅ The new
unsupported_endpointcause is threaded consistently through the resolver, error messages,unified_session.cjsvalidation, the.d.tstypes, the JSON schema, and the spec changelog — good cross-cutting consistency for a new domain concept. - ✅ Docs (
inline-sub-agents.md) and the unified-session spec are updated in the same PR, keeping the domain language and behavior description in sync with the code.
No blocking issues found; the one comment left is a style suggestion, not a correctness concern.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 105 AIC · ⌖ 15 AIC · ⊞ 10.2K
Comment /matt to run again
|
Review findings (round 3): Round 3 for this PR (#70945, issue #70939). Your round-2 reply shows that merging this PR would make two production workflows fail at startup with
Keep the PR to this one fix. Before fixing a failing check, compare it with the same check on main; if it also fails on main, leave it and note it in the PR. Regenerated-file drift from main is fine to include. Reply on the PR with what changed. |
There was a problem hiding this comment.
🟡 Changes recommended
Model selection and role registration can diverge from workflow declarations, undermining the intended fail-closed behavior.
7 open issues
Preserve exact model precedence before filtering aliases · New Reject non-string model declarations instead of inheriting · New Migrate scheduled workflows to endpoint-compatible model selectors · New Distinguish unknown endpoint metadata from incompatibility · New Propagate and validate reasoning effort from resolved aliases · New Detect native-role name collisions before registration · New Classify unsupported endpoints separately in audit output · New
1 file not reviewed
actions/setup/js/package-lock.json: Generated file
What changed in this PR
This PR addresses #70939 by converting workflow-declared Codex sub-agents into native TOML roles and enforcing model resolution before startup.
Changes:
- Generate native roles with instructions, resolved models, and reasoning effort.
- Filter model aliases by endpoint compatibility and fail closed on invalid definitions.
- Add regression coverage, captured fixtures, documentation, and the
unsupported_endpointsession cause.
| File | Description |
|---|---|
docs/src/content/docs/specs/unified-agent-session-specification.md |
Document the new failure cause and specification version. |
docs/src/content/docs/reference/inline-sub-agents.md |
Explain native Codex roles and endpoint restrictions. |
docs/public/schemas/unified-session.schema.json |
Accept unsupported_endpoint. |
actions/setup/js/unified_session.test.cjs |
Cover ingestion of the new cause. |
actions/setup/js/unified_session.cjs |
Recognize the new resolution cause. |
actions/setup/js/types/unified_session.d.ts |
Extend resolution-cause typings. |
actions/setup/js/resolve_model_alias.cjs |
Add endpoint-incompatibility diagnostics. |
actions/setup/js/package.json |
Add a TOML parser for tests. |
actions/setup/js/package-lock.json |
Lock the TOML parser dependency. |
actions/setup/js/fixtures/claude-codex-sub-agents/purelock-39601756922/.codex/agents/test-writer.md |
Capture a representative worker definition. |
actions/setup/js/fixtures/claude_codex_subagent_runs.cjs |
Expose purelock fixtures and provenance. |
actions/setup/js/fixtures/awf-reflect-codex-purelock-39601756922.json |
Capture provider endpoint capabilities. |
actions/setup/js/engine_subagent_models.test.cjs |
Test native roles, serialization, and startup failures. |
actions/setup/js/engine_subagent_models.cjs |
Generate roles and enforce model compatibility. |
actions/setup/js/codex_harness.test.cjs |
Verify role files exist before spawn. |
actions/setup/js/codex_harness.cjs |
Gate startup on native-role preparation. |
.changeset/codex-native-toml-subagents.md |
Record the patch release behavior. |
Review effort: Max
…f-spec-compiler-surfacing Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
Fixed in 018d4e0.
Checks:
|
…e endpoints, alias effort, role collisions; audit unsupported_endpoint Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
|
@copilot address the following outstanding work in one pass:
Push the necessary fixes, reply to each listed review thread and resolve it when addressed. Ignore feedback already answered or resolved. Use the pr-finisher skill and stop when only human review or CI remains; do not trigger CI. Sous-chef head: 1c8576a
|
…oml-sub-agents Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Merged the latest |
|
Verified at
|
|
🎉 This pull request is included in a new release. Release: |


Workflow-declared Codex sub-agents were staged only as Markdown. Codex 0.163.0 discovers custom roles only from
.tomlfiles, so it never loaded them. The harness resolved and recorded their models, logged a "not applied" warning, and the run still passed (for exampledaily-arxiv-researcherrun 39570856821).Native role generation (
engine_subagent_models.cjs)declareCodexSubagentModelsis replaced byapplyCodexSubagentModels. Before spawn, it writes one$CODEX_HOME/agents/<name>.tomlper staged agent.name: the declared block name.description: from frontmatter; required.developer_instructions: the Markdown body without frontmatter; required.model: the existing resolver's concrete bare ID.model_reasoning_effort: written only when the selector carries?effort=. The value is checked against the efforts Codex supports.inherit, get nomodelkey and inherit the main model.toolskey, because Codex roles inherit the parent's provider, tools and MCP servers.codex_config.cjsTOML serializer.Example generated role (fixture
paper-screenerwithmodel: small; instructions abbreviated):Fail closed, matching Claude
The harness exits before CLI spawn when:
model.resolutionrecord withrole,status: "failed",resolved_model: nulland the existing cause (model_unavailableorcatalog_unavailable).CODEX_HOMEis unset.No fallback to the main model. The reserved
mainrejection and the threat-detection skip are unchanged. The "not applied" warning is removed.Tests
/reflectcatalog, with every mutation labelled:codex_declared_small_writes_native_toml_before_spawncodex_declared_dead_model_fails_before_spawncodex_no_declared_agents_is_noopmain$CODEX_HOME/agentswhen it starts, so assertions reflect the state at spawn time.Notes for review
rolenow come from the block (file) name. Previously a frontmattername:took precedence. This only differs when the two disagree.daily-arxiv-researcherstill resolves: it uses theopenaiprovider. In main-branch run 39570856821 all four declared models resolvedstatus=exact(gpt-5.6-sol, andgpt-5.4-minithree times), so the fail-closed path should not block it.smoke_codex_native_subagent_uses_resolved_modelstill needs an authorized dry-run dispatch on this branch, covering the GitHub/Copilot-through-AWF and OpenAI provider paths. That run is the evidence of native discovery and named invocation; unit tests alone don't show it.