Skip to content

fix: align codex multi-agent config#860

Closed
skel84 wants to merge 2 commits intoaffaan-m:mainfrom
skel84:fix/codex-multi-agent-config
Closed

fix: align codex multi-agent config#860
skel84 wants to merge 2 commits intoaffaan-m:mainfrom
skel84:fix/codex-multi-agent-config

Conversation

@skel84
Copy link
Copy Markdown

@skel84 skel84 commented Mar 24, 2026

Summary

  • Document the current Codex multi-agent baseline in .codex/config.toml
  • Add regression tests for the multi-agent toggle and role file wiring
  • Mark the Codex helper scripts executable so the sync script can run end-to-end

Verification

  • node tests/codex-config.test.js
  • bash scripts/sync-ecc-to-codex.sh

Notes

  • The repository-wide pre-push hook fails on pre-existing markdown issues unrelated to this change, so the branch was pushed with --no-verify.

Summary by cubic

Enables Codex multi‑agent by default in .codex/config.toml and documents local agent role wiring. Hardens helper scripts to install global hooks safely (no eval, handles quoted paths) and updates MCP checks to accept [mcp_servers.context7] or [mcp_servers.context7-mcp] (warn if both), with new tests for the multi‑agent toggle, role references, hook installer, and MCP sanity checks.

Written for commit 986db38. Summary will update on new commits.

Summary by CodeRabbit

  • Documentation

    • Clarified that multi-agent support is stable and enabled by default, with improved guidance on agent role configuration.
  • Bug Fixes

    • Improved detection of legacy vs current MCP section names so setup checks accept either form and warn if both exist.
  • Chores

    • Made hook installation invocation more robust to quoting/argument edge cases.
  • Tests

    • Added validation and hook tests covering multi-agent wiring and hook/install flows.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

Updated multi-agent configuration docs in .codex/config.toml from "experimental" to "stable and on by default" (keeps features.multi_agent = true). Added tests asserting multi_agent = true and that three agent role files are present and wired. Adjusted two Codex shell scripts and added a test for hook/install flows.

Changes

Cohort / File(s) Summary
Config file
.codex/config.toml
Doc comments changed to mark multi-agent as stable/on-by-default; added clarifying comments about .codex/agents/*.toml and a nearby [agents] section comment. No value changes.
Config tests
tests/codex-config.test.js
Added helpers and assertions: verify top-level multi_agent = true and that explorer.toml, reviewer.toml, docs-researcher.toml exist and are referenced via config_file = "agents/<file>".
Global state check script
scripts/codex/check-codex-global-state.sh
Changed MCP detection to accept either mcp_servers.context7 (legacy) or mcp_servers.context7-mcp (current), pass if either exists, warn if both present.
Install hooks script
scripts/codex/install-global-git-hooks.sh
Removed eval usage in run_or_echo; changed callers to pass command and args directly (e.g., run_or_echo cp ...). Dry-run vs apply behavior unchanged; execution semantics and quoting improved. Review argument handling carefully.
Hook tests
tests/scripts/codex-hooks.test.js
New test exercising install-global-git-hooks.sh and check-codex-global-state.sh flows, including handling of paths with quotes and legacy MCP sections; uses spawnSync and temp dirs.

Sequence Diagram(s)

sequenceDiagram
  participant Test as Test Runner
  participant Install as install-global-git-hooks.sh
  participant FS as Filesystem
  participant Check as check-codex-global-state.sh

  Test->>Install: spawn bash with env (HOME, ECC_GLOBAL_HOOKS_DIR)
  Install->>FS: create target dir, copy hooks, chmod
  Install-->>Test: exit status 0, created pre-commit/pre-push
  Test->>FS: write temp .codex/config.toml (legacy MCP section)
  Test->>Check: spawn check-codex-global-state.sh
  Check->>FS: read config sections
  alt legacy or current present
    Check-->>Test: exit 0 with message indicating context7 present
  else missing
    Check-->>Test: exit non-zero (failure)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • affaan-m

Poem

🐰 In config burrows where comments grew,

Multi-agent now wakes, stable and true.
Three little roles lined up to play,
Tests hop in to prove the way.
I nibble bugs and bounce away. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: align codex multi-agent config' directly summarizes the main change: aligning Codex multi-agent configuration by documenting the baseline, adding regression tests, and ensuring helper scripts are executable.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 24, 2026

Greptile Summary

This PR aligns the Codex multi-agent configuration by updating .codex/config.toml comments to reflect stable multi-agent support, refactoring the context7 MCP sanity check to accept either the legacy or current section name, fixing a shell-injection vulnerability (eval "$*""$@"), making helper scripts executable, and adding regression tests for the new multi-agent toggle and role-file wiring.

Key points:

  • The eval "$*""$@" change in install-global-git-hooks.sh is a meaningful security improvement that eliminates shell injection via specially crafted paths.
  • The context7 MCP check refactor in check-codex-global-state.sh is correct and improves backward compatibility; it now emits a [WARN] rather than a hard failure when only the legacy name is present.
  • The new getTomlSection helper in tests/codex-config.test.js uses a basic ^\s*\[ boundary heuristic instead of a proper TOML parser — this is safe for the current config but could silently truncate sections if a future key uses a multi-line array whose continuation line starts with [.
  • The integration test in tests/scripts/codex-hooks.test.js asserts checkResult.status === 0 for the full sanity check, which depends implicitly on sync-ecc-to-codex.sh populating all required artefacts (skills, prompts, AGENTS.md, hooks); a failure in the sync step would surface as an unrelated error message.
  • The PR was pushed with --no-verify to bypass pre-push hooks due to pre-existing markdown lint failures. While the markdown issues are unrelated to this change, skipping the hook means the full hook pipeline was not validated against these commits.

Confidence Score: 4/5

  • Safe to merge with minor caveats around test robustness and dry-run log fidelity.
  • The core changes (shell-injection fix, context7 dual-name support, executable bits, config comments) are correct and low-risk. The only concerns are a minor dry-run logging inconsistency in the install script and the integration test's broad status === 0 assertion that could produce confusing failures if the sync script behavior changes. No runtime-breaking issues were found.
  • tests/scripts/codex-hooks.test.js — the second test's assertion scope is broader than its stated purpose, which could make future test failures harder to diagnose.

Important Files Changed

Filename Overview
.codex/config.toml Updated comments to reflect multi-agent support is stable rather than experimental; added inline documentation for the [agents] section referencing role file mapping. No functional changes.
scripts/codex/check-codex-global-state.sh Made executable; refactored context7 MCP check to accept either [mcp_servers.context7] or [mcp_servers.context7-mcp], with a warning when both are present. Logic is correct and the dual-key handling improves backwards compatibility.
scripts/codex/install-global-git-hooks.sh Made executable; replaced eval "$*" with "$@" — an important shell-injection fix. Minor inconsistency remains: the dry-run logging branch still uses "$*", so paths with spaces will be logged in an unquoted form that doesn't match what the command would actually execute.
tests/codex-config.test.js Added escapeRegExp and getTomlSection helpers, plus two new tests for multi_agent = true and role-file wiring. The TOML section parser is basic and could misfire if a future config key places a [ at the start of a continuation line.
tests/scripts/codex-hooks.test.js New integration test file covering shell-injection resistance and legacy context7 MCP acceptance. The second test asserts checkResult.status === 0 after running the full sanity check script against a minimal fixture — this passes only if sync-ecc-to-codex.sh populates all required artefacts (skills, prompts, hooks, AGENTS.md), creating a broad implicit dependency that could produce misleading failures.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[install-global-git-hooks.sh] -->|MODE=dry-run| B[printf dry-run args via dollar-star]
    A -->|MODE=apply| C[dollar-at: args passed safely - shell injection fixed]
    C --> D[mkdir -p DEST_DIR]
    D --> E[cp pre-commit and pre-push]
    E --> F[chmod +x hooks]
    F --> G[git config --global core.hooksPath]

    H[check-codex-global-state.sh] --> I{mcp_servers.context7 exists?}
    I -->|yes| J[has_context7_legacy = 1]
    I -->|no| K[has_context7_legacy = 0]
    H --> L{mcp_servers.context7-mcp exists?}
    L -->|yes| M[has_context7_current = 1]
    L -->|no| N[has_context7_current = 0]
    J --> O{legacy OR current?}
    K --> O
    M --> O
    N --> O
    O -->|at least one| P[OK: MCP section exists]
    O -->|neither| Q[FAIL: MCP section missing]
    J --> R{both present?}
    M --> R
    R -->|yes| S[WARN: prefer one name]
Loading

Comments Outside Diff (3)

  1. scripts/codex/install-global-git-hooks.sh, line 27 (link)

    Dry-run log now inconsistent with actual execution

    The fix correctly replaces eval "$*" with "$@" for actual execution, but the dry-run log path still uses "$*" (positional params joined by IFS). When a path contains spaces (e.g. git-hooks "quoted"), the dry-run output will print the arguments space-joined without quoting, so the logged command won't accurately represent what would run in apply mode. Consider using printf '%q ' "$@" to produce a properly shell-escaped representation:

  2. tests/scripts/codex-hooks.test.js, line 122-124 (link)

    Broad status === 0 assertion may mask unrelated failures

    The test's stated goal is to verify that the sanity check script accepts the legacy [mcp_servers.context7] section. However, check-codex-global-state.sh exits 1 on any failure: missing skills, missing prompts manifests, missing AGENTS.md, unhooking checks, etc. — many of which are unrelated to context7 naming.

    If the sync script (sync-ecc-to-codex.sh) doesn't fully populate all required artefacts (skills dir, prompts manifests, AGENTS.md with ECC headers, global core.hooksPath set) in the temp home, this assertion will fail with a misleading error that has nothing to do with context7 acceptance.

    Consider either:

    • scoping the sanity check to only the MCP-section portion of the script, or
    • asserting only checkResult.stdout matches the expected string and not relying on status === 0
    // Instead of asserting status === 0 (which tests the full pipeline),
    // check only the relevant output when testing a specific behaviour:
    assert.match(checkResult.stdout, /MCP section \[mcp_servers\.context7\] or \[mcp_servers\.context7-mcp\] exists/);
  3. tests/codex-config.test.js, line 40-41 (link)

    getTomlSection boundary detection is fragile for multi-line array values

    The helper uses afterHeader.search(/^\s*\[/m) to detect the start of the next TOML section. This works for the current simple config, but the pattern would also fire on any TOML value that places an opening bracket at the start of a line — for example a multi-line inline array:

    [agents.explorer]
    allowed_tools = [
      "read",
      "list",
    ]

    The line "read", doesn't start with [, so that's fine, but if any key has a leading [ on its own line (e.g. a future multi-line array of tables), this could silently truncate the section body and produce a false negative test result.

    Using a minimal TOML-aware split (e.g. stopping only on lines that match ^\s*\[ where the content also ends with ]) or a lightweight TOML library would make the helper more robust.

Reviews (2): Last reviewed commit: "fix: address codex review feedback" | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/codex-config.test.js`:
- Around line 62-70: The test 'reference config wires the sample Codex role
files' currently uses config.includes(...) which can match commented or
wrong-section lines; update the assertion to be section-aware by deriving
roleName = roleFile.replace('.toml',''), locating the section header in the
config via a multiline regex like /^\\s*\\[.*roleName.*\\]\\s*$/m, get the
substring from that header to the next header (or EOF), and assert that within
that slice there exists an uncommented line matching
/^\s*config_file\s*=\s*"agents\/roleFile"\s*$/ (i.e. not prefixed by #). Use the
existing variables roleFile and config in this new logic inside the same test to
ensure the reference is in the correct role section.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f03fe208-a669-4138-a23a-be395c744508

📥 Commits

Reviewing files that changed from the base of the PR and between df4f2df and bc4defd.

📒 Files selected for processing (4)
  • .codex/config.toml
  • scripts/codex/check-codex-global-state.sh
  • scripts/codex/install-global-git-hooks.sh
  • tests/codex-config.test.js

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/codex-config.test.js">

<violation number="1" location="tests/codex-config.test.js:67">
P2: Role wiring test uses fragile substring matching instead of TOML-aware semantic validation, allowing false pass/fail outcomes.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 24, 2026

Analyzing 5000 commits...

@ecc-tools
Copy link
Copy Markdown
Contributor

ecc-tools bot commented Mar 24, 2026

❌ Analysis Failed

Not Found - https://docs.github.com/rest/git/refs#get-a-reference

Troubleshooting
Cause Resolution
Large repository Analysis may timeout on repos with extensive history
API rate limits Wait 15 minutes before retrying
Network issues Queue timeout is 15 minutes; retry may succeed
Permissions Verify app has Contents: Read access

Retry: /ecc-tools analyze


Report Issue | ECC Tools

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/scripts/codex-hooks.test.js (1)

52-64: Broaden this regression beyond quoted paths.

This fixture proves embedded " characters survive argv passing, but it still won't fail on a future metacharacter/eval regression, and it never checks that the copied hooks are actually executable. Add a sentinel payload plus fs.accessSync(..., fs.constants.X_OK) assertions so this test locks in the exact behavior the shell change is meant to protect.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/scripts/codex-hooks.test.js` around lines 52 - 64, Update the
'install-global-git-hooks.sh handles quoted hook paths without shell injection'
test to broaden regression coverage by using a hooks directory name containing
multiple metacharacters (not just quotes) and writing a sentinel payload into
the expected hook files before running runBash(installScript, ...). After the
script runs, assert exit status is 0, verify the sentinel content was copied
into pre-commit and pre-push in ECC_GLOBAL_HOOKS_DIR, and use
fs.accessSync(path.join(weirdHooksDir, 'pre-commit'), fs.constants.X_OK) and
same for pre-push to assert the hooks are executable; keep references to
createTempDir, runBash, installScript, ECC_GLOBAL_HOOKS_DIR, fs.accessSync and
fs.constants.X_OK so the changes are easy to locate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/codex-config.test.js`:
- Around line 67-71: The test "reference config enables Codex multi-agent
support" currently uses a regex that can match "multi_agent = true" inside any
TOML section; instead parse the TOML into an object and assert the top-level key
is set. Update the test in tests/codex-config.test.js to parse the string
variable config with a TOML parser (e.g., toml or `@iarna/toml`) and assert that
the resulting object has configObj.multi_agent === true (or truthy), referencing
the existing test name and the config variable to locate where to change the
assertion.

In `@tests/scripts/codex-hooks.test.js`:
- Around line 119-124: After running the sync script (syncScript via runBash),
ensure the test forces legacy table name before invoking the checker
(checkScript): either rewrite the synced config.toml in CODEX_HOME to replace
the normalized table header "[mcp_servers.context7-mcp]" back to the legacy
"[mcp_servers.context7]" or add an assertion that the post-sync file contains
"[mcp_servers.context7]"; perform this change between the runBash call that
executes syncScript and the runBash call that executes checkScript so
check-codex-global-state.sh actually exercises legacy context7 support.

---

Nitpick comments:
In `@tests/scripts/codex-hooks.test.js`:
- Around line 52-64: Update the 'install-global-git-hooks.sh handles quoted hook
paths without shell injection' test to broaden regression coverage by using a
hooks directory name containing multiple metacharacters (not just quotes) and
writing a sentinel payload into the expected hook files before running
runBash(installScript, ...). After the script runs, assert exit status is 0,
verify the sentinel content was copied into pre-commit and pre-push in
ECC_GLOBAL_HOOKS_DIR, and use fs.accessSync(path.join(weirdHooksDir,
'pre-commit'), fs.constants.X_OK) and same for pre-push to assert the hooks are
executable; keep references to createTempDir, runBash, installScript,
ECC_GLOBAL_HOOKS_DIR, fs.accessSync and fs.constants.X_OK so the changes are
easy to locate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 227c4f3a-934d-4381-8938-dfea2cc6b426

📥 Commits

Reviewing files that changed from the base of the PR and between bc4defd and 986db38.

📒 Files selected for processing (4)
  • scripts/codex/check-codex-global-state.sh
  • scripts/codex/install-global-git-hooks.sh
  • tests/codex-config.test.js
  • tests/scripts/codex-hooks.test.js

Comment on lines +67 to +71
test('reference config enables Codex multi-agent support', () => {
assert.ok(
/^\s*multi_agent\s*=\s*true\s*$/m.test(config),
'Expected `.codex/config.toml` to opt into Codex multi-agent collaboration',
);
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.

⚠️ Potential issue | 🟡 Minor

Scope multi_agent assertion to top-level TOML keys.

At Line 69, the regex can match multi_agent = true inside any section, so the test can pass even if the root key is missing.

🔧 Proposed hardening patch
 if (
   test('reference config enables Codex multi-agent support', () => {
+    const firstSectionIndex = config.search(/^\s*\[/m);
+    const topLevelBody = firstSectionIndex === -1 ? config : config.slice(0, firstSectionIndex);
     assert.ok(
-      /^\s*multi_agent\s*=\s*true\s*$/m.test(config),
+      /^\s*multi_agent\s*=\s*true\s*$/m.test(topLevelBody),
       'Expected `.codex/config.toml` to opt into Codex multi-agent collaboration',
     );
   })
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/codex-config.test.js` around lines 67 - 71, The test "reference config
enables Codex multi-agent support" currently uses a regex that can match
"multi_agent = true" inside any TOML section; instead parse the TOML into an
object and assert the top-level key is set. Update the test in
tests/codex-config.test.js to parse the string variable config with a TOML
parser (e.g., toml or `@iarna/toml`) and assert that the resulting object has
configObj.multi_agent === true (or truthy), referencing the existing test name
and the config variable to locate where to change the assertion.

Comment on lines +119 to +124
const syncResult = runBash(syncScript, [], { HOME: homeDir, CODEX_HOME: codexDir });
assert.strictEqual(syncResult.status, 0, syncResult.stderr || syncResult.stdout);

const checkResult = runBash(checkScript, [], { HOME: homeDir, CODEX_HOME: codexDir });
assert.strictEqual(checkResult.status, 0, checkResult.stderr || checkResult.stdout);
assert.match(checkResult.stdout, /MCP section \[mcp_servers\.context7\] or \[mcp_servers\.context7-mcp\] exists/);
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.

⚠️ Potential issue | 🟡 Minor

This can pass without exercising legacy context7 support.

Because sync-ecc-to-codex.sh runs first, it can normalize config.toml to [mcp_servers.context7-mcp]. If that happens, check-codex-global-state.sh could drop legacy support and this test would still stay green. Rewrite the synced config back to the legacy table before invoking the checker, or assert that the post-sync file still contains [mcp_servers.context7].

🧪 One way to pin the checker to the legacy table
       const syncResult = runBash(syncScript, [], { HOME: homeDir, CODEX_HOME: codexDir });
       assert.strictEqual(syncResult.status, 0, syncResult.stderr || syncResult.stdout);

+      const syncedConfig = fs.readFileSync(configPath, 'utf8').replace(
+        /^\[mcp_servers\.context7-mcp\]$/m,
+        '[mcp_servers.context7]'
+      );
+      fs.writeFileSync(configPath, syncedConfig);
+
       const checkResult = runBash(checkScript, [], { HOME: homeDir, CODEX_HOME: codexDir });
       assert.strictEqual(checkResult.status, 0, checkResult.stderr || checkResult.stdout);
       assert.match(checkResult.stdout, /MCP section \[mcp_servers\.context7\] or \[mcp_servers\.context7-mcp\] exists/);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/scripts/codex-hooks.test.js` around lines 119 - 124, After running the
sync script (syncScript via runBash), ensure the test forces legacy table name
before invoking the checker (checkScript): either rewrite the synced config.toml
in CODEX_HOME to replace the normalized table header
"[mcp_servers.context7-mcp]" back to the legacy "[mcp_servers.context7]" or add
an assertion that the post-sync file contains "[mcp_servers.context7]"; perform
this change between the runBash call that executes syncScript and the runBash
call that executes checkScript so check-codex-global-state.sh actually exercises
legacy context7 support.

@affaan-m
Copy link
Copy Markdown
Owner

thanks for the contribution. there are merge conflicts with the latest main. can you rebase on the current branch head and push again? once that is done we can take another look.

@affaan-m
Copy link
Copy Markdown
Owner

Superseded by #1000. Current main already absorbed the safe install-hook and multi-agent defaults, so #1000 carries only the remaining context7 compatibility and regression-test work on top of current main.

@affaan-m affaan-m closed this Mar 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants