diff --git a/.agents/skills/impeccable/scripts/cleanup-deprecated.mjs b/.agents/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.agents/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.agents/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.claude/skills/impeccable/scripts/cleanup-deprecated.mjs b/.claude/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.claude/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.claude/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.cursor/skills/impeccable/scripts/cleanup-deprecated.mjs b/.cursor/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.cursor/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.cursor/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.gemini/skills/impeccable/scripts/cleanup-deprecated.mjs b/.gemini/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.gemini/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.gemini/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.github/skills/impeccable/scripts/cleanup-deprecated.mjs b/.github/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.github/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.github/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.kiro/skills/impeccable/scripts/cleanup-deprecated.mjs b/.kiro/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.kiro/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.kiro/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.opencode/skills/impeccable/scripts/cleanup-deprecated.mjs b/.opencode/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.opencode/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.opencode/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.pi/skills/impeccable/scripts/cleanup-deprecated.mjs b/.pi/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.pi/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.pi/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.qoder/skills/impeccable/scripts/cleanup-deprecated.mjs b/.qoder/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.qoder/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.qoder/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.rovodev/skills/impeccable/scripts/cleanup-deprecated.mjs b/.rovodev/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.rovodev/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.rovodev/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.trae-cn/skills/impeccable/scripts/cleanup-deprecated.mjs b/.trae-cn/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.trae-cn/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.trae-cn/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/.trae/skills/impeccable/scripts/cleanup-deprecated.mjs b/.trae/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/.trae/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/.trae/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/bin/commands/skills.mjs b/bin/commands/skills.mjs index 1029605e..9289933e 100644 --- a/bin/commands/skills.mjs +++ b/bin/commands/skills.mjs @@ -19,8 +19,10 @@ import { tmpdir } from 'node:os'; const __dirname = dirname(fileURLToPath(import.meta.url)); const API_BASE = 'https://impeccable.style'; -// Provider folder names in project roots -const PROVIDER_DIRS = ['.claude', '.cursor', '.gemini', '.agents', '.github', '.kiro', '.opencode', '.pi', '.qoder', '.trae', '.trae-cn']; +// Provider folder names in project roots. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js +// (.codex is intentionally excluded -- Codex CLI consumes .agents/skills/). +const PROVIDER_DIRS = ['.claude', '.cursor', '.gemini', '.agents', '.github', '.kiro', '.opencode', '.pi', '.qoder', '.rovodev', '.trae', '.trae-cn']; function ask(question) { const rl = createInterface({ input: process.stdin, output: process.stdout }); diff --git a/plugin/skills/impeccable/scripts/cleanup-deprecated.mjs b/plugin/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/plugin/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/plugin/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/source/skills/impeccable/scripts/cleanup-deprecated.mjs b/source/skills/impeccable/scripts/cleanup-deprecated.mjs index 6aee4710..f079b8b6 100644 --- a/source/skills/impeccable/scripts/cleanup-deprecated.mjs +++ b/source/skills/impeccable/scripts/cleanup-deprecated.mjs @@ -52,9 +52,11 @@ const DEPRECATED_NAMES = [ ]; // All known harness directories that may contain a skills/ subfolder. +// Must stay in sync with configDir entries in scripts/lib/transformers/providers.js. const HARNESS_DIRS = [ '.claude', '.cursor', '.gemini', '.codex', '.agents', - '.trae', '.trae-cn', '.pi', '.opencode', '.kiro', '.rovodev', + '.github', '.trae', '.trae-cn', '.pi', '.opencode', + '.kiro', '.qoder', '.rovodev', ]; // Per-skill fingerprints for SKILL.md bodies that never mentioned diff --git a/tests/cleanup-deprecated.test.mjs b/tests/cleanup-deprecated.test.mjs index 9d4dfb77..6ffcaa48 100644 --- a/tests/cleanup-deprecated.test.mjs +++ b/tests/cleanup-deprecated.test.mjs @@ -167,6 +167,19 @@ describe('cleanup-deprecated', () => { assert.equal(deleted.length, 3); }); + it('cleans GitHub Copilot and Qoder harness installs', () => { + // Regression: HARNESS_DIRS used to omit .github and .qoder, so users + // who installed via those harnesses kept stale skill directories + // forever. providers.js declares both as build targets, so they need + // to round-trip through cleanup as well. + writeSkill(tmp, '.github', 'arrange', 'Invoke /impeccable first.'); + writeSkill(tmp, '.qoder', 'normalize', 'Run impeccable teach.'); + const deleted = removeDeprecatedSkills(tmp); + assert.equal(deleted.length, 2); + assert.equal(existsSync(join(tmp, '.github', 'skills', 'arrange')), false); + assert.equal(existsSync(join(tmp, '.qoder', 'skills', 'normalize')), false); + }); + it('leaves non-deprecated skills alone', () => { writeSkill(tmp, '.claude', 'my-custom-skill', 'Invoke /impeccable first.'); writeSkill(tmp, '.claude', 'arrange', 'Invoke /impeccable first.');