mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-15 15:46:30 +03:00
Constrain audit/critique to only suggest real commands via {{available_commands}}
Adds a dynamic {{available_commands}} placeholder that the build system
replaces with the actual list of user-invokable skill names. Audit and
critique now explicitly instruct the LLM to only suggest from this list,
preventing hallucinated commands like /redesign.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
aadaee5c37
commit
870d65b1e3
@@ -21,6 +21,7 @@ export function transformAgents(skills, distDir, patterns = null, options = {})
|
||||
ensureDir(skillsDir);
|
||||
|
||||
const allSkillNames = skills.map(s => s.name);
|
||||
const commandNames = skills.filter(s => s.userInvokable).map(s => `${prefix}${s.name}`);
|
||||
let refCount = 0;
|
||||
for (const skill of skills) {
|
||||
const skillName = `${prefix}${skill.name}`;
|
||||
@@ -42,7 +43,7 @@ export function transformAgents(skills, distDir, patterns = null, options = {})
|
||||
}
|
||||
|
||||
const frontmatter = generateYamlFrontmatter(frontmatterObj);
|
||||
let skillBody = replacePlaceholders(skill.body, 'agents');
|
||||
let skillBody = replacePlaceholders(skill.body, 'agents', commandNames);
|
||||
if (prefix) skillBody = prefixSkillReferences(skillBody, prefix, allSkillNames);
|
||||
const content = `${frontmatter}\n\n${skillBody}`;
|
||||
const outputPath = path.join(skillDir, 'SKILL.md');
|
||||
|
||||
@@ -23,6 +23,7 @@ export function transformClaudeCode(skills, distDir, patterns = null, options =
|
||||
ensureDir(skillsDir);
|
||||
|
||||
const allSkillNames = skills.map(s => s.name);
|
||||
const commandNames = skills.filter(s => s.userInvokable).map(s => `${prefix}${s.name}`);
|
||||
let refCount = 0;
|
||||
for (const skill of skills) {
|
||||
const skillName = `${prefix}${skill.name}`;
|
||||
@@ -41,7 +42,7 @@ export function transformClaudeCode(skills, distDir, patterns = null, options =
|
||||
if (skill.allowedTools) frontmatterObj['allowed-tools'] = skill.allowedTools;
|
||||
|
||||
const frontmatter = generateYamlFrontmatter(frontmatterObj);
|
||||
let skillBody = replacePlaceholders(skill.body, 'claude-code');
|
||||
let skillBody = replacePlaceholders(skill.body, 'claude-code', commandNames);
|
||||
if (prefix) skillBody = prefixSkillReferences(skillBody, prefix, allSkillNames);
|
||||
const content = `${frontmatter}\n\n${skillBody}`;
|
||||
const outputPath = path.join(skillDir, 'SKILL.md');
|
||||
|
||||
@@ -24,6 +24,7 @@ export function transformCodex(skills, distDir, patterns = null, options = {}) {
|
||||
ensureDir(skillsDir);
|
||||
|
||||
const allSkillNames = skills.map(s => s.name);
|
||||
const commandNames = skills.filter(s => s.userInvokable).map(s => `${prefix}${s.name}`);
|
||||
let refCount = 0;
|
||||
for (const skill of skills) {
|
||||
const skillName = `${prefix}${skill.name}`;
|
||||
@@ -45,7 +46,7 @@ export function transformCodex(skills, distDir, patterns = null, options = {}) {
|
||||
|
||||
const frontmatter = generateYamlFrontmatter(frontmatterObj);
|
||||
|
||||
let skillBody = replacePlaceholders(skill.body, 'codex');
|
||||
let skillBody = replacePlaceholders(skill.body, 'codex', commandNames);
|
||||
if (prefix) skillBody = prefixSkillReferences(skillBody, prefix, allSkillNames);
|
||||
// For user-invokable skills, transform remaining {{argname}} to $ARGNAME
|
||||
if (skill.userInvokable) {
|
||||
|
||||
@@ -23,6 +23,7 @@ export function transformCursor(skills, distDir, patterns = null, options = {})
|
||||
ensureDir(skillsDir);
|
||||
|
||||
const allSkillNames = skills.map(s => s.name);
|
||||
const commandNames = skills.filter(s => s.userInvokable).map(s => `${prefix}${s.name}`);
|
||||
let refCount = 0;
|
||||
for (const skill of skills) {
|
||||
const skillName = `${prefix}${skill.name}`;
|
||||
@@ -35,7 +36,7 @@ export function transformCursor(skills, distDir, patterns = null, options = {})
|
||||
if (skill.license) frontmatterObj.license = skill.license;
|
||||
|
||||
const frontmatter = generateYamlFrontmatter(frontmatterObj);
|
||||
let skillBody = replacePlaceholders(skill.body, 'cursor');
|
||||
let skillBody = replacePlaceholders(skill.body, 'cursor', commandNames);
|
||||
if (prefix) skillBody = prefixSkillReferences(skillBody, prefix, allSkillNames);
|
||||
const content = `${frontmatter}\n\n${skillBody}`;
|
||||
const outputPath = path.join(skillDir, 'SKILL.md');
|
||||
|
||||
@@ -24,6 +24,7 @@ export function transformGemini(skills, distDir, patterns = null, options = {})
|
||||
ensureDir(skillsDir);
|
||||
|
||||
const allSkillNames = skills.map(s => s.name);
|
||||
const commandNames = skills.filter(s => s.userInvokable).map(s => `${prefix}${s.name}`);
|
||||
let refCount = 0;
|
||||
for (const skill of skills) {
|
||||
const skillName = `${prefix}${skill.name}`;
|
||||
@@ -34,7 +35,7 @@ export function transformGemini(skills, distDir, patterns = null, options = {})
|
||||
description: skill.description,
|
||||
});
|
||||
|
||||
let skillBody = replacePlaceholders(skill.body, 'gemini');
|
||||
let skillBody = replacePlaceholders(skill.body, 'gemini', commandNames);
|
||||
if (prefix) skillBody = prefixSkillReferences(skillBody, prefix, allSkillNames);
|
||||
// For user-invokable skills, replace remaining {{arg}} placeholders with {{args}}
|
||||
if (skill.userInvokable) {
|
||||
|
||||
@@ -326,13 +326,17 @@ function escapeRegex(str) {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
export function replacePlaceholders(content, provider) {
|
||||
export function replacePlaceholders(content, provider, commandNames = []) {
|
||||
const placeholders = PROVIDER_PLACEHOLDERS[provider] || PROVIDER_PLACEHOLDERS['cursor'];
|
||||
const commandList = commandNames.length > 0
|
||||
? commandNames.map(n => `/${n}`).join(', ')
|
||||
: '';
|
||||
|
||||
return content
|
||||
.replace(/\{\{model\}\}/g, placeholders.model)
|
||||
.replace(/\{\{config_file\}\}/g, placeholders.config_file)
|
||||
.replace(/\{\{ask_instruction\}\}/g, placeholders.ask_instruction);
|
||||
.replace(/\{\{ask_instruction\}\}/g, placeholders.ask_instruction)
|
||||
.replace(/\{\{available_commands\}\}/g, commandList);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,7 +71,7 @@ For each issue, document:
|
||||
- **Impact**: How it affects users
|
||||
- **WCAG/Standard**: Which standard it violates (if applicable)
|
||||
- **Recommendation**: How to fix it
|
||||
- **Suggested command**: Which command to use (e.g., `/normalize`, `/optimize`, `/harden`)
|
||||
- **Suggested command**: Which command to use (ONLY from: {{available_commands}})
|
||||
|
||||
#### Critical Issues
|
||||
[Issues that block core functionality or violate WCAG A]
|
||||
@@ -108,10 +108,12 @@ Create actionable plan:
|
||||
|
||||
### Suggested Commands for Fixes
|
||||
|
||||
Map issues to appropriate commands:
|
||||
- "Use `/normalize` to align components with design system (addresses 23 theming issues)"
|
||||
- "Use `/optimize` to improve performance (addresses 12 performance issues)"
|
||||
- "Use `/harden` to improve i18n and text handling (addresses 8 edge cases)"
|
||||
Map issues to the available commands. **Only suggest commands from this list**: {{available_commands}}. Never invent commands that aren't listed.
|
||||
|
||||
Examples:
|
||||
- "Use `/normalize` to align with design system (addresses N theming issues)"
|
||||
- "Use `/optimize` to improve performance (addresses N performance issues)"
|
||||
- "Use `/harden` to improve resilience (addresses N edge cases)"
|
||||
|
||||
**IMPORTANT**: Be thorough but actionable. Too many low-priority issues creates noise. Focus on what actually matters.
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ For each issue:
|
||||
- **What**: Name the problem clearly
|
||||
- **Why it matters**: How this hurts users or undermines goals
|
||||
- **Fix**: What to do about it (be concrete)
|
||||
- **Command**: Which command to use (`/polish`, `/distill`, `/bolder`, `/quieter`, etc.)
|
||||
- **Command**: Which command to use (ONLY from: {{available_commands}})
|
||||
|
||||
### Minor Observations
|
||||
Quick notes on smaller issues worth addressing.
|
||||
|
||||
Reference in New Issue
Block a user