From e3d066efbb6cdb42793478bfc9fbd8ceb75079d5 Mon Sep 17 00:00:00 2001 From: yihui Date: Sat, 11 Jul 2026 14:31:38 +0800 Subject: [PATCH] chore: bump version and changelog (v1.32.1.0) Co-Authored-By: Claude Opus 4.7 --- CHANGELOG.md | 17 +++++++++++++++++ VERSION | 2 +- setup | 35 +++++++++++++++++++++++++++++++++++ test/gen-skill-docs.test.ts | 19 +++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd3d7330a9..b2d0b51aec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [1.32.1.0] - 2026-07-11 + +## **Cleanup stale flat Codex skill directories on install.** + +The `setup` script now detects and removes stale flat Claude-format skill directories (from pre-prefixed older Codex installs) that can shadow the generated `gstack-*` Codex skills and still point at `~/.claude/skills/gstack` runtime paths. New test coverage added for the cleanup logic. + +### The numbers that matter + +Diff against `main` at v1.32.0.0. + +| Metric | v1.32.0.0 | v1.32.1.0 | Δ | +|---|---|---|---| +| Files changed | — | 2 | — | +| Tests added | — | 1 | — | + +--- + ## [1.32.0.0] - 2026-05-10 ## **Seven contributor PRs land. Three are security or hardening.** diff --git a/VERSION b/VERSION index de3ddb989b..31c8797a7e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.32.0.0 +1.32.1.0 diff --git a/setup b/setup index 4c1763f9fd..cb6dc39f70 100755 --- a/setup +++ b/setup @@ -530,6 +530,39 @@ link_codex_skill_dirs() { fi } +# ─── Helper: remove stale flat Codex skills from pre-prefixed installs ─────── +# Older Codex setup versions installed Claude-format skills as flat directories +# like ~/.codex/skills/ship. Those stale entries can shadow the generated +# gstack-ship skill and still point at ~/.claude/skills/gstack runtime paths. +cleanup_stale_codex_skill_dirs() { + local gstack_dir="$1" + local skills_dir="$2" + local removed=() + + for skill_dir in "$gstack_dir"/*/; do + if [ -f "$skill_dir/SKILL.md" ]; then + skill_name="$(basename "$skill_dir")" + [ "$skill_name" = "node_modules" ] && continue + case "$skill_name" in gstack-*) continue ;; esac + + stale_target="$skills_dir/$skill_name" + stale_skill="$stale_target/SKILL.md" + [ -d "$stale_target" ] || continue + [ -f "$stale_skill" ] || continue + [ -L "$stale_skill" ] && continue + + if grep -q 'AUTO-GENERATED from SKILL.md.tmpl' "$stale_skill" 2>/dev/null \ + && grep -q '~/.claude/skills/gstack' "$stale_skill" 2>/dev/null; then + rm -rf "$stale_target" + removed+=("$skill_name") + fi + fi + done + if [ ${#removed[@]} -gt 0 ]; then + echo " cleaned up stale codex entries: ${removed[*]}" + fi +} + # ─── Helper: create .agents/skills/gstack/ sidecar symlinks ────────── # Codex/Gemini/Cursor read skills from .agents/skills/. We link runtime # assets (bin/, browse/dist/, review/, qa/, etc.) so skill templates can @@ -851,6 +884,8 @@ if [ "$INSTALL_CODEX" -eq 1 ]; then if [ "$CODEX_REPO_LOCAL" -eq 0 ]; then create_codex_runtime_root "$SOURCE_GSTACK_DIR" "$CODEX_GSTACK" fi + # Remove stale flat Claude-format gstack skills before linking gstack-* Codex skills. + cleanup_stale_codex_skill_dirs "$SOURCE_GSTACK_DIR" "$CODEX_SKILLS" # Install generated Codex-format skills (not Claude source dirs) link_codex_skill_dirs "$SOURCE_GSTACK_DIR" "$CODEX_SKILLS" diff --git a/test/gen-skill-docs.test.ts b/test/gen-skill-docs.test.ts index b30a324649..ae166243d3 100644 --- a/test/gen-skill-docs.test.ts +++ b/test/gen-skill-docs.test.ts @@ -2290,6 +2290,25 @@ describe('setup script validation', () => { expect(fnBody).toContain('[ "$skill_name" = "gstack" ] && continue'); }); + test('Codex install cleans stale flat gstack-generated skill directories', () => { + expect(setupContent).toContain('cleanup_stale_codex_skill_dirs'); + const fnStart = setupContent.indexOf('cleanup_stale_codex_skill_dirs()'); + const fnEnd = setupContent.indexOf('}', setupContent.indexOf('removed[@]}', fnStart)); + const fnBody = setupContent.slice(fnStart, fnEnd); + expect(fnBody).toContain('~/.claude/skills/gstack'); + expect(fnBody).toContain('AUTO-GENERATED from SKILL.md.tmpl'); + expect(fnBody).toContain('rm -rf "$stale_target"'); + + const codexSection = setupContent.slice( + setupContent.indexOf('# 5. Install for Codex'), + setupContent.indexOf('# 6. Create') + ); + expect(codexSection).toContain('cleanup_stale_codex_skill_dirs "$SOURCE_GSTACK_DIR" "$CODEX_SKILLS"'); + expect(codexSection.indexOf('cleanup_stale_codex_skill_dirs')).toBeLessThan( + codexSection.indexOf('link_codex_skill_dirs') + ); + }); + // T2: Dynamic $GSTACK_ROOT paths in generated Codex preambles test('generated Codex preambles use dynamic GSTACK_ROOT paths', () => { const codexSkillDir = path.join(ROOT, '.agents', 'skills', 'gstack-ship');