mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-21 02:26:31 +03:00
Consolidate 18 skills into 1 /impeccable skill with 20 commands
Biggest change in a while. Users previously had 18 standalone skill
entries cluttering their /menu; now they have one entry (/impeccable)
that routes to 20 specialized commands via argument dispatch. The pin
mechanism (/impeccable pin audit) restores standalone shortcuts on
demand for commands users hit all the time.
## Architecture
- Single /impeccable skill with command router section in SKILL.md
- 20 commands served via reference files under source/skills/impeccable/reference/
- /impeccable pin <command> creates a lightweight redirect shim so users
who prefer /audit, /polish, etc. can still have them
- Context gathering (teach) auto-runs on first use
- command-metadata.json is the single source of truth for command
descriptions, argument hints, and relationships
## Site rewrite
- Docs URL: /skills renamed to /docs (with /skills permanent redirects)
- Homepage hero frames Impeccable as "one skill with 20 commands"
- "Get Started" split into 50/50 install + how-to-use with editorial
numbered steps, /impeccable shown as the home command with three modes
- New /docs overview: home command hero card + dense category rows
matching the old cheatsheet density, with leads-to/pairs-with/
combines-with relationship metadata served from a shared source
- Cheatsheet merged into /docs, /cheatsheet redirects
- Magazine spread and mobile cards show /impeccable as a stacked
namespace label above the command name at full display size
- Periodic table updated with craft/teach/extract as first-class cells
- Skill detail pages generate from reference files, with an editorial
wrapper per command for tagline + body
- Tutorials and anti-patterns pages updated to use /impeccable <cmd>
## Build system
- Dead code removed (scripts/lib/transformers/shared.js)
- Build log wording fixed ("1 skill" not "1 skills (1 user-invocable)")
- generateApiData fallback branch removed (throws loudly if metadata
missing instead of silently degrading)
- Commands API includes editorial tagline alongside the long description;
UI surfaces prefer tagline for human display, description for auto-
trigger keyword matching
## Gitignore
- Added .claude/scheduled_tasks.lock, .claude/settings.local.json to
ignore list (local Claude Code state that should not be tracked).
- Harness skill directories (.claude/skills/, .agents/skills/, etc.)
remain tracked by design: npx skills reads them from this repo at
install time and they enable clean submodule use.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
f957fcad20
commit
b0f44f83c6
@@ -77,7 +77,7 @@ describe('cleanup-deprecated', () => {
|
||||
assert.ok(names.includes('i-arrange'));
|
||||
assert.ok(names.includes('frontend-design'));
|
||||
assert.ok(names.includes('i-frontend-design'));
|
||||
assert.equal(names.length, 12); // 6 deprecated * 2
|
||||
assert.equal(names.length, 46); // 23 deprecated * 2
|
||||
});
|
||||
});
|
||||
|
||||
@@ -128,11 +128,11 @@ describe('cleanup-deprecated', () => {
|
||||
});
|
||||
|
||||
it('leaves non-deprecated skills alone', () => {
|
||||
writeSkill(tmp, '.claude', 'polish', 'Invoke /impeccable first.');
|
||||
writeSkill(tmp, '.claude', 'my-custom-skill', 'Invoke /impeccable first.');
|
||||
writeSkill(tmp, '.claude', 'arrange', 'Invoke /impeccable first.');
|
||||
const deleted = removeDeprecatedSkills(tmp);
|
||||
assert.equal(deleted.length, 1); // only arrange
|
||||
assert.equal(existsSync(join(tmp, '.claude', 'skills', 'polish')), true);
|
||||
assert.equal(existsSync(join(tmp, '.claude', 'skills', 'my-custom-skill')), true);
|
||||
});
|
||||
|
||||
it('handles symlinks to deprecated skills', () => {
|
||||
@@ -152,7 +152,7 @@ describe('cleanup-deprecated', () => {
|
||||
version: 1,
|
||||
skills: {
|
||||
arrange: { source: 'pbakaus/impeccable', sourceType: 'github', computedHash: 'abc' },
|
||||
polish: { source: 'pbakaus/impeccable', sourceType: 'github', computedHash: 'def' },
|
||||
impeccable: { source: 'pbakaus/impeccable', sourceType: 'github', computedHash: 'def' },
|
||||
'resolve-reviews': { source: 'pbakaus/agent-reviews', sourceType: 'github', computedHash: 'ghi' },
|
||||
},
|
||||
};
|
||||
@@ -161,7 +161,7 @@ describe('cleanup-deprecated', () => {
|
||||
assert.deepEqual(removed, ['arrange']);
|
||||
const updated = JSON.parse(readFileSync(join(tmp, 'skills-lock.json'), 'utf-8'));
|
||||
assert.equal(updated.skills.arrange, undefined);
|
||||
assert.ok(updated.skills.polish); // not deprecated
|
||||
assert.ok(updated.skills.impeccable); // not deprecated
|
||||
assert.ok(updated.skills['resolve-reviews']); // different source
|
||||
});
|
||||
|
||||
@@ -209,7 +209,7 @@ describe('cleanup-deprecated', () => {
|
||||
skills: {
|
||||
arrange: { source: 'pbakaus/impeccable', sourceType: 'github', computedHash: 'a' },
|
||||
extract: { source: 'pbakaus/impeccable', sourceType: 'github', computedHash: 'b' },
|
||||
polish: { source: 'pbakaus/impeccable', sourceType: 'github', computedHash: 'c' },
|
||||
impeccable: { source: 'pbakaus/impeccable', sourceType: 'github', computedHash: 'c' },
|
||||
},
|
||||
};
|
||||
writeFileSync(join(tmp, 'skills-lock.json'), JSON.stringify(lock), 'utf-8');
|
||||
@@ -221,13 +221,13 @@ describe('cleanup-deprecated', () => {
|
||||
assert.equal(existsSync(join(tmp, '.agents', 'skills', 'arrange')), false);
|
||||
|
||||
const updated = JSON.parse(readFileSync(join(tmp, 'skills-lock.json'), 'utf-8'));
|
||||
assert.ok(updated.skills.polish);
|
||||
assert.ok(updated.skills.impeccable); // not deprecated
|
||||
assert.equal(updated.skills.arrange, undefined);
|
||||
assert.equal(updated.skills.extract, undefined);
|
||||
});
|
||||
|
||||
it('is a no-op when nothing needs cleaning', () => {
|
||||
writeSkill(tmp, '.claude', 'polish', 'Invoke /impeccable.');
|
||||
writeSkill(tmp, '.claude', 'my-custom-skill', 'Invoke /impeccable.');
|
||||
const result = cleanup(tmp);
|
||||
assert.equal(result.deletedPaths.length, 0);
|
||||
assert.equal(result.removedLockEntries.length, 0);
|
||||
|
||||
Reference in New Issue
Block a user