From 1266c152e2a412048ab5e0fc1d2118151484b21d Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Fri, 14 Aug 2026 19:31:39 -0700 Subject: [PATCH] fix(hosts): Codex-generated skills reference AGENTS.md, not CLAUDE.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex reads AGENTS.md, but its generated skills still told agents to read CLAUDE.md in 8 places — instructions Codex hosts cannot follow. The host config now maps the memory-file name per host; all three ship goldens refreshed from the regenerated output. Contributed by @exGeni (PR #1996). Co-Authored-By: Claude Fable 5 --- hosts/codex.ts | 1 + test/fixtures/golden/claude-ship-SKILL.md | 14 ++++++--- test/fixtures/golden/codex-ship-SKILL.md | 36 ++++++++++++---------- test/fixtures/golden/factory-ship-SKILL.md | 4 +++ test/host-config.test.ts | 4 +++ 5 files changed, 38 insertions(+), 21 deletions(-) diff --git a/hosts/codex.ts b/hosts/codex.ts index 7dc80ea87..0ea9ea61a 100644 --- a/hosts/codex.ts +++ b/hosts/codex.ts @@ -29,6 +29,7 @@ const codex: HostConfig = { { from: '.claude/skills/gstack', to: '.agents/skills/gstack' }, { from: '.claude/skills/review', to: '.agents/skills/gstack/review' }, { from: '.claude/skills', to: '.agents/skills' }, + { from: 'CLAUDE.md', to: 'AGENTS.md' }, ], suppressedResolvers: [ diff --git a/test/fixtures/golden/claude-ship-SKILL.md b/test/fixtures/golden/claude-ship-SKILL.md index d49a20238..abc16e7d0 100644 --- a/test/fixtures/golden/claude-ship-SKILL.md +++ b/test/fixtures/golden/claude-ship-SKILL.md @@ -84,13 +84,15 @@ if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" _QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false") echo "QUESTION_TUNING: $_QUESTION_TUNING" +_UPDATE_CHECK=$(~/.claude/skills/gstack/bin/gstack-config get update_check 2>/dev/null || echo "true") +echo "UPDATE_CHECK: $_UPDATE_CHECK" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"ship","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(_repo=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null | tr -cd 'a-zA-Z0-9._-'); echo "${_repo:-unknown}")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true fi for _PF in $(find ~/.gstack/analytics -maxdepth 1 -name '.pending-*' 2>/dev/null); do if [ -f "$_PF" ]; then - if [ "$_TEL" != "off" ] && [ -x "~/.claude/skills/gstack/bin/gstack-telemetry-log" ]; then + if [ "$_TEL" != "off" ] && [ -x "$HOME/.claude/skills/gstack/bin/gstack-telemetry-log" ]; then ~/.claude/skills/gstack/bin/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true fi rm -f "$_PF" 2>/dev/null || true @@ -156,6 +158,8 @@ If `PROACTIVE` is `"false"`, do not auto-invoke or proactively suggest skills. I If `SKILL_PREFIX` is `"true"`, suggest/invoke `/gstack-*` names. Disk paths stay `~/.claude/skills/gstack/[skill-name]/SKILL.md`. +If `UPDATE_CHECK` is `"false"`, skip the next two lines — the update-check binary emits nothing in that mode, so there is no `UPGRADE_AVAILABLE` / `JUST_UPGRADED` output to act on. + If output shows `UPGRADE_AVAILABLE `: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If output shows `JUST_UPGRADED `: print "Running gstack v{to} (just updated!)". If `SPAWNED_SESSION` is true, skip feature discovery. @@ -468,8 +472,8 @@ if [ -f "$HOME/.gstack-artifacts-remote.txt" ]; then else _BRAIN_REMOTE_FILE="$HOME/.gstack-brain-remote.txt" fi -_BRAIN_SYNC_BIN="~/.claude/skills/gstack/bin/gstack-brain-sync" -_BRAIN_CONFIG_BIN="~/.claude/skills/gstack/bin/gstack-config" +_BRAIN_SYNC_BIN="$HOME/.claude/skills/gstack/bin/gstack-brain-sync" +_BRAIN_CONFIG_BIN="$HOME/.claude/skills/gstack/bin/gstack-config" # /sync-gbrain context-load: teach the agent to use gbrain when it's available. # Per-worktree pin: post-spike redesign uses kubectl-style `.gbrain-source` in the @@ -578,8 +582,8 @@ If A/B and `~/.gstack/.git` is missing, ask whether to run `gstack-artifacts-ini At skill END before telemetry: ```bash -"~/.claude/skills/gstack/bin/gstack-brain-sync" --discover-new 2>/dev/null || true -"~/.claude/skills/gstack/bin/gstack-brain-sync" --once 2>/dev/null || true +"$HOME/.claude/skills/gstack/bin/gstack-brain-sync" --discover-new 2>/dev/null || true +"$HOME/.claude/skills/gstack/bin/gstack-brain-sync" --once 2>/dev/null || true ``` diff --git a/test/fixtures/golden/codex-ship-SKILL.md b/test/fixtures/golden/codex-ship-SKILL.md index 174b78598..700247096 100644 --- a/test/fixtures/golden/codex-ship-SKILL.md +++ b/test/fixtures/golden/codex-ship-SKILL.md @@ -70,6 +70,8 @@ if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" _QUESTION_TUNING=$($GSTACK_BIN/gstack-config get question_tuning 2>/dev/null || echo "false") echo "QUESTION_TUNING: $_QUESTION_TUNING" +_UPDATE_CHECK=$($GSTACK_BIN/gstack-config get update_check 2>/dev/null || echo "true") +echo "UPDATE_CHECK: $_UPDATE_CHECK" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"ship","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(_repo=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null | tr -cd 'a-zA-Z0-9._-'); echo "${_repo:-unknown}")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true @@ -96,7 +98,7 @@ else fi $GSTACK_BIN/gstack-timeline-log '{"skill":"ship","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then +if [ -f AGENTS.md ] && grep -q "## Skill routing" AGENTS.md 2>/dev/null; then _HAS_ROUTING="yes" fi _ROUTING_DECLINED=$($GSTACK_BIN/gstack-config get routing_declined 2>/dev/null || echo "false") @@ -142,6 +144,8 @@ If `PROACTIVE` is `"false"`, do not auto-invoke or proactively suggest skills. I If `SKILL_PREFIX` is `"true"`, suggest/invoke `/gstack-*` names. Disk paths stay `$GSTACK_ROOT/[skill-name]/SKILL.md`. +If `UPDATE_CHECK` is `"false"`, skip the next two lines — the update-check binary emits nothing in that mode, so there is no `UPGRADE_AVAILABLE` / `JUST_UPGRADED` output to act on. + If output shows `UPGRADE_AVAILABLE `: read `$GSTACK_ROOT/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If output shows `JUST_UPGRADED `: print "Running gstack v{to} (just updated!)". If `SPAWNED_SESSION` is true, skip feature discovery. @@ -245,17 +249,17 @@ Then run `touch ~/.gstack/.first-loop-tip-shown 2>/dev/null || true`. Skip this section if `ACTIVATED` and `FIRST_LOOP_SHOWN` are both `yes`. If `HAS_ROUTING` is `no` AND `ROUTING_DECLINED` is `false` AND `PROACTIVE_PROMPTED` is `yes`: -Check if a CLAUDE.md file exists in the project root. If it does not exist, create it. +Check if a AGENTS.md file exists in the project root. If it does not exist, create it. Use AskUserQuestion: -> gstack works best when your project's CLAUDE.md includes skill routing rules. +> gstack works best when your project's AGENTS.md includes skill routing rules. Options: -- A) Add routing rules to CLAUDE.md (recommended) +- A) Add routing rules to AGENTS.md (recommended) - B) No thanks, I'll invoke skills manually -If A: Append this section to the end of CLAUDE.md: +If A: Append this section to the end of AGENTS.md: ```markdown @@ -279,7 +283,7 @@ Key routing rules: - Author a backlog-ready spec/issue → invoke /spec ``` -Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"` +Then commit the change: `git add AGENTS.md && git commit -m "chore: add gstack skill routing rules to AGENTS.md"` If B: run `$GSTACK_BIN/gstack-config set routing_declined true` and say they can re-enable with `gstack-config set routing_declined false`. @@ -298,7 +302,7 @@ If A: 1. Run `git rm -r .agents/skills/gstack/` 2. Run `echo '.agents/skills/gstack/' >> .gitignore` 3. Run `$GSTACK_BIN/gstack-team-init required` (or `optional`) -4. Run `git add .claude/ .gitignore CLAUDE.md && git commit -m "chore: migrate gstack from vendored to team mode"` +4. Run `git add .claude/ .gitignore AGENTS.md && git commit -m "chore: migrate gstack from vendored to team mode"` 5. Tell the user: "Done. Each developer now runs: `cd $GSTACK_ROOT && ./setup --team`" If B: say "OK, you're on your own to keep the vendored copy up to date." @@ -475,7 +479,7 @@ if [ -f "$_GBRAIN_CONFIG" ] && command -v gbrain >/dev/null 2>&1; then if [ -n "$_GBRAIN_PIN_PATH" ]; then echo "GBrain configured. Prefer \`gbrain search\`/\`gbrain query\` over Grep for" echo "semantic questions; use \`gbrain code-def\`/\`code-refs\`/\`code-callers\` for" - echo "symbol-aware code lookup. See \"## GBrain Search Guidance\" in CLAUDE.md." + echo "symbol-aware code lookup. See \"## GBrain Search Guidance\" in AGENTS.md." echo "Run /sync-gbrain to refresh." else echo "GBrain configured but this worktree isn't pinned yet. Run \`/sync-gbrain --full\`" @@ -1117,9 +1121,9 @@ Write TESTING.md with: - Test layers: Unit tests (what, where, when), Integration tests, Smoke tests, E2E tests - Conventions: file naming, assertion style, setup/teardown patterns -### B7. Update CLAUDE.md +### B7. Update AGENTS.md -First check: If CLAUDE.md already has a `## Testing` section → skip. Don't duplicate. +First check: If AGENTS.md already has a `## Testing` section → skip. Don't duplicate. Append a `## Testing` section: - Run command and test directory @@ -1138,7 +1142,7 @@ Append a `## Testing` section: git status --porcelain ``` -Only commit if there are changes. Stage all bootstrap files (config, test directory, TESTING.md, CLAUDE.md, .github/workflows/test.yml if created): +Only commit if there are changes. Stage all bootstrap files (config, test directory, TESTING.md, AGENTS.md, .github/workflows/test.yml if created): `git commit -m "chore: bootstrap test framework ({framework name})"` --- @@ -1283,7 +1287,7 @@ Evals are mandatory when prompt-related files change. Skip this step entirely if git diff origin/ --name-only ``` -Match against these patterns (from CLAUDE.md): +Match against these patterns (from AGENTS.md): - `app/services/*_prompt_builder.rb` - `app/services/*_generation_service.rb`, `*_writer_service.rb`, `*_designer_service.rb` - `app/services/*_evaluator.rb`, `*_scorer.rb`, `*_classifier_service.rb`, `*_analyzer.rb` @@ -1365,8 +1369,8 @@ poller is reaped. Before analyzing coverage, detect the project's test framework: -1. **Read CLAUDE.md** — look for a `## Testing` section with test command and framework name. If found, use that as the authoritative source. -2. **If CLAUDE.md has no testing section, auto-detect:** +1. **Read AGENTS.md** — look for a `## Testing` section with test command and framework name. If found, use that as the authoritative source. +2. **If AGENTS.md has no testing section, auto-detect:** ```bash setopt +o nomatch 2>/dev/null || true # zsh compat @@ -1533,7 +1537,7 @@ Coverage line: `Test Coverage Audit: N new code paths. M covered (X%). K tests g **7. Coverage gate:** -Before proceeding, check CLAUDE.md for a `## Test Coverage` section with `Minimum:` and `Target:` fields. If found, use those percentages. Otherwise use defaults: Minimum = 60%, Target = 80%. +Before proceeding, check AGENTS.md for a `## Test Coverage` section with `Minimum:` and `Target:` fields. If found, use those percentages. Otherwise use defaults: Minimum = 60%, Target = 80%. Using the coverage percentage from the diagram in substep 4 (the `COVERAGE: X/Y (Z%)` line): @@ -2539,7 +2543,7 @@ git push -u origin > You are executing the /document-release workflow after a code push. Read the full skill file `${HOME}/.agents/skills/gstack/document-release/SKILL.md` and execute its complete workflow end-to-end, including CHANGELOG clobber protection, doc exclusions, risky-change gates, and named staging. Do NOT attempt to edit the PR body — no PR exists yet. Branch: ``, base: ``. > > After completing the workflow, output a single JSON object on the LAST LINE of your response (no other text after it): -> `{"files_updated":["README.md","CLAUDE.md",...],"commit_sha":"abc1234","pushed":true,"documentation_section":""}` +> `{"files_updated":["README.md","AGENTS.md",...],"commit_sha":"abc1234","pushed":true,"documentation_section":""}` > > If no documentation files needed updating, output: > `{"files_updated":[],"commit_sha":null,"pushed":false,"documentation_section":null}` diff --git a/test/fixtures/golden/factory-ship-SKILL.md b/test/fixtures/golden/factory-ship-SKILL.md index efd8ffb96..69c6013db 100644 --- a/test/fixtures/golden/factory-ship-SKILL.md +++ b/test/fixtures/golden/factory-ship-SKILL.md @@ -72,6 +72,8 @@ if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" _QUESTION_TUNING=$($GSTACK_BIN/gstack-config get question_tuning 2>/dev/null || echo "false") echo "QUESTION_TUNING: $_QUESTION_TUNING" +_UPDATE_CHECK=$($GSTACK_BIN/gstack-config get update_check 2>/dev/null || echo "true") +echo "UPDATE_CHECK: $_UPDATE_CHECK" mkdir -p ~/.gstack/analytics if [ "$_TEL" != "off" ]; then echo '{"skill":"ship","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(_repo=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null | tr -cd 'a-zA-Z0-9._-'); echo "${_repo:-unknown}")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true @@ -144,6 +146,8 @@ If `PROACTIVE` is `"false"`, do not auto-invoke or proactively suggest skills. I If `SKILL_PREFIX` is `"true"`, suggest/invoke `/gstack-*` names. Disk paths stay `$GSTACK_ROOT/[skill-name]/SKILL.md`. +If `UPDATE_CHECK` is `"false"`, skip the next two lines — the update-check binary emits nothing in that mode, so there is no `UPGRADE_AVAILABLE` / `JUST_UPGRADED` output to act on. + If output shows `UPGRADE_AVAILABLE `: read `$GSTACK_ROOT/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If output shows `JUST_UPGRADED `: print "Running gstack v{to} (just updated!)". If `SPAWNED_SESSION` is true, skip feature discovery. diff --git a/test/host-config.test.ts b/test/host-config.test.ts index 1c939d7be..dabaa83cb 100644 --- a/test/host-config.test.ts +++ b/test/host-config.test.ts @@ -481,6 +481,10 @@ describe('host config correctness', () => { expect(codex.generation.metadataFormat).toBe('openai.yaml'); }); + test('codex rewrites CLAUDE.md to AGENTS.md', () => { + expect(codex.pathRewrites).toContainEqual({ from: 'CLAUDE.md', to: 'AGENTS.md' }); + }); + test('codex has sidecar config', () => { expect(codex.sidecar).toBeDefined(); expect(codex.sidecar!.path).toBe('.agents/skills/gstack');