Skip to content

feat(codex): add --no-model-invocation integration option - #5117

Open
echarrod wants to merge 4 commits into
github:mainfrom
echarrod:feat/2654-codex-no-model-invocation
Open

echarrod wants to merge 4 commits into
github:mainfrom
echarrod:feat/2654-codex-no-model-invocation

Conversation

@echarrod

Copy link
Copy Markdown
Contributor

Description

Refs #2654. Follow-up to #4919 (Claude) and #5116 (Droid).

Adds a Codex CLI-only integration option:

specify init my-project --integration codex --integration-options="--no-model-invocation"
  • It writes agents/openai.yaml with policy.allow_implicit_invocation: false next to each core speckit-* command skill. OpenAI's skills docs say Codex then does not invoke the skill implicitly, while explicit $skill invocation still works. The default is unchanged.
  • Extension skills stay model-invocable, because mandatory hooks such as git's speckit.git.feature need the model to invoke them.
  • The option persists through integration.json, so specify integration upgrade codex reapplies it, and clearing the options removes the generated files (they are tracked in the integration manifest).

Differences from Droid:

  • Codex has no SKILL.md frontmatter flag, so the policy is a separate file. The integration overrides setup() to write it after the skills, and an existing agents/openai.yaml keeps its other keys.
  • Because it is a sibling file, preset overrides of core skills leave it in place; skills registered by commands that bypass setup() get no file until specify integration upgrade codex --force.
  • The docs do not say whether a skill with this policy keeps its name and description in Codex's context, so the new docs section only claims implicit invocation is disabled.

Only the Codex package, its tests and docs/integrations/codex.md change; no shared base.py change.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (fill in the disclosure below)

AI disclosure: Written for @echarrod by Claude Code (claude-sonnet-5-5) running autonomously. It wrote the code, tests and docs, ran the test suite and an automated /code-review medium. @echarrod reviewed it before marking it ready.

Refs github#2654. Writes agents/openai.yaml with policy.allow_implicit_invocation: false
for core command skills; extension skills stay model-invocable.

Assisted-by: Claude Code (claude-sonnet-5-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xh3oZ7vsiPpGXAqtZnULC8
@echarrod
echarrod requested a review from mnriem as a code owner October 25, 2026 18:39
@mnriem mnriem added the triage-nice-to-have Verdict: evidence-backed fix or greenlit feature — land after review label Oct 25, 2026
@mnriem
mnriem requested a max review from Copilot October 26, 2026 14:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Policy-file handling can destroy user configuration and leave implicit invocation disabled after the option is cleared.

4 open issues
What changed in this PR

Adds a Codex-specific opt-out for implicit invocation of core Spec Kit skills, following the Claude and Droid integration options.

Changes:

  • Adds --no-model-invocation and generates per-skill agents/openai.yaml policies.
  • Keeps extension skills unchanged and uses existing option persistence and manifest tracking.
  • Adds tests and documents usage, upgrades, and lifecycle limitations.

Validation used targeted, dependency-free checks; the project test suite was not run.

AI-generated review by GitHub Copilot for the requesting reviewer (identity not provided; model unknown; automated mode; settings not exposed).

File Description
tests/​integrations/​test_integration_codex.py Tests option parsing, policy generation, upgrades, extension exclusion, and metadata merging.
src/​specify_cli/​integrations/​codex/​__init__.py Declares the option and writes tracked policy files for core skills.
docs/​integrations/​codex.md Documents invocation behavior, persistence, and lifecycle caveats.

Review effort: Max

@mnriem

mnriem commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback

@mnriem mnriem added the author-awaiting Waiting on author response label Oct 26, 2026
echarrod and others added 3 commits October 28, 2026 10:39
Setup no longer overwrites an unreadable, invalid or non-mapping
agents/openai.yaml: it validates every target before writing any and
raises naming the file. Policy files are written with record_file() on
the lexical project-relative path, so a symlinked file or agents/
directory is refused before anything is written outside the project.

A pre-existing or user-edited openai.yaml is recorded as partial and
keeps that ownership across upgrades; uninstall, clearing the option and
re-running init without it remove only policy.allow_implicit_invocation
from such files, and delete only unmodified generated ones. Setup
reconciles against the prior on-disk manifest, so re-init without the
option no longer leaves implicit invocation disabled. A user file that
already sets the policy is not claimed.

Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015w5WirGUspLsYEpCkaHWxV
Validate existing policy files before the base setup writes any skill,
and derive manifest paths from the resolved project root. Treat a
generated file whose content still equals the policy (CRLF checkout,
added comment) as generated, so cleanup deletes it rather than leaving a
stub. Keep tracking a user-edited generated file as partial even when it
no longer parses, so upgrade's stale-file pass cannot delete it. Do not
report user files whose policy teardown removed as preserved modified
files. Document that rewritten files lose comments and formatting.

Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015w5WirGUspLsYEpCkaHWxV
Teardown now treats generated openai.yaml files like the option-clearing
path does: a content-equal file (CRLF, added comment) is deleted, and an
edited one keeps its keys and loses only the policy unless --force is
given. A user file whose policy cannot be removed stays tracked so a
later run can retry, and stale policies are released only after the new
ones are written.

Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015w5WirGUspLsYEpCkaHWxV
@echarrod

Copy link
Copy Markdown
Contributor Author

@mnriem I've addressed the Copilot feedback in c409bf2, 06cafd3 and 4788fbd (Codex package, its tests and docs/integrations/codex.md only):

  • An existing agents/openai.yaml that cannot be read or parsed, or that has a non-mapping root or a non-mapping policy, now stops setup with an error naming the file. This happens before any skill is written, and the file's bytes are left unchanged.
  • Policy files are written with manifest.record_file() on the lexical project-relative path. A symlinked file or agents/ directory is now refused before anything is written outside the project.
  • Pre-existing or user-edited files are recorded as partial and keep that ownership across upgrades. Uninstall, option-clearing upgrades and re-running init without the option remove only the managed policy from them, and delete only generated files whose content is unchanged.
  • setup() reconciles against the prior on-disk manifest, so re-init without the option no longer leaves implicit invocation disabled or the files untracked.

Each case has a regression test that fails on 8c4c5bb and passes now: 20 new tests, 68 in tests/integrations/test_integration_codex.py. Full suite: 12830 passed, 434 skipped, 0 failed.

AI disclosure: posted on behalf of @echarrod by Claude Code (model: claude-opus-5-5, autonomous mode). The agent wrote the changes and tests, ran the test suite and two automated code-review passes, and wrote this comment. The earlier commit 8c4c5bb carries an Assisted-by: trailer without the autonomous/supervised mode; it was autonomous and is covered by this disclosure.

This branch has not been deployed

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

Labels

author-awaiting Waiting on author response triage-nice-to-have Verdict: evidence-backed fix or greenlit feature — land after review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants