refactor(skills): remove ce-onboarding skill (#639)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -138,7 +138,7 @@ describe("CLI", () => {
|
||||
await fs.mkdir(path.join(codexRoot, "skills", "ce:review-beta"), { recursive: true })
|
||||
await fs.writeFile(path.join(codexRoot, "skills", "ce:review-beta", "SKILL.md"), "legacy raw colon beta skill")
|
||||
await fs.mkdir(path.join(codexRoot, "skills", "ce-update"), { recursive: true })
|
||||
await fs.writeFile(path.join(codexRoot, "skills", "ce-update", "SKILL.md"), "legacy claude-only skill")
|
||||
await fs.writeFile(path.join(codexRoot, "skills", "ce-update", "SKILL.md"), "legacy pre-namespaced flat skill")
|
||||
// A user-authored skill at a flat path whose name happens to collide with
|
||||
// a current CE skill name (ce-debug is a current CE skill that has never
|
||||
// been on the historical flat-path allow-list). The cleanup MUST NOT move
|
||||
@@ -202,9 +202,12 @@ describe("CLI", () => {
|
||||
}
|
||||
|
||||
expect(stdout).toContain("Cleaned codex")
|
||||
// 6 historical artifacts get backed up: ce:plan, ce:review-beta, ce-update,
|
||||
// report-bug.md, the .agents/skills/ce-plan symlink-equivalent, and the
|
||||
// namespaced compound-engineering/repo-research-analyst directory.
|
||||
// 6 historical artifacts get backed up: ce:plan, ce:review-beta, ce-update
|
||||
// (pre-namespaced flat path; ce-update is a current skill but its managed
|
||||
// install is at ~/.codex/skills/compound-engineering/ce-update, so the
|
||||
// flat path is legacy), report-bug.md, the .agents/skills/ce-plan
|
||||
// symlink-equivalent, and the namespaced
|
||||
// compound-engineering/repo-research-analyst directory.
|
||||
// The user-authored ce-debug skill is preserved.
|
||||
expect(stdout).toContain("backed up 6 artifact")
|
||||
expect(await exists(path.join(codexRoot, "skills", "ce:plan"))).toBe(false)
|
||||
|
||||
@@ -227,13 +227,55 @@ describe("cleanupStaleSkillDirs", () => {
|
||||
"Optimize Claude Code permissions by finding safe Bash commands from session history and auto-applying them to settings.json. Can run from any coding agent but targets Claude Code specifically. Use when experiencing permission fatigue, too many permission prompts, wanting to optimize permissions, or needing to set up allowlists. Triggers on \"optimize permissions\", \"reduce permission prompts\", \"allowlist commands\", \"too many permission prompts\", \"permission fatigue\", \"permission setup\", or complaints about clicking approve too often.",
|
||||
),
|
||||
)
|
||||
await createDir(
|
||||
path.join(root, "ce-onboarding"),
|
||||
skillContent(
|
||||
"ce-onboarding",
|
||||
"Generate or regenerate ONBOARDING.md to help new contributors understand a codebase. Use when the user asks to 'create onboarding docs', 'generate ONBOARDING.md', 'document this project for new developers', 'write onboarding documentation', 'vonboard', 'vonboarding', 'prepare this repo for a new contributor', 'refresh the onboarding doc', or 'update ONBOARDING.md'. Also use when someone needs to onboard a new team member and wants a written artifact, or when a codebase lacks onboarding documentation and the user wants to generate one.",
|
||||
),
|
||||
)
|
||||
await createDir(
|
||||
path.join(root, "ce-andrew-kane-gem-writer"),
|
||||
skillContent(
|
||||
"ce-andrew-kane-gem-writer",
|
||||
"This skill should be used when writing Ruby gems following Andrew Kane's proven patterns and philosophy. It applies when creating new Ruby gems, refactoring existing gems, designing gem APIs, or when clean, minimal, production-ready Ruby library code is needed. Triggers on requests like \"create a gem\", \"write a Ruby library\", \"design a gem API\", or mentions of Andrew Kane's style.",
|
||||
),
|
||||
)
|
||||
await createDir(
|
||||
path.join(root, "ce-changelog"),
|
||||
skillContent("ce-changelog", "Create engaging changelogs for recent merges to main branch"),
|
||||
)
|
||||
await createDir(
|
||||
path.join(root, "ce-deploy-docs"),
|
||||
skillContent("ce-deploy-docs", "Validate and prepare documentation for GitHub Pages deployment"),
|
||||
)
|
||||
await createDir(
|
||||
path.join(root, "ce-dspy-ruby"),
|
||||
skillContent(
|
||||
"ce-dspy-ruby",
|
||||
"Build type-safe LLM applications with DSPy.rb — Ruby's programmatic prompt framework with signatures, modules, agents, and optimization. Use when implementing predictable AI features, creating LLM signatures and modules, configuring language model providers, building agent systems with tools, optimizing prompts, or testing LLM-powered functionality in Ruby applications.",
|
||||
),
|
||||
)
|
||||
await createDir(
|
||||
path.join(root, "ce-every-style-editor"),
|
||||
skillContent(
|
||||
"ce-every-style-editor",
|
||||
"This skill should be used when reviewing or editing copy to ensure adherence to Every's style guide. It provides a systematic line-by-line review process for grammar, punctuation, mechanics, and style guide compliance.",
|
||||
),
|
||||
)
|
||||
|
||||
const removed = await cleanupStaleSkillDirs(root)
|
||||
|
||||
expect(removed).toBe(3)
|
||||
expect(removed).toBe(9)
|
||||
expect(await exists(path.join(root, "feature-video"))).toBe(false)
|
||||
expect(await exists(path.join(root, "reproduce-bug"))).toBe(false)
|
||||
expect(await exists(path.join(root, "claude-permissions-optimizer"))).toBe(false)
|
||||
expect(await exists(path.join(root, "ce-onboarding"))).toBe(false)
|
||||
expect(await exists(path.join(root, "ce-andrew-kane-gem-writer"))).toBe(false)
|
||||
expect(await exists(path.join(root, "ce-changelog"))).toBe(false)
|
||||
expect(await exists(path.join(root, "ce-deploy-docs"))).toBe(false)
|
||||
expect(await exists(path.join(root, "ce-dspy-ruby"))).toBe(false)
|
||||
expect(await exists(path.join(root, "ce-every-style-editor"))).toBe(false)
|
||||
})
|
||||
|
||||
test("preserves same-named user skills for legacy-only entries when content differs", async () => {
|
||||
|
||||
32
tests/legacy-registry-invariants.test.ts
Normal file
32
tests/legacy-registry-invariants.test.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import { STALE_SKILL_DIRS } from "../src/utils/legacy-cleanup"
|
||||
|
||||
// If a previously-retired skill is re-added to the plugin, its entry must be
|
||||
// removed from STALE_SKILL_DIRS in the same PR. Leaving the entry in place
|
||||
// causes `cleanupStaleSkillDirs()` to fingerprint-match the just-installed
|
||||
// skill (the live plugin description becomes the fingerprint) and delete it
|
||||
// on every `bun install --to <target>` before the writer re-creates it.
|
||||
//
|
||||
// The sibling registry `EXTRA_LEGACY_ARTIFACTS_BY_PLUGIN["compound-engineering"].skills`
|
||||
// is NOT covered by this invariant: it can legitimately contain names of
|
||||
// current skills whose FLAT install path is stale (e.g. `ce-update`, which
|
||||
// now installs at `~/.codex/skills/compound-engineering/ce-update` but had a
|
||||
// pre-namespaced flat install at `~/.codex/skills/ce-update`). Sweeping the
|
||||
// flat path is correct even while the skill is current.
|
||||
|
||||
const PLUGIN_ROOT = path.join(import.meta.dir, "..", "plugins", "compound-engineering")
|
||||
|
||||
async function listCurrentSkillDirs(): Promise<Set<string>> {
|
||||
const entries = await fs.readdir(path.join(PLUGIN_ROOT, "skills"), { withFileTypes: true })
|
||||
return new Set(entries.filter((e) => e.isDirectory()).map((e) => e.name))
|
||||
}
|
||||
|
||||
describe("legacy registry invariants", () => {
|
||||
test("STALE_SKILL_DIRS contains no name matching a current plugin skill", async () => {
|
||||
const current = await listCurrentSkillDirs()
|
||||
const collisions = STALE_SKILL_DIRS.filter((name) => current.has(name))
|
||||
expect(collisions).toEqual([])
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user