diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 6e79722..5057a1d 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -12,7 +12,7 @@ "name": "dev-workflows", "source": "./dev-workflows", "strict": true, - "version": "0.17.0", + "version": "0.17.1", "description": "Skills + Subagents for backend development - Use skills for coding guidance, or run recipe workflows for full orchestrated agentic coding with specialized agents", "author": { "name": "Shinsuke Kagawa", @@ -82,7 +82,7 @@ "name": "dev-workflows-frontend", "source": "./dev-workflows-frontend", "strict": true, - "version": "0.17.0", + "version": "0.17.1", "description": "Skills + Subagents for React/TypeScript - Use skills for coding guidance, or run recipe workflows for full orchestrated agentic coding with specialized agents", "author": { "name": "Shinsuke Kagawa", @@ -150,7 +150,7 @@ "name": "dev-skills", "source": "./dev-skills", "strict": true, - "version": "0.17.0", + "version": "0.17.1", "description": "Lightweight skills for users with existing workflows - coding best practices, testing principles, and design guidelines without recipe workflows or agents", "author": { "name": "Shinsuke Kagawa", diff --git a/dev-skills/.claude-plugin/plugin.json b/dev-skills/.claude-plugin/plugin.json index b9a6521..53f31c2 100644 --- a/dev-skills/.claude-plugin/plugin.json +++ b/dev-skills/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "dev-skills", "description": "Lightweight skills for users with existing workflows - coding best practices, testing principles, and design guidelines without recipe workflows or agents", - "version": "0.17.0", + "version": "0.17.1", "author": { "name": "Shinsuke Kagawa", "url": "https://github.com/shinpr" diff --git a/dev-workflows-frontend/.claude-plugin/plugin.json b/dev-workflows-frontend/.claude-plugin/plugin.json index 1d0c511..3ac9b98 100644 --- a/dev-workflows-frontend/.claude-plugin/plugin.json +++ b/dev-workflows-frontend/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "dev-workflows-frontend", "description": "Skills + Subagents for React/TypeScript - Use skills for coding guidance, or run recipe workflows for full orchestrated agentic coding with specialized agents", - "version": "0.17.0", + "version": "0.17.1", "author": { "name": "Shinsuke Kagawa", "url": "https://github.com/shinpr" diff --git a/dev-workflows-frontend/skills/task-analyzer/references/skills-index.yaml b/dev-workflows-frontend/skills/task-analyzer/references/skills-index.yaml index 0d08880..856c1e8 100644 --- a/dev-workflows-frontend/skills/task-analyzer/references/skills-index.yaml +++ b/dev-workflows-frontend/skills/task-analyzer/references/skills-index.yaml @@ -25,7 +25,7 @@ skills: - "Commenting Principles" - "Refactoring Approach" - "Testing Considerations" - - "Security Principles (Secure Defaults, Input and Output Boundaries, Access Control, Knowledge Cutoff Supplement)" + - "Security Principles" - "Documentation" - "Version Control Practices" - "Language-Specific Adaptations" @@ -122,8 +122,8 @@ skills: integration-e2e-testing: skill: "integration-e2e-testing" - tags: [testing, integration-testing, e2e-testing, test-design, behavior-first, roi, test-skeleton, ears-format] - typical-use: "Integration and E2E test design principles, ROI-based test selection, behavior-first approach, test skeleton specification" + tags: [testing, integration-testing, e2e-testing, fixture-e2e, service-integration-e2e, lane-selection, test-design, behavior-first, roi, test-skeleton, ears-format] + typical-use: "Integration and E2E test design principles, two-lane E2E split (fixture-e2e and service-integration-e2e) with lane-specific ROI thresholds, behavior-first approach, test skeleton specification" size: medium key-references: - "Test Pyramid - Mike Cohn" @@ -186,8 +186,8 @@ skills: test-implement: skill: "test-implement" - tags: [testing, frontend, react, react-testing-library, msw, playwright, e2e, coverage, tdd] - typical-use: "Test implementation patterns. references/frontend.md for RTL+Vitest+MSW, references/e2e.md for Playwright E2E" + tags: [testing, frontend, react, react-testing-library, msw, playwright, e2e, fixture-e2e, service-integration-e2e, coverage, tdd] + typical-use: "Test implementation patterns. references/frontend.md for RTL+Vitest+MSW, references/e2e.md for Playwright with both fixture-e2e (mocked backend) and service-integration-e2e (live local stack) patterns" size: large key-references: - "references/frontend.md" diff --git a/dev-workflows/.claude-plugin/plugin.json b/dev-workflows/.claude-plugin/plugin.json index ff70ff4..24ed421 100644 --- a/dev-workflows/.claude-plugin/plugin.json +++ b/dev-workflows/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "dev-workflows", "description": "Skills + Subagents for backend development - Use skills for coding guidance, or run recipe workflows for full orchestrated agentic coding with specialized agents", - "version": "0.17.0", + "version": "0.17.1", "author": { "name": "Shinsuke Kagawa", "url": "https://github.com/shinpr" diff --git a/dev-workflows/skills/task-analyzer/references/skills-index.yaml b/dev-workflows/skills/task-analyzer/references/skills-index.yaml index 0d08880..856c1e8 100644 --- a/dev-workflows/skills/task-analyzer/references/skills-index.yaml +++ b/dev-workflows/skills/task-analyzer/references/skills-index.yaml @@ -25,7 +25,7 @@ skills: - "Commenting Principles" - "Refactoring Approach" - "Testing Considerations" - - "Security Principles (Secure Defaults, Input and Output Boundaries, Access Control, Knowledge Cutoff Supplement)" + - "Security Principles" - "Documentation" - "Version Control Practices" - "Language-Specific Adaptations" @@ -122,8 +122,8 @@ skills: integration-e2e-testing: skill: "integration-e2e-testing" - tags: [testing, integration-testing, e2e-testing, test-design, behavior-first, roi, test-skeleton, ears-format] - typical-use: "Integration and E2E test design principles, ROI-based test selection, behavior-first approach, test skeleton specification" + tags: [testing, integration-testing, e2e-testing, fixture-e2e, service-integration-e2e, lane-selection, test-design, behavior-first, roi, test-skeleton, ears-format] + typical-use: "Integration and E2E test design principles, two-lane E2E split (fixture-e2e and service-integration-e2e) with lane-specific ROI thresholds, behavior-first approach, test skeleton specification" size: medium key-references: - "Test Pyramid - Mike Cohn" @@ -186,8 +186,8 @@ skills: test-implement: skill: "test-implement" - tags: [testing, frontend, react, react-testing-library, msw, playwright, e2e, coverage, tdd] - typical-use: "Test implementation patterns. references/frontend.md for RTL+Vitest+MSW, references/e2e.md for Playwright E2E" + tags: [testing, frontend, react, react-testing-library, msw, playwright, e2e, fixture-e2e, service-integration-e2e, coverage, tdd] + typical-use: "Test implementation patterns. references/frontend.md for RTL+Vitest+MSW, references/e2e.md for Playwright with both fixture-e2e (mocked backend) and service-integration-e2e (live local stack) patterns" size: large key-references: - "references/frontend.md" diff --git a/lefthook.yml b/lefthook.yml index 23fa2f0..59e91d9 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -23,3 +23,9 @@ pre-commit: claude plugin validate dev-workflows && \ claude plugin validate dev-workflows-frontend && \ claude plugin validate dev-skills + + - name: check-skills-index + glob: + - "skills/*/SKILL.md" + - "skills/task-analyzer/references/skills-index.yaml" + run: pnpm check:skills-index diff --git a/package.json b/package.json index 9347314..ce5d13d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claude-code-workflows", - "version": "0.17.0", + "version": "0.17.1", "private": true, "type": "module", "engines": { @@ -10,7 +10,8 @@ "scripts": { "prepare": "lefthook install", "sync": "node scripts/sync-plugins.mjs", - "sync:check": "node scripts/sync-plugins.mjs --check" + "sync:check": "node scripts/sync-plugins.mjs --check", + "check:skills-index": "node scripts/check-skills-index.mjs" }, "devDependencies": { "lefthook": "^2.1.6" diff --git a/scripts/check-skills-index.mjs b/scripts/check-skills-index.mjs new file mode 100644 index 0000000..91b5a2c --- /dev/null +++ b/scripts/check-skills-index.mjs @@ -0,0 +1,130 @@ +#!/usr/bin/env node +import { readFile } from 'node:fs/promises' +import { dirname, join, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' + +const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..') +const INDEX_PATH = join(ROOT, 'skills', 'task-analyzer', 'references', 'skills-index.yaml') +const SKILLS_DIR = join(ROOT, 'skills') + +function parseSkillsIndex(content) { + const skills = {} + const lines = content.split('\n') + + let currentSkill = null + let inSections = false + + for (const line of lines) { + const skillMatch = /^ {2}([\w-]+):\s*$/.exec(line) + if (skillMatch) { + currentSkill = skillMatch[1] + skills[currentSkill] = { sections: [], lineNumber: lines.indexOf(line) + 1 } + inSections = false + continue + } + + if (!currentSkill) continue + + if (/^ {4}sections:\s*$/.test(line)) { + inSections = true + continue + } + + if (/^ {4}[\w-]+:/.test(line)) { + inSections = false + continue + } + + if (inSections) { + const itemMatch = /^ {6}- "(.*)"\s*$/.exec(line) + if (itemMatch) { + skills[currentSkill].sections.push(itemMatch[1]) + } + } + } + + return skills +} + +function extractH2Headings(markdown) { + return markdown + .split('\n') + .filter((line) => line.startsWith('## ')) + .map((line) => line.replace(/^## /, '').trim()) +} + +function diffArrays(expected, actual) { + const max = Math.max(expected.length, actual.length) + const mismatches = [] + for (let i = 0; i < max; i++) { + if (expected[i] !== actual[i]) { + mismatches.push({ index: i, expected: expected[i] ?? '', actual: actual[i] ?? '' }) + } + } + return mismatches +} + +async function main() { + const indexContent = await readFile(INDEX_PATH, 'utf8') + const skills = parseSkillsIndex(indexContent) + + const skillNames = Object.keys(skills) + if (skillNames.length === 0) { + console.error('check-skills-index: no skill entries parsed from skills-index.yaml — parser may be broken') + process.exit(1) + } + + let failed = 0 + const reports = [] + + for (const name of skillNames) { + const skillMdPath = join(SKILLS_DIR, name, 'SKILL.md') + let markdown + try { + markdown = await readFile(skillMdPath, 'utf8') + } catch { + reports.push(`✗ ${name}: SKILL.md not found at ${skillMdPath} (yaml entry references a non-existent skill)`) + failed++ + continue + } + + const expected = skills[name].sections + const actual = extractH2Headings(markdown) + + if (expected.length === 0) { + reports.push(`! ${name}: yaml has no sections listed (expected at least one to validate)`) + failed++ + continue + } + + const mismatches = diffArrays(expected, actual) + if (mismatches.length === 0) { + reports.push(`✓ ${name}: ${expected.length} sections match`) + } else { + reports.push(`✗ ${name}: ${mismatches.length} mismatch(es)`) + for (const m of mismatches) { + reports.push(` [${m.index}] yaml: "${m.expected}"`) + reports.push(` md: "${m.actual}"`) + } + failed++ + } + } + + for (const line of reports) { + console.log(line) + } + + if (failed > 0) { + console.error(`\ncheck-skills-index: ${failed} skill(s) failed`) + console.error('Either update skills/task-analyzer/references/skills-index.yaml to match the SKILL.md headings,') + console.error('or update the SKILL.md headings to match the yaml. Order matters.') + process.exit(1) + } + + console.log(`\ncheck-skills-index: all ${skillNames.length} skill(s) consistent`) +} + +main().catch((err) => { + console.error(err) + process.exit(1) +}) diff --git a/skills/task-analyzer/references/skills-index.yaml b/skills/task-analyzer/references/skills-index.yaml index 0d08880..856c1e8 100644 --- a/skills/task-analyzer/references/skills-index.yaml +++ b/skills/task-analyzer/references/skills-index.yaml @@ -25,7 +25,7 @@ skills: - "Commenting Principles" - "Refactoring Approach" - "Testing Considerations" - - "Security Principles (Secure Defaults, Input and Output Boundaries, Access Control, Knowledge Cutoff Supplement)" + - "Security Principles" - "Documentation" - "Version Control Practices" - "Language-Specific Adaptations" @@ -122,8 +122,8 @@ skills: integration-e2e-testing: skill: "integration-e2e-testing" - tags: [testing, integration-testing, e2e-testing, test-design, behavior-first, roi, test-skeleton, ears-format] - typical-use: "Integration and E2E test design principles, ROI-based test selection, behavior-first approach, test skeleton specification" + tags: [testing, integration-testing, e2e-testing, fixture-e2e, service-integration-e2e, lane-selection, test-design, behavior-first, roi, test-skeleton, ears-format] + typical-use: "Integration and E2E test design principles, two-lane E2E split (fixture-e2e and service-integration-e2e) with lane-specific ROI thresholds, behavior-first approach, test skeleton specification" size: medium key-references: - "Test Pyramid - Mike Cohn" @@ -186,8 +186,8 @@ skills: test-implement: skill: "test-implement" - tags: [testing, frontend, react, react-testing-library, msw, playwright, e2e, coverage, tdd] - typical-use: "Test implementation patterns. references/frontend.md for RTL+Vitest+MSW, references/e2e.md for Playwright E2E" + tags: [testing, frontend, react, react-testing-library, msw, playwright, e2e, fixture-e2e, service-integration-e2e, coverage, tdd] + typical-use: "Test implementation patterns. references/frontend.md for RTL+Vitest+MSW, references/e2e.md for Playwright with both fixture-e2e (mocked backend) and service-integration-e2e (live local stack) patterns" size: large key-references: - "references/frontend.md"