mirror of
https://github.com/Jeffallan/claude-skills.git
synced 2026-09-14 18:43:38 +08:00
chore(roadmap): re-triage GitHub issues, rewrite ROADMAP.md, extend validation script
Phase 3+4+5 of v0.5.0 roadmap consolidation spec:
- Create V0.6.0 and V0.7.0 milestones, close V0.2.0/V0.3.0/V0.4.0
- Move 16 issues to correct milestones, close #67/#70/#71/#72
- Rewrite ROADMAP.md with actual release dates and updated v0.5.0-v1.0.0 scope
- Extend validate-skills.py with --check workflows: YAML definition validation,
DAG cycle detection, manifest consistency, orphan detection
- Drop Phase 6 (CI portability check) from spec — npx skills validates releases,
not PRs
This commit is contained in:
+78
-217
@@ -16,264 +16,134 @@
|
||||
## Development Timeline
|
||||
|
||||
```
|
||||
v0.3.2 ──────> v0.4.0 ──────> v0.5.0 ──────> v0.6.0 ──────> v0.7.0 ──────> v1.0.0
|
||||
(Current) Q1 2026 Q2 2026 Q3 2026 Q3 2026 Q4 2026
|
||||
Domain Cross- Skill Intelligence Template Workflow Stable
|
||||
Expansion Referencing Composition & Analytics UI Designer Release
|
||||
v0.4.2 ──────> v0.5.0 ──────> v0.6.0 ──────> v0.7.0 ──────> v1.0.0
|
||||
(Current) Workflow Local-First Skill Stable
|
||||
Overhaul Config Routing Release
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## v0.3.0 - Domain Expansion & Stabilization
|
||||
**Target:** Q1 2026 | **Scope:** +9 skills, stability improvements
|
||||
## v0.3.0 - Domain Expansion & Stabilization (Released)
|
||||
|
||||
### Goals
|
||||
Complete the foundational skill library with expanded domain coverage and enhanced reliability.
|
||||
**Released:** December 26, 2025 | Patches: v0.3.1 (2025-12-26), v0.3.2 (2026-01-17)
|
||||
|
||||
### New Domains
|
||||
|
||||
#### Data Science Domain (3 skills)
|
||||
- [#73](https://github.com/Jeffallan/claude-skills/issues/73): **pandas-pro** - Advanced data manipulation and analysis
|
||||
- [#74](https://github.com/Jeffallan/claude-skills/issues/74): **spark-engineer** - Distributed data processing at scale
|
||||
- [#75](https://github.com/Jeffallan/claude-skills/issues/75): **ml-pipeline** - End-to-end machine learning workflows
|
||||
|
||||
#### AI/LLM Domain (3 skills)
|
||||
- [#76](https://github.com/Jeffallan/claude-skills/issues/76): **prompt-engineer** - Systematic prompt design and optimization
|
||||
- [#77](https://github.com/Jeffallan/claude-skills/issues/77): **rag-architect** - Retrieval-Augmented Generation systems
|
||||
- [#78](https://github.com/Jeffallan/claude-skills/issues/78): **fine-tuning-expert** - Model customization and training
|
||||
|
||||
#### Platform Domain (3 skills)
|
||||
- [#79](https://github.com/Jeffallan/claude-skills/issues/79): **salesforce-developer** - CRM customization and development
|
||||
- [#80](https://github.com/Jeffallan/claude-skills/issues/80): **shopify-expert** - E-commerce platform development
|
||||
- [#81](https://github.com/Jeffallan/claude-skills/issues/81): **wordpress-pro** - WordPress development and optimization
|
||||
|
||||
### Improvements
|
||||
- Complete outstanding GitHub issues:
|
||||
- [#3](https://github.com/Jeffallan/claude-skills/issues/3): Kubernetes advanced patterns
|
||||
- [#4](https://github.com/Jeffallan/claude-skills/issues/4): Migration guides for legacy systems
|
||||
- Comprehensive testing of all skill triggers
|
||||
- Validation of routing table accuracy
|
||||
- Documentation updates for new skills
|
||||
|
||||
### Skill Enhancements
|
||||
- [#56](https://github.com/Jeffallan/claude-skills/issues/56): Add TDD Iron Laws reference to test-master skill
|
||||
- [#57](https://github.com/Jeffallan/claude-skills/issues/57): Add Testing Anti-Patterns reference to test-master skill
|
||||
- [#58](https://github.com/Jeffallan/claude-skills/issues/58): Add Systematic Debugging reference to debugging-wizard skill
|
||||
- [#59](https://github.com/Jeffallan/claude-skills/issues/59): Add Spec Compliance Review reference to code-reviewer skill
|
||||
- [#60](https://github.com/Jeffallan/claude-skills/issues/60): Add Receiving Feedback reference to code-reviewer skill
|
||||
|
||||
### Maintenance
|
||||
- [#63](https://github.com/Jeffallan/claude-skills/issues/63): Audit all skills for CLAUDE.md conformance (Description Trap)
|
||||
- [#61](https://github.com/Jeffallan/claude-skills/issues/61): Triage research/superpowers.md for remaining integration opportunities
|
||||
|
||||
### Success Metrics
|
||||
- All 63 skills validated and tested
|
||||
- 100% skill trigger accuracy
|
||||
- Zero breaking changes from v0.2.0
|
||||
- Complete reference documentation
|
||||
Added 9 skills across Data Science (pandas-pro, spark-engineer, ml-pipeline), AI/LLM (prompt-engineer, rag-architect, fine-tuning-expert), and Platform (salesforce-developer, shopify-expert, wordpress-pro) domains. Completed skill trigger validation, routing table accuracy audit, and reference documentation for test-master, debugging-wizard, and code-reviewer enhancements.
|
||||
|
||||
---
|
||||
|
||||
## v0.4.0 - Enhanced Skill Cross-Referencing
|
||||
**Target:** Q2 2026 | **Scope:** Intelligence layer improvements
|
||||
## v0.4.0 - Project Workflow Commands & Cross-Referencing (Released)
|
||||
|
||||
### Goals
|
||||
Enable skills to work together more effectively through intelligent cross-referencing and contextual recommendations.
|
||||
**Released:** January 18, 2026 | Patches: v0.4.1 (2026-01-19), v0.4.2 (2026-01-29)
|
||||
|
||||
### Features
|
||||
- [#64](https://github.com/Jeffallan/claude-skills/issues/64): **Smart Skill Discovery** - Automatic detection of related skills based on context
|
||||
- [#65](https://github.com/Jeffallan/claude-skills/issues/65): **Cross-Domain Recommendations** - Suggest complementary skills from different domains
|
||||
- [#66](https://github.com/Jeffallan/claude-skills/issues/66): **Enhanced Routing Logic** - Context-aware skill selection
|
||||
- [#67](https://github.com/Jeffallan/claude-skills/issues/67): **Related Skills Integration** - Deep linking between complementary skills
|
||||
- [#68](https://github.com/Jeffallan/claude-skills/issues/68): **Skill Dependency Mapping** - Visual representation of skill relationships
|
||||
|
||||
### Technical Improvements
|
||||
- [#69](https://github.com/Jeffallan/claude-skills/issues/69): Skill metadata enhancement
|
||||
- [#70](https://github.com/Jeffallan/claude-skills/issues/70): Improved context analysis algorithms
|
||||
- [#71](https://github.com/Jeffallan/claude-skills/issues/71): Better skill description indexing
|
||||
- [#72](https://github.com/Jeffallan/claude-skills/issues/72): Enhanced routing table intelligence
|
||||
|
||||
### Success Metrics
|
||||
- 30% improvement in relevant skill suggestions
|
||||
- Reduced user navigation time
|
||||
- Increased multi-skill usage patterns
|
||||
- Positive user feedback on recommendations
|
||||
Introduced 9 project workflow commands spanning discovery, planning, execution, and retrospective phases. Added Atlassian MCP integration for Jira/Confluence operations, epic-driven development lifecycle, and Common Ground assumption-surfacing skill. Established the progressive disclosure architecture with tiered reference loading.
|
||||
|
||||
---
|
||||
|
||||
## v0.5.0 - Skill Composition & Interactivity
|
||||
**Target:** Q2 2026 | **Scope:** Compositional framework
|
||||
## v0.5.0 - Workflow Overhaul
|
||||
|
||||
### Goals
|
||||
Transform skills from standalone tools into composable building blocks that work together seamlessly.
|
||||
**Scope:** Decouple workflow commands from Jira/Confluence, add per-project backend configuration, create a project intake phase, rework discovery for product-centric workflows, integrate feature-forge into the pipeline.
|
||||
|
||||
### Features
|
||||
- **Custom Slash Commands** - User-defined commands for common skill chains
|
||||
- **Skill Chaining** - Execute multiple skills in sequence with data flow
|
||||
- **Subagent Support** - Skills that can invoke other skills as subagents
|
||||
- **Interactive Skills** - Decision trees and clarifying questions
|
||||
- **Conditional Logic** - Branch based on context and user input
|
||||
- **Data Persistence** - Maintain state across skill invocations
|
||||
See [`docs/v0.5.0-plan.md`](docs/v0.5.0-plan.md) for the consolidated implementation plan.
|
||||
|
||||
### Workflow Command Enhancements
|
||||
- [#62](https://github.com/Jeffallan/claude-skills/issues/62): Generalize workflow commands for multiple documentation and ticketing systems
|
||||
- [#50](https://github.com/Jeffallan/claude-skills/issues/50): Context Persistence - Auto-store epic workflow state
|
||||
- [#51](https://github.com/Jeffallan/claude-skills/issues/51): State Validation - Prevent commands from running out of order
|
||||
- [#52](https://github.com/Jeffallan/claude-skills/issues/52): Error Recovery - Resume/rollback/retry mechanisms
|
||||
- [#53](https://github.com/Jeffallan/claude-skills/issues/53): Extract Shared Templates - Centralize checkpoint patterns
|
||||
### Backend Adapter Pattern
|
||||
- [#62](https://github.com/Jeffallan/claude-skills/issues/62): Generalize workflow commands for multiple ticketing and documentation systems
|
||||
- [#119](https://github.com/Jeffallan/claude-skills/issues/119): Backend adapter reference files (9 reference files for local, Jira, GitHub Issues, Confluence, GitHub Wiki backends)
|
||||
- Per-project config via `.claude/workflow-config.json` — ticketing (`local` | `jira` | `github-issues`) and documentation (`local` | `confluence` | `github-wiki`)
|
||||
|
||||
### Workflow Testing Infrastructure
|
||||
- [#54](https://github.com/Jeffallan/claude-skills/issues/54): Regression Test Suite - Automated execution integrated into workflow
|
||||
- [#55](https://github.com/Jeffallan/claude-skills/issues/55): Performance & Security Testing - Systematic integration into workflow
|
||||
### Intake Commands (New Phase)
|
||||
- [#120](https://github.com/Jeffallan/claude-skills/issues/120): Three new commands — `intake:document-codebase`, `intake:capture-behavior`, `intake:create-system-description`
|
||||
- Generates living system documentation, characterization tests, and SOC2-style system description
|
||||
|
||||
### Example Use Cases
|
||||
```
|
||||
/deploy-fullstack → backend-architect → frontend-architect → devops-sre → deploy
|
||||
/security-audit → security-researcher → penetration-tester → compliance-officer → report
|
||||
/product-launch → product-manager → ux-researcher → growth-hacker → marketing
|
||||
```
|
||||
### Discovery Rework
|
||||
- [#121](https://github.com/Jeffallan/claude-skills/issues/121): Full rewrite — topic-based input (not Jira epic key), local-first sources, produces epics AND tickets
|
||||
- [#103](https://github.com/Jeffallan/claude-skills/issues/103): Epic creation gap fix — discovery now creates epics, not just tickets
|
||||
|
||||
### Success Metrics
|
||||
- 20+ predefined skill chains
|
||||
- Support for custom user-defined chains
|
||||
- Seamless data flow between skills
|
||||
- Interactive skill engagement rates
|
||||
### Feature-Forge Integration
|
||||
- [#122](https://github.com/Jeffallan/claude-skills/issues/122): System description context (Step 0), discovery recommendation ("Needs additional discovery" standing option), output boundaries (optional EARS), skill-aware ticket generation
|
||||
|
||||
### Namespace & Directory Restructure
|
||||
- [#123](https://github.com/Jeffallan/claude-skills/issues/123): Drop `project:` prefix — `project:phase:action` becomes `phase:action`; flatten `commands/project/` to `commands/`; remove `complete-sprint` command
|
||||
|
||||
### Already Completed (Phase 1-2)
|
||||
- [#124](https://github.com/Jeffallan/claude-skills/issues/124): YAML workflow definition schema + DAG manifest
|
||||
- [#125](https://github.com/Jeffallan/claude-skills/issues/125): Narrative document restructure with per-command metadata
|
||||
|
||||
### Infrastructure
|
||||
- [#126](https://github.com/Jeffallan/claude-skills/issues/126): CI portability check — GitHub Action asserting `npx skills` detection matches `version.json`
|
||||
|
||||
### Command Count: 11
|
||||
- 3 new (intake), 7 reworked (backend-agnostic), 1 removed (complete-sprint)
|
||||
|
||||
---
|
||||
|
||||
## v0.6.0 - Intelligent Optimization
|
||||
**Target:** Q3 2026 | **Scope:** Analytics and optimization
|
||||
## v0.6.0 - Local-First Configuration
|
||||
|
||||
### Goals
|
||||
Provide visibility into skill performance and automatically optimize for cost and efficiency.
|
||||
**Scope:** Global-to-local config migration, per-project skill activation, workflow infrastructure hardening.
|
||||
|
||||
### Features
|
||||
- **Prompt Optimization Agent** - Automatic prompt refinement within skill chains
|
||||
- **Token Usage Tracking** - Per-prompt and per-project analytics
|
||||
- **Cost Analytics** - Real-time cost tracking and budgeting
|
||||
- **Efficiency Metrics** - Success rates, completion times, retry patterns
|
||||
- **Performance Insights** - Identify optimization opportunities
|
||||
- **Automated Prompt Engineering** - Inject prompt optimization into chains
|
||||
This release moves configuration from global to per-project, enabling teams to customize skill sets and workflow behavior per repository. Builds on the backend adapter pattern from v0.5.0.
|
||||
|
||||
### Analytics Dashboard
|
||||
- Token consumption trends
|
||||
- Cost projections and alerts
|
||||
- Skill usage patterns
|
||||
- Performance bottlenecks
|
||||
- Optimization recommendations
|
||||
### Configuration Migration
|
||||
- [Discussion #112](https://github.com/Jeffallan/claude-skills/discussions/112): Global-to-local config migration — `.claude/skills/` local install strategy, meta-skill/project analyzer
|
||||
- Per-project skill activation — select which skills are active for a given repository
|
||||
|
||||
### Success Metrics
|
||||
- 20% reduction in average token usage
|
||||
- Real-time cost visibility
|
||||
- Actionable optimization insights
|
||||
- Improved prompt efficiency scores
|
||||
### Workflow Infrastructure
|
||||
- [#50](https://github.com/Jeffallan/claude-skills/issues/50): Context Persistence — auto-store epic workflow state
|
||||
- [#51](https://github.com/Jeffallan/claude-skills/issues/51): State Validation — prevent commands from running out of order
|
||||
- [#52](https://github.com/Jeffallan/claude-skills/issues/52): Error Recovery — resume/rollback/retry mechanisms
|
||||
- [#53](https://github.com/Jeffallan/claude-skills/issues/53): Extract Shared Templates — centralize checkpoint patterns
|
||||
- [#54](https://github.com/Jeffallan/claude-skills/issues/54): Regression Test Suite — automated execution testing
|
||||
- [#55](https://github.com/Jeffallan/claude-skills/issues/55): Performance & Security Testing — systematic integration
|
||||
|
||||
### Common Ground
|
||||
- [#109](https://github.com/Jeffallan/claude-skills/issues/109): Common-ground local storage — persist assumptions per project
|
||||
|
||||
---
|
||||
|
||||
## v0.7.0 - Prompt Template UI
|
||||
**Target:** Q3 2026 | **Scope:** Template management interface
|
||||
## v0.7.0 - Enhanced Skill Routing
|
||||
|
||||
### Goals
|
||||
Empower users to create, manage, and share custom prompt templates through a visual interface.
|
||||
**Scope:** Improved skill discovery and routing, common-ground workflow integration. Depends on v0.6.0 local config.
|
||||
|
||||
### Features
|
||||
- **Visual Prompt Builder** - Drag-and-drop template creation
|
||||
- **Template Categories** - Skills, agents, one-off prompts, and custom types
|
||||
- **Template Library** - Browse, search, and import community templates
|
||||
- **Variable Management** - Define dynamic placeholders and defaults
|
||||
- **Template Versioning** - Track changes and rollback capabilities
|
||||
- **Export/Import** - Share templates with team or community
|
||||
- **Template Testing** - Validate templates before deployment
|
||||
### Skill Routing Improvements
|
||||
- [#65](https://github.com/Jeffallan/claude-skills/issues/65): Cross-Domain Recommendations — suggest complementary skills from different domains
|
||||
- [#66](https://github.com/Jeffallan/claude-skills/issues/66): Enhanced Routing Logic — context-aware skill selection
|
||||
- [#68](https://github.com/Jeffallan/claude-skills/issues/68): Skill Dependency Mapping — represent skill relationships
|
||||
- [#69](https://github.com/Jeffallan/claude-skills/issues/69): Skill metadata enhancement — structured `metadata` field for richer skill descriptors
|
||||
|
||||
### Template Types
|
||||
- Skill templates (new skill creation)
|
||||
- Agent templates (multi-skill workflows)
|
||||
- Prompt templates (reusable prompt patterns)
|
||||
- Chain templates (skill composition patterns)
|
||||
### Common Ground Enhancements
|
||||
- [#108](https://github.com/Jeffallan/claude-skills/issues/108): Common-ground SessionStart hook — automatic assumption surfacing on session start
|
||||
- [#110](https://github.com/Jeffallan/claude-skills/issues/110): Common-ground progressive disclosure — phased assumption surfacing
|
||||
- [#111](https://github.com/Jeffallan/claude-skills/issues/111): Common-ground UserPromptSubmit hook — contextual assumption checks
|
||||
|
||||
### Success Metrics
|
||||
- Intuitive template creation workflow
|
||||
- Growing template library
|
||||
- Active community contributions
|
||||
- Reduced time to create custom skills
|
||||
### Feasibility Evaluation
|
||||
- [#64](https://github.com/Jeffallan/claude-skills/issues/64): Smart Skill Discovery — consolidates #70, #71, #72; requires third-party tooling evaluation (vector embeddings, semantic search). Tracked separately pending feasibility assessment.
|
||||
|
||||
---
|
||||
|
||||
## v1.0.0 - Workflow Designer & Stable Release
|
||||
**Target:** Q4 2026 | **Scope:** Production-ready platform
|
||||
## v1.0.0 - Stable Release
|
||||
|
||||
### Goals
|
||||
Deliver a complete, stable, production-ready platform with visual workflow design capabilities.
|
||||
|
||||
### Features
|
||||
- **Visual Workflow Builder** - Complete drag-and-drop workflow composition
|
||||
- **Custom Slash Commands** - Visual designer for command creation
|
||||
- **Skill Chain Designer** - Map complex multi-skill workflows
|
||||
- **Conditional Branching** - Visual logic flow design
|
||||
- **Error Handling** - Built-in retry and fallback mechanisms
|
||||
- **Workflow Library** - Pre-built workflows for common scenarios
|
||||
- **Team Collaboration** - Share and collaborate on workflows
|
||||
- **Configuration Export** - JSON/YAML workflow definitions
|
||||
|
||||
### Workflow Examples
|
||||
```
|
||||
Customer Support Flow:
|
||||
Trigger → customer-success → [Analysis] → [Route Decision]
|
||||
├─ Technical → backend-architect → devops-sre → Resolution
|
||||
├─ Product → product-manager → ux-researcher → Feedback
|
||||
└─ Sales → sales-engineer → account-executive → Follow-up
|
||||
|
||||
Development Lifecycle:
|
||||
Feature Request → product-manager → [Spec] → backend-architect
|
||||
→ frontend-architect → [Code] → qa-automation → [Test]
|
||||
→ security-researcher → [Audit] → devops-sre → [Deploy]
|
||||
```
|
||||
**Scope:** Production-ready platform with comprehensive testing and documentation.
|
||||
|
||||
### Production Readiness
|
||||
- Comprehensive test coverage (95%+)
|
||||
- Comprehensive test coverage
|
||||
- Performance benchmarks established
|
||||
- Security audit completed
|
||||
- Documentation complete
|
||||
- Documentation complete for all commands, skills, and configuration
|
||||
- Migration guides for all versions
|
||||
- Long-term support commitment
|
||||
|
||||
### Success Metrics
|
||||
- Production adoption by enterprise teams
|
||||
- 99.9% uptime for core features
|
||||
- Positive user satisfaction (NPS 50+)
|
||||
- Active community ecosystem
|
||||
- Sustainable maintenance model
|
||||
### Stable Guarantees
|
||||
- Semantic versioning commitment
|
||||
- Backward compatibility within major version
|
||||
- Long-term support model
|
||||
|
||||
---
|
||||
|
||||
## Beyond v1.0.0 - Future Considerations
|
||||
|
||||
### Community & Ecosystem
|
||||
- Marketplace for community-created skills
|
||||
- Plugin architecture for custom integrations
|
||||
- Third-party skill certification program
|
||||
- Open-source contributor program
|
||||
|
||||
### Enterprise Features
|
||||
- Team collaboration tools
|
||||
- Role-based access control
|
||||
- Audit logging and compliance
|
||||
- Private skill repositories
|
||||
- On-premise deployment options
|
||||
|
||||
### Advanced Intelligence
|
||||
- AI-powered skill recommendations
|
||||
- Automatic workflow optimization
|
||||
- Predictive analytics
|
||||
- Natural language workflow creation
|
||||
- Self-improving prompts based on outcomes
|
||||
|
||||
### Integration Ecosystem
|
||||
- IDE plugins (VS Code, IntelliJ, etc.)
|
||||
- CI/CD pipeline integrations
|
||||
- Project management tool connectors
|
||||
- Communication platform bots (Slack, Teams)
|
||||
- API platform for programmatic access
|
||||
- Team collaboration features
|
||||
- IDE integrations
|
||||
- CI/CD pipeline connectors
|
||||
|
||||
---
|
||||
|
||||
@@ -285,7 +155,6 @@ We welcome community input on the roadmap direction. Here's how you can contribu
|
||||
- Open a GitHub issue with the `enhancement` label
|
||||
- Use the feature request template
|
||||
- Explain the use case and expected benefits
|
||||
- Provide examples of how it would work
|
||||
|
||||
### Vote on Priorities
|
||||
- React to existing feature requests
|
||||
@@ -296,20 +165,12 @@ We welcome community input on the roadmap direction. Here's how you can contribu
|
||||
- Follow the skill creation guide
|
||||
- Submit pull requests for new skills
|
||||
- Improve existing skill documentation
|
||||
- Share reference files and examples
|
||||
|
||||
### Share Feedback
|
||||
- Report bugs and issues promptly
|
||||
- Suggest improvements to existing skills
|
||||
- Share your skill usage patterns
|
||||
- Participate in community discussions
|
||||
|
||||
### Testing & Validation
|
||||
- Join the beta testing program
|
||||
- Validate pre-release versions
|
||||
- Provide detailed feedback
|
||||
- Help identify edge cases
|
||||
|
||||
---
|
||||
|
||||
## Versioning Philosophy
|
||||
@@ -341,4 +202,4 @@ We welcome community input on the roadmap direction. Here's how you can contribu
|
||||
|
||||
---
|
||||
|
||||
*This roadmap is a living document and subject to change based on community feedback, technical constraints, and emerging priorities. Last updated: January 2026 (v0.4.2)*
|
||||
*This roadmap is a living document and subject to change based on community feedback, technical constraints, and emerging priorities. Last updated: February 2026 (v0.4.2)*
|
||||
|
||||
@@ -232,52 +232,128 @@ Use a technical writing agent to:
|
||||
4. **Write missing content** — landing page copy, category descriptions, getting started guide
|
||||
5. **Refresh stale content** — update any sections referencing old versions or outdated patterns
|
||||
|
||||
### Phase 3: Site Generator Selection and Setup
|
||||
### Phase 3: Complete #69 — Skill Metadata Enhancement (BLOCKING)
|
||||
|
||||
Evaluate based on:
|
||||
- **[HARD] Dual-format output** — Can it output both HTML and raw markdown for every page?
|
||||
- Can it consume YAML frontmatter and generate pages programmatically?
|
||||
- Does it support auto-generation from structured data (like the command YAML files)?
|
||||
- Does it handle markdown with embedded code blocks well?
|
||||
- Does it support sitemap generation, meta tags, OpenGraph?
|
||||
- Can it deploy to GitHub Pages?
|
||||
**This phase must complete before site generator setup.** The Astro content collection schemas depend on the finalized metadata structure. Building the site before #69 means defining the schema twice — once provisionally, then again when the metadata spec lands.
|
||||
|
||||
Candidates:
|
||||
- **MkDocs + Material theme** — Python ecosystem, strong autodoc mindset, YAML-native config, good search. Dual-format: would need a plugin or post-build script to copy source .md files to output.
|
||||
- **Astro + Starlight** — Modern, content-collection-based, supports YAML/MDX, fast builds. Dual-format: Astro's build pipeline can output multiple formats per route via custom endpoints.
|
||||
- **Docusaurus** — React-based, good for versioned docs, plugin ecosystem. Dual-format: would need a custom plugin to emit .md alongside HTML.
|
||||
- **VitePress** — Vue-based, fast, good defaults for technical docs. Dual-format: would need a post-build step.
|
||||
#69 determines:
|
||||
- What fields exist in SKILL.md frontmatter vs. the `metadata.*` key
|
||||
- How relationship types are structured (complementary, prerequisite, alternative)
|
||||
- Whether domain tags, compatibility info, or other new metadata lives under `metadata.*`
|
||||
- The finalized schema that both the agent runtime AND the docs site consume
|
||||
|
||||
Note: Since the source content is already markdown, the simplest dual-format approach for any generator is a post-build script that copies the source `.md` files into the output directory mirroring the HTML route structure. This is generator-agnostic and avoids lock-in.
|
||||
The content collection schema, the internal link graph, the per-page meta tags, and the `llms.txt` index all derive from whatever #69 produces. Get the data model right first.
|
||||
|
||||
### Phase 4: Build and Deploy
|
||||
**What CAN proceed in parallel with #69:**
|
||||
- Phase 1 (audit) and Phase 2 (content restructuring) — these are about the docs content, not the schema
|
||||
- Evaluating Astro + Starlight with a proof-of-concept using current frontmatter fields
|
||||
- Setting up the repo structure for the docs site (Astro project scaffolding)
|
||||
|
||||
1. Set up the selected generator with the proposed site structure
|
||||
2. Write generator plugins/scripts to consume YAML definitions and produce pages
|
||||
3. Deploy to GitHub Pages with custom domain
|
||||
4. Submit sitemap to Google Search Console
|
||||
5. Add `llms.txt` to site root
|
||||
6. Add sponsor badges to site and repo README
|
||||
7. Set up GitHub Actions for auto-deploy on push to main
|
||||
### Phase 4: Site Generator Setup — Astro + Starlight
|
||||
|
||||
### Phase 5: Ongoing Maintenance
|
||||
#### Decision: Astro + Starlight
|
||||
|
||||
After evaluating Docusaurus, Hugo, MkDocs Material, and VitePress against the hard requirements (dual-format output, auto-generation from YAML/markdown, SEO), **Astro + Starlight** is the recommended choice.
|
||||
|
||||
**Why Astro wins for this project:**
|
||||
|
||||
| Requirement | How Astro Handles It |
|
||||
|---|---|
|
||||
| **Dual-format (HTML+MD)** | Custom endpoints serve raw markdown at `/skills/react-expert/index.md` alongside HTML at `/skills/react-expert/`. Supported pattern, not a hack. |
|
||||
| **Auto-gen from YAML/SKILL.md** | Content collections: define a schema matching SKILL.md frontmatter, point at `skills/*/SKILL.md`, pages are auto-generated with typed data. Command YAML files become a second collection. |
|
||||
| **SEO out of the box** | 100/100 Lighthouse scores. Auto sitemap, meta tags, OpenGraph. Starlight adds search, navigation, TOC. |
|
||||
| **Zero JS shipped** | Pure static HTML by default. No SPA hydration overhead. Instant loads for developers hitting docs from Google or LLM referrals. |
|
||||
| **Social cards** | Existing `scripts/capture-screenshot.js` can be adapted for per-page OG images. |
|
||||
|
||||
**Why not the others:**
|
||||
|
||||
- **Docusaurus** — Best SEO defaults, but ships a React SPA (unnecessary JS weight) and has no native content collection concept. Dual-format requires a custom plugin.
|
||||
- **Hugo** — Only SSG with first-class dual-format output (custom output formats). But Go templating for auto-generation from structured YAML is more manual wiring than Astro content collections. Strong fallback if Astro proves problematic.
|
||||
- **MkDocs Material** — Unique auto social card generation, but weakest on dual-format and programmatic page generation. Too opinionated about directory structure.
|
||||
- **VitePress** — Fast and clean, but less mature plugin ecosystem and no content collections.
|
||||
|
||||
**Ecosystem fit:** The project targets TypeScript/JavaScript developers. Astro uses TypeScript natively. Existing Python scripts (`validate-skills.py`, `update-docs.py`) remain as CI validation — the site generator doesn't replace them.
|
||||
|
||||
#### How Content Collections Map to This Project
|
||||
|
||||
```
|
||||
// Astro content collection schema (conceptual)
|
||||
// IMPORTANT: Final schema depends on #69 metadata enhancement
|
||||
|
||||
skills collection:
|
||||
source: skills/*/SKILL.md
|
||||
schema:
|
||||
name: string ← from frontmatter
|
||||
description: string ← from frontmatter (max 1024 chars)
|
||||
triggers: string[] ← from frontmatter
|
||||
role: enum ← specialist | expert | architect
|
||||
scope: enum ← implementation | review | design | ...
|
||||
output-format: enum ← code | document | report | ...
|
||||
metadata: ← from #69, structure TBD
|
||||
related: object[] ← typed relationships (complementary, prerequisite, etc.)
|
||||
domain: string[] ← domain tags
|
||||
...
|
||||
|
||||
commands collection:
|
||||
source: commands/**/*.yaml
|
||||
schema:
|
||||
command: string ← phase:action identifier
|
||||
phase: string ← intake | discovery | planning | ...
|
||||
inputs: object[] ← typed input definitions
|
||||
outputs: object[] ← typed output definitions
|
||||
requires: string[] ← ticketing | documentation
|
||||
status: enum ← existing | planned | deprecated
|
||||
|
||||
workflows collection:
|
||||
source: commands/workflow-manifest.yaml
|
||||
schema:
|
||||
phases: object ← DAG definition with depends_on edges
|
||||
utilities: object[] ← on-demand commands
|
||||
```
|
||||
|
||||
### Phase 5: Build and Deploy
|
||||
|
||||
1. Define Astro content collection schemas from finalized #69 metadata spec
|
||||
2. Build page templates for skills, commands, workflows
|
||||
3. Implement dual-format endpoints (HTML + markdown per page)
|
||||
4. Generate `llms.txt` from content collections at build time
|
||||
5. Deploy to GitHub Pages with custom domain
|
||||
6. Submit sitemap to Google Search Console
|
||||
7. Add sponsor badges to site and repo README
|
||||
8. Set up GitHub Actions for auto-deploy on push to main
|
||||
|
||||
### Phase 6: Ongoing Maintenance
|
||||
|
||||
- CI check: validate that every skill/command has a corresponding docs page
|
||||
- CI check: validate internal links (extends #100 cross-reference validation)
|
||||
- Auto-regenerate `llms.txt` on release
|
||||
- Auto-regenerate sitemap on content changes
|
||||
- Content collection schema validation catches broken frontmatter at build time
|
||||
|
||||
---
|
||||
|
||||
## Relationship to Existing Issues
|
||||
## Dependency Chain
|
||||
|
||||
| Issue | Relationship |
|
||||
|-------|-------------|
|
||||
| #69 — Skill Metadata Enhancement | Prerequisite for structured internal linking; can proceed with static `## Related Skills` sections initially |
|
||||
| #100 — Cross-Reference Validation | Extends to docs site link validation |
|
||||
| #65 — Cross-Domain Recommendations | Content improvements that directly improve docs site quality |
|
||||
| #66 — Enhanced Routing Logic | Better descriptions/triggers = better page titles and meta descriptions |
|
||||
| #68 — Skill Dependency Mapping | Visual DAG representation becomes a docs site page |
|
||||
```
|
||||
#69 Skill Metadata Enhancement
|
||||
├── Docs site content collection schemas (can't finalize without #69)
|
||||
├── #65 Cross-Domain Recommendations (content work, depends on #69)
|
||||
├── #66 Enhanced Routing Logic (better descriptions = better page titles)
|
||||
└── Internal link graph (relationship metadata → <a href> links)
|
||||
|
||||
#100 Cross-Reference Validation
|
||||
└── Docs site link validation (same check, dual purpose)
|
||||
|
||||
#68 Skill Dependency Mapping
|
||||
└── DAG visualization page on docs site
|
||||
|
||||
Phase 1 (Audit) ──────────────────── can start NOW
|
||||
Phase 2 (Content restructuring) ──── can start NOW
|
||||
Phase 3 (#69 metadata) ──────────── BLOCKING for site schema
|
||||
Phase 4 (Astro setup) ───────────── after #69
|
||||
Phase 5 (Build and deploy) ──────── after Phase 4
|
||||
Phase 6 (Maintenance) ───────────── ongoing after Phase 5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -285,5 +361,5 @@ Note: Since the source content is already markdown, the simplest dual-format app
|
||||
|
||||
1. **Custom domain?** — `docs.claudeskills.dev`, `skills.jeffallan.dev`, or subdirectory of existing site?
|
||||
2. **Versioned docs?** — Do we need docs for multiple versions, or just latest?
|
||||
3. **Search** — Built-in site search vs. Algolia DocSearch (free for open source)?
|
||||
4. **When to start?** — Can begin Phase 1 (audit) independently of #69 metadata work
|
||||
3. **Search** — Starlight built-in search vs. Algolia DocSearch (free for open source)?
|
||||
4. **Docs site repo** — Same repo (monorepo with `/site` directory) or separate repo?
|
||||
|
||||
+600
-12
@@ -9,6 +9,7 @@ Usage:
|
||||
python scripts/validate-skills.py # Run all checks
|
||||
python scripts/validate-skills.py --check yaml # YAML-related checks only
|
||||
python scripts/validate-skills.py --check references # Reference checks only
|
||||
python scripts/validate-skills.py --check workflows # Workflow definition checks only
|
||||
python scripts/validate-skills.py --skill react-expert # Single skill
|
||||
python scripts/validate-skills.py --format json # JSON for CI
|
||||
|
||||
@@ -113,6 +114,27 @@ COUNT_FILES = [
|
||||
]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Workflow Constants
|
||||
# =============================================================================
|
||||
|
||||
COMMANDS_DIR_WORKFLOW = "commands"
|
||||
MANIFEST_FILE = "commands/workflow-manifest.yaml"
|
||||
|
||||
# Required fields in per-command YAML definitions
|
||||
REQUIRED_DEFINITION_FIELDS = [
|
||||
"command", "path", "description", "inputs", "outputs", "requires",
|
||||
]
|
||||
|
||||
# Valid values for workflow definition fields
|
||||
VALID_INPUT_TYPES = {"string", "url", "list[url]", "list[string]", "flag", "file[]"}
|
||||
VALID_OUTPUT_TYPES = {"url", "document", "tickets", "report", "file", "directory"}
|
||||
VALID_REQUIRES = {"ticketing", "documentation"}
|
||||
VALID_STATUS = {"existing", "planned", "deprecated"}
|
||||
VALID_PHASES = {"intake", "discovery", "planning", "execution", "retrospective"}
|
||||
VALID_DEPENDENCY_STRENGTHS = {"required", "recommended"}
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Data Classes
|
||||
# =============================================================================
|
||||
@@ -169,29 +191,35 @@ class ValidationReport:
|
||||
"""Full validation report."""
|
||||
results: list[ValidationResult] = field(default_factory=list)
|
||||
count_issues: list[ValidationIssue] = field(default_factory=list)
|
||||
workflow_issues: list[ValidationIssue] = field(default_factory=list)
|
||||
|
||||
@property
|
||||
def has_errors(self) -> bool:
|
||||
return any(r.has_errors for r in self.results) or any(
|
||||
i.severity == Severity.ERROR for i in self.count_issues
|
||||
return (
|
||||
any(r.has_errors for r in self.results)
|
||||
or any(i.severity == Severity.ERROR for i in self.count_issues)
|
||||
or any(i.severity == Severity.ERROR for i in self.workflow_issues)
|
||||
)
|
||||
|
||||
@property
|
||||
def total_errors(self) -> int:
|
||||
count = sum(1 for r in self.results for i in r.issues if i.severity == Severity.ERROR)
|
||||
count += sum(1 for i in self.count_issues if i.severity == Severity.ERROR)
|
||||
count += sum(1 for i in self.workflow_issues if i.severity == Severity.ERROR)
|
||||
return count
|
||||
|
||||
@property
|
||||
def total_warnings(self) -> int:
|
||||
count = sum(1 for r in self.results for i in r.issues if i.severity == Severity.WARNING)
|
||||
count += sum(1 for i in self.count_issues if i.severity == Severity.WARNING)
|
||||
count += sum(1 for i in self.workflow_issues if i.severity == Severity.WARNING)
|
||||
return count
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"results": [r.to_dict() for r in self.results],
|
||||
"count_issues": [i.to_dict() for i in self.count_issues],
|
||||
"workflow_issues": [i.to_dict() for i in self.workflow_issues],
|
||||
"summary": {
|
||||
"total_skills": len(self.results),
|
||||
"total_errors": self.total_errors,
|
||||
@@ -559,6 +587,522 @@ class NonStandardHeadersChecker(BaseChecker):
|
||||
return issues
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Workflow Checkers
|
||||
# =============================================================================
|
||||
|
||||
class WorkflowDefinitionChecker:
|
||||
"""Validates per-command YAML definition files against the schema."""
|
||||
|
||||
name = "workflow-definition"
|
||||
|
||||
def check(self, base_path: Path) -> list[ValidationIssue]:
|
||||
issues = []
|
||||
commands_dir = base_path / COMMANDS_DIR_WORKFLOW
|
||||
|
||||
if not commands_dir.exists():
|
||||
issues.append(ValidationIssue(
|
||||
skill="__workflow__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Commands directory not found: {commands_dir}",
|
||||
))
|
||||
return issues
|
||||
|
||||
yaml_files = sorted([
|
||||
f for f in commands_dir.rglob("*.yaml")
|
||||
if f.name != "workflow-manifest.yaml"
|
||||
])
|
||||
|
||||
if not yaml_files:
|
||||
issues.append(ValidationIssue(
|
||||
skill="__workflow__",
|
||||
check=self.name,
|
||||
severity=Severity.WARNING,
|
||||
message="No workflow definition YAML files found",
|
||||
))
|
||||
return issues
|
||||
|
||||
for yaml_file in yaml_files:
|
||||
rel_path = str(yaml_file.relative_to(base_path))
|
||||
issues.extend(self._validate_definition(yaml_file, rel_path, base_path))
|
||||
|
||||
return issues
|
||||
|
||||
def _validate_definition(
|
||||
self, yaml_file: Path, rel_path: str, base_path: Path
|
||||
) -> list[ValidationIssue]:
|
||||
issues = []
|
||||
|
||||
try:
|
||||
data = parse_yaml(yaml_file.read_text())
|
||||
if data is None:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message="YAML file is empty",
|
||||
file=rel_path,
|
||||
))
|
||||
return issues
|
||||
except Exception as e:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"YAML parse error: {e}",
|
||||
file=rel_path,
|
||||
))
|
||||
return issues
|
||||
|
||||
command = data.get("command", "")
|
||||
is_utility = ":" not in command
|
||||
|
||||
# Check required fields (phase is optional for utility commands)
|
||||
for req_field in REQUIRED_DEFINITION_FIELDS:
|
||||
if req_field not in data:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Missing required field: {req_field}",
|
||||
file=rel_path,
|
||||
))
|
||||
|
||||
if not is_utility and "phase" not in data:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message="Missing required field: phase (required for phased commands)",
|
||||
file=rel_path,
|
||||
))
|
||||
|
||||
# Validate phase value
|
||||
phase = data.get("phase", "")
|
||||
if phase and phase not in VALID_PHASES:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.WARNING,
|
||||
message=f"Non-standard phase: '{phase}'. Expected: {', '.join(sorted(VALID_PHASES))}",
|
||||
file=rel_path,
|
||||
))
|
||||
|
||||
# Validate command prefix matches phase
|
||||
if command and phase and ":" in command:
|
||||
cmd_phase = command.split(":")[0]
|
||||
# Allow plural forms (e.g., "retrospectives" phase, "retrospectives:" prefix)
|
||||
if cmd_phase != phase and cmd_phase.rstrip("s") != phase.rstrip("s"):
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.WARNING,
|
||||
message=f"Command prefix '{cmd_phase}' doesn't match phase '{phase}'",
|
||||
file=rel_path,
|
||||
))
|
||||
|
||||
# Validate status
|
||||
status = data.get("status", "existing")
|
||||
if status not in VALID_STATUS:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.WARNING,
|
||||
message=f"Unknown status: '{status}'. Expected: {', '.join(sorted(VALID_STATUS))}",
|
||||
file=rel_path,
|
||||
))
|
||||
|
||||
# Validate path resolves (when status is existing)
|
||||
cmd_path = data.get("path", "")
|
||||
if cmd_path and status == "existing":
|
||||
if not (base_path / cmd_path).exists():
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Command file not found: {cmd_path}",
|
||||
file=rel_path,
|
||||
))
|
||||
|
||||
# Validate description path resolves
|
||||
desc_path = data.get("description", "")
|
||||
if desc_path:
|
||||
if not (base_path / desc_path).exists():
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Description file not found: {desc_path}",
|
||||
file=rel_path,
|
||||
))
|
||||
|
||||
# Validate requires values
|
||||
requires = data.get("requires", [])
|
||||
if isinstance(requires, list):
|
||||
for req in requires:
|
||||
if req not in VALID_REQUIRES:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.WARNING,
|
||||
message=f"Unknown requires value: '{req}'. Expected: {', '.join(sorted(VALID_REQUIRES))}",
|
||||
file=rel_path,
|
||||
))
|
||||
|
||||
# Validate inputs structure
|
||||
inputs = data.get("inputs", [])
|
||||
if isinstance(inputs, list):
|
||||
for i, inp in enumerate(inputs):
|
||||
if isinstance(inp, dict):
|
||||
for req_field in ["name", "type", "required", "description"]:
|
||||
if req_field not in inp:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Input [{i}] missing field: {req_field}",
|
||||
file=rel_path,
|
||||
))
|
||||
inp_type = inp.get("type", "")
|
||||
if inp_type and inp_type not in VALID_INPUT_TYPES:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.WARNING,
|
||||
message=f"Input [{i}] unknown type: '{inp_type}'",
|
||||
file=rel_path,
|
||||
))
|
||||
|
||||
# Validate outputs structure
|
||||
outputs = data.get("outputs", [])
|
||||
if isinstance(outputs, list):
|
||||
for i, out in enumerate(outputs):
|
||||
if isinstance(out, dict):
|
||||
for req_field in ["name", "type"]:
|
||||
if req_field not in out:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Output [{i}] missing field: {req_field}",
|
||||
file=rel_path,
|
||||
))
|
||||
out_type = out.get("type", "")
|
||||
if out_type and out_type not in VALID_OUTPUT_TYPES:
|
||||
issues.append(ValidationIssue(
|
||||
skill=rel_path,
|
||||
check=self.name,
|
||||
severity=Severity.WARNING,
|
||||
message=f"Output [{i}] unknown type: '{out_type}'",
|
||||
file=rel_path,
|
||||
))
|
||||
|
||||
return issues
|
||||
|
||||
|
||||
class ManifestDagChecker:
|
||||
"""Validates workflow-manifest.yaml structure and DAG integrity."""
|
||||
|
||||
name = "manifest-dag"
|
||||
|
||||
def check(self, base_path: Path) -> list[ValidationIssue]:
|
||||
issues = []
|
||||
manifest_path = base_path / MANIFEST_FILE
|
||||
|
||||
if not manifest_path.exists():
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Manifest file not found: {MANIFEST_FILE}",
|
||||
))
|
||||
return issues
|
||||
|
||||
try:
|
||||
data = parse_yaml(manifest_path.read_text())
|
||||
if data is None:
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message="Manifest is empty",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
return issues
|
||||
except Exception as e:
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"YAML parse error: {e}",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
return issues
|
||||
|
||||
phases = data.get("phases", {})
|
||||
if not phases:
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message="No phases defined in manifest",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
return issues
|
||||
|
||||
phase_names = set(phases.keys())
|
||||
all_commands = set()
|
||||
|
||||
for phase_name, phase_data in phases.items():
|
||||
if not isinstance(phase_data, dict):
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Phase '{phase_name}' must be a mapping",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
continue
|
||||
|
||||
# Check description path
|
||||
desc = phase_data.get("description", "")
|
||||
if desc and not (base_path / desc).exists():
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Phase '{phase_name}' description not found: {desc}",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
|
||||
# Check dependency references
|
||||
depends_on = phase_data.get("depends_on", [])
|
||||
if isinstance(depends_on, list):
|
||||
for dep in depends_on:
|
||||
if isinstance(dep, dict):
|
||||
dep_phase = dep.get("phase", "")
|
||||
if dep_phase and dep_phase not in phase_names:
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Phase '{phase_name}' depends on undefined phase: '{dep_phase}'",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
strength = dep.get("strength", "")
|
||||
if strength and strength not in VALID_DEPENDENCY_STRENGTHS:
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.WARNING,
|
||||
message=f"Phase '{phase_name}' dependency strength '{strength}' not standard",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
|
||||
# Check commands
|
||||
commands = phase_data.get("commands", [])
|
||||
if isinstance(commands, list):
|
||||
for cmd in commands:
|
||||
if isinstance(cmd, dict):
|
||||
cmd_name = cmd.get("command", "")
|
||||
if cmd_name:
|
||||
if cmd_name in all_commands:
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Duplicate command: '{cmd_name}'",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
all_commands.add(cmd_name)
|
||||
|
||||
definition = cmd.get("definition", "")
|
||||
if definition and not (base_path / definition).exists():
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Command '{cmd_name}' definition not found: {definition}",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
|
||||
# Check utilities
|
||||
utilities = data.get("utilities", [])
|
||||
if isinstance(utilities, list):
|
||||
for util in utilities:
|
||||
if isinstance(util, dict):
|
||||
cmd_name = util.get("command", "")
|
||||
if cmd_name:
|
||||
if cmd_name in all_commands:
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Duplicate command: '{cmd_name}'",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
all_commands.add(cmd_name)
|
||||
|
||||
definition = util.get("definition", "")
|
||||
if definition and not (base_path / definition).exists():
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"Utility '{cmd_name}' definition not found: {definition}",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
|
||||
# DAG cycle detection
|
||||
issues.extend(self._detect_cycles(phases, manifest_path))
|
||||
|
||||
# Cross-check: manifest commands match their definition files
|
||||
issues.extend(self._check_definition_consistency(
|
||||
phases, utilities, base_path, manifest_path
|
||||
))
|
||||
|
||||
return issues
|
||||
|
||||
def _detect_cycles(self, phases: dict, manifest_path: Path) -> list[ValidationIssue]:
|
||||
"""Detect cycles in the phase dependency graph using DFS."""
|
||||
issues = []
|
||||
|
||||
# Build adjacency list
|
||||
graph = {}
|
||||
for phase_name, phase_data in phases.items():
|
||||
if not isinstance(phase_data, dict):
|
||||
continue
|
||||
deps = []
|
||||
for dep in phase_data.get("depends_on", []):
|
||||
if isinstance(dep, dict):
|
||||
dep_phase = dep.get("phase", "")
|
||||
if dep_phase:
|
||||
deps.append(dep_phase)
|
||||
graph[phase_name] = deps
|
||||
|
||||
WHITE, GRAY, BLACK = 0, 1, 2
|
||||
color = {node: WHITE for node in graph}
|
||||
path = []
|
||||
|
||||
def dfs(node):
|
||||
color[node] = GRAY
|
||||
path.append(node)
|
||||
for neighbor in graph.get(node, []):
|
||||
if neighbor not in color:
|
||||
continue # Reference to undefined phase (caught elsewhere)
|
||||
if color[neighbor] == GRAY:
|
||||
cycle_start = path.index(neighbor)
|
||||
cycle = path[cycle_start:] + [neighbor]
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=f"DAG cycle detected: {' -> '.join(cycle)}",
|
||||
file=str(manifest_path),
|
||||
))
|
||||
path.pop()
|
||||
return
|
||||
if color[neighbor] == WHITE:
|
||||
dfs(neighbor)
|
||||
path.pop()
|
||||
color[node] = BLACK
|
||||
|
||||
for node in graph:
|
||||
if color[node] == WHITE:
|
||||
dfs(node)
|
||||
|
||||
return issues
|
||||
|
||||
def _check_definition_consistency(
|
||||
self,
|
||||
phases: dict,
|
||||
utilities: list,
|
||||
base_path: Path,
|
||||
manifest_path: Path,
|
||||
) -> list[ValidationIssue]:
|
||||
"""Verify manifest command names match the command field in their YAML definitions."""
|
||||
issues = []
|
||||
|
||||
def check_cmd(cmd_name: str, definition_path: str):
|
||||
full_path = base_path / definition_path
|
||||
if not full_path.exists():
|
||||
return # Missing file already reported
|
||||
try:
|
||||
data = parse_yaml(full_path.read_text())
|
||||
if data and data.get("command", "") != cmd_name:
|
||||
issues.append(ValidationIssue(
|
||||
skill="__manifest__",
|
||||
check=self.name,
|
||||
severity=Severity.ERROR,
|
||||
message=(
|
||||
f"Manifest command '{cmd_name}' doesn't match "
|
||||
f"definition command '{data.get('command', '')}' in {definition_path}"
|
||||
),
|
||||
file=str(manifest_path),
|
||||
))
|
||||
except Exception:
|
||||
pass # Parse errors reported elsewhere
|
||||
|
||||
for phase_data in phases.values():
|
||||
if not isinstance(phase_data, dict):
|
||||
continue
|
||||
for cmd in phase_data.get("commands", []):
|
||||
if isinstance(cmd, dict):
|
||||
check_cmd(cmd.get("command", ""), cmd.get("definition", ""))
|
||||
|
||||
if isinstance(utilities, list):
|
||||
for util in utilities:
|
||||
if isinstance(util, dict):
|
||||
check_cmd(util.get("command", ""), util.get("definition", ""))
|
||||
|
||||
return issues
|
||||
|
||||
|
||||
class WorkflowOrphanChecker:
|
||||
"""Detects command .md files not referenced by any YAML definition."""
|
||||
|
||||
name = "workflow-orphans"
|
||||
|
||||
def check(self, base_path: Path) -> list[ValidationIssue]:
|
||||
issues = []
|
||||
commands_dir = base_path / COMMANDS_DIR_WORKFLOW
|
||||
|
||||
if not commands_dir.exists():
|
||||
return issues
|
||||
|
||||
# Collect path references from all per-command YAML files
|
||||
referenced_paths = set()
|
||||
for yaml_file in commands_dir.rglob("*.yaml"):
|
||||
if yaml_file.name == "workflow-manifest.yaml":
|
||||
continue
|
||||
try:
|
||||
data = parse_yaml(yaml_file.read_text())
|
||||
if data and "path" in data:
|
||||
referenced_paths.add(data["path"])
|
||||
except Exception:
|
||||
pass # Parse errors reported by WorkflowDefinitionChecker
|
||||
|
||||
# Collect command .md files (exclude references/, skip COMMAND.md pattern)
|
||||
for md_file in sorted(commands_dir.rglob("*.md")):
|
||||
if "references" in md_file.parts:
|
||||
continue
|
||||
if md_file.name == "COMMAND.md":
|
||||
continue
|
||||
|
||||
md_rel = str(md_file.relative_to(base_path))
|
||||
if md_rel not in referenced_paths:
|
||||
issues.append(ValidationIssue(
|
||||
skill="__orphans__",
|
||||
check=self.name,
|
||||
severity=Severity.WARNING,
|
||||
message=f"Command file has no YAML definition: {md_rel}",
|
||||
file=md_rel,
|
||||
))
|
||||
|
||||
return issues
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Count Consistency Checker
|
||||
# =============================================================================
|
||||
@@ -631,6 +1175,28 @@ class CountConsistencyChecker:
|
||||
return issues
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Workflow Validator
|
||||
# =============================================================================
|
||||
|
||||
class WorkflowValidator:
|
||||
"""Orchestrates workflow definition and manifest validation."""
|
||||
|
||||
def __init__(self, base_path: Path):
|
||||
self.base_path = base_path
|
||||
self.checkers = [
|
||||
WorkflowDefinitionChecker(),
|
||||
ManifestDagChecker(),
|
||||
WorkflowOrphanChecker(),
|
||||
]
|
||||
|
||||
def validate(self) -> list[ValidationIssue]:
|
||||
issues = []
|
||||
for checker in self.checkers:
|
||||
issues.extend(checker.check(self.base_path))
|
||||
return issues
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Formatters
|
||||
# =============================================================================
|
||||
@@ -659,6 +1225,17 @@ class TableFormatter:
|
||||
file_info = f" ({issue.file})" if issue.file else ""
|
||||
lines.append(f" [{icon}] {issue.check}: {issue.message}{file_info}")
|
||||
|
||||
# Workflow issues
|
||||
if report.workflow_issues:
|
||||
lines.append("")
|
||||
lines.append("WORKFLOW ISSUES:")
|
||||
lines.append("-" * 80)
|
||||
for issue in report.workflow_issues:
|
||||
icon = "ERROR" if issue.severity == Severity.ERROR else "WARN "
|
||||
file_info = f" ({issue.file})" if issue.file else ""
|
||||
scope = f"[{issue.skill}] " if issue.skill else ""
|
||||
lines.append(f" [{icon}] {scope}{issue.check}: {issue.message}{file_info}")
|
||||
|
||||
# Count issues
|
||||
if report.count_issues:
|
||||
lines.append("")
|
||||
@@ -698,11 +1275,11 @@ class JsonFormatter:
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Validator
|
||||
# Skill Validator
|
||||
# =============================================================================
|
||||
|
||||
class SkillValidator:
|
||||
"""Main validator that orchestrates checks."""
|
||||
"""Main validator that orchestrates skill checks."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -783,18 +1360,20 @@ Examples:
|
||||
python scripts/validate-skills.py # Run all checks
|
||||
python scripts/validate-skills.py --check yaml # YAML-related checks only
|
||||
python scripts/validate-skills.py --check references # Reference checks only
|
||||
python scripts/validate-skills.py --check workflows # Workflow definition checks only
|
||||
python scripts/validate-skills.py --skill react-expert # Single skill
|
||||
python scripts/validate-skills.py --format json # JSON for CI
|
||||
|
||||
Check categories:
|
||||
yaml - YAML frontmatter validation (parsing, required fields, format)
|
||||
references - Reference file validation (directory, count, headers)
|
||||
workflows - Workflow YAML definitions, manifest DAG, orphan detection
|
||||
""",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--check",
|
||||
choices=["yaml", "references"],
|
||||
choices=["yaml", "references", "workflows"],
|
||||
help="Run only checks in the specified category",
|
||||
)
|
||||
|
||||
@@ -818,13 +1397,22 @@ Check categories:
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Run validation
|
||||
validator = SkillValidator(
|
||||
skills_dir=args.skills_dir,
|
||||
check_category=args.check,
|
||||
skill_filter=args.skill,
|
||||
)
|
||||
report = validator.validate()
|
||||
report = ValidationReport()
|
||||
|
||||
# Run skill validation (unless --check workflows)
|
||||
if args.check != "workflows":
|
||||
validator = SkillValidator(
|
||||
skills_dir=args.skills_dir,
|
||||
check_category=args.check,
|
||||
skill_filter=args.skill,
|
||||
)
|
||||
report = validator.validate()
|
||||
|
||||
# Run workflow validation (unless filtering to skill-specific checks)
|
||||
if args.check == "workflows" or (args.check is None and not args.skill):
|
||||
base_path = Path(".")
|
||||
workflow_validator = WorkflowValidator(base_path)
|
||||
report.workflow_issues = workflow_validator.validate()
|
||||
|
||||
# Format and output
|
||||
if args.format == "json":
|
||||
|
||||
@@ -223,80 +223,80 @@ And all issue links resolve to existing GitHub issues
|
||||
|
||||
## Implementation TODO
|
||||
|
||||
### Phase 1: YAML Schema & Definitions
|
||||
- [ ] Define YAML schema for per-command workflow definitions (document in `commands/references/workflow-definition-schema.md`)
|
||||
- [ ] Create `.yaml` files for all 11 commands (3 intake, 3 discovery, 2 planning, 2 execution, 1 retrospective)
|
||||
- [ ] Create `commands/workflow-manifest.yaml` with phase DAG and per-phase ordering
|
||||
- [ ] Create `docs/workflow/` directory with per-phase and per-command overview markdown files
|
||||
### Phase 1: YAML Schema & Definitions (DONE)
|
||||
- [x] Define YAML schema for per-command workflow definitions (document in `docs/workflow/workflow-definition-schema.md`)
|
||||
- [x] Create `.yaml` files for all 12 commands (3 intake, 3 discovery, 2 planning, 2 execution, 1 retrospective, 1 utility)
|
||||
- [x] Create `commands/workflow-manifest.yaml` with phase DAG and per-phase ordering
|
||||
- [x] Create `docs/workflow/` directory with per-phase and per-command overview markdown files
|
||||
|
||||
### Phase 2: Document Consolidation
|
||||
- [ ] Merge `v0.5.0-ideas.md`, `v0.5.0-ideas-2.md`, `v0.5.0-implementation.md` into `docs/v0.5.0-plan.md`
|
||||
- [ ] Restructure `docs/v0.5.0-narrative.md` with per-command input/output format
|
||||
- [ ] Delete superseded docs
|
||||
- [ ] Cross-link plan doc ↔ GitHub issues ↔ YAML definitions
|
||||
### Phase 2: Document Consolidation (DONE)
|
||||
- [x] Merge `v0.5.0-ideas.md`, `v0.5.0-ideas-2.md`, `v0.5.0-implementation.md` into `docs/v0.5.0-plan.md`
|
||||
- [x] Restructure `docs/v0.5.0-narrative.md` with per-command input/output format
|
||||
- [x] Delete superseded docs
|
||||
- [x] Cross-link plan doc ↔ GitHub issues ↔ YAML definitions
|
||||
|
||||
### Phase 3: GitHub Issue Re-Triage
|
||||
- [ ] Create milestone: v0.6.0 (global-to-local config migration)
|
||||
- [ ] Create milestone: v0.7.0 (enhanced skill routing + common-ground)
|
||||
### Phase 3: GitHub Issue Re-Triage (DONE)
|
||||
- [x] Create milestone: v0.6.0 (global-to-local config migration)
|
||||
- [x] Create milestone: v0.7.0 (enhanced skill routing + common-ground)
|
||||
|
||||
**v0.5.0 assignments:**
|
||||
- [ ] Keep #62 in v0.5.0 (core workflow generalization)
|
||||
- [ ] Assign #103 to v0.5.0 (discovery rework covers this)
|
||||
- [x] Keep #62 in v0.5.0 (core workflow generalization)
|
||||
- [x] Assign #103 to v0.5.0 (discovery rework covers this)
|
||||
|
||||
**v0.6.0 assignments:**
|
||||
- [ ] Move #50-55 from v0.5.0 to v0.6.0 (depend on local config)
|
||||
- [ ] Assign #109 to v0.6.0 (local config migration)
|
||||
- [x] Move #50-55 from v0.5.0 to v0.6.0 (depend on local config)
|
||||
- [x] Assign #109 to v0.6.0 (local config migration)
|
||||
|
||||
**v0.7.0 assignments:**
|
||||
- [ ] Move #65, #66, #69 from v0.5.0 to v0.7.0 (skill content work)
|
||||
- [ ] Move #68 from v0.5.0 to v0.7.0 (deferred diagram generation)
|
||||
- [ ] Assign #108, #110, #111 to v0.7.0 (common-ground enhancements)
|
||||
- [x] Move #65, #66, #69 from v0.5.0 to v0.7.0 (skill content work)
|
||||
- [x] Move #68 from v0.5.0 to v0.7.0 (deferred diagram generation)
|
||||
- [x] Assign #108, #110, #111 to v0.7.0 (common-ground enhancements)
|
||||
|
||||
**Closures:**
|
||||
- [ ] Close #67 (deep linking → #69, context sharing → deferred to v0.6.0)
|
||||
- [ ] Close #70, #71, #72 as duplicates (merged into #64)
|
||||
- [ ] Update #64 body to consolidate scope from #70, #71, #72
|
||||
- [ ] Convert #64 to GitHub Discussion, label 'needs-third-party'
|
||||
- [x] Close #67 (deep linking → #69, context sharing → deferred to v0.6.0)
|
||||
- [x] Close #70, #71, #72 as duplicates (merged into #64)
|
||||
- [x] Update #64 body to consolidate scope from #70, #71, #72
|
||||
- [x] Label #64 'needs-third-party', remove from milestone
|
||||
- [ ] Convert #64 to GitHub Discussion (requires GitHub UI — manual step)
|
||||
|
||||
**No milestone:**
|
||||
- [ ] Leave #98, #100 unmilestoned (good-first-issues)
|
||||
- [ ] Leave #106, #107 unmilestoned (infrastructure, not release-tied)
|
||||
- [x] Leave #98, #100 unmilestoned (good-first-issues)
|
||||
- [x] Leave #106, #107 unmilestoned (infrastructure, not release-tied)
|
||||
|
||||
**New issues to create for v0.5.0:**
|
||||
- [ ] Backend adapter reference files (Phase 1 of v0.5.0 plan)
|
||||
- [ ] Intake commands (document-codebase, capture-behavior, create-system-description)
|
||||
- [ ] Discovery command rework (topic-based, local-first)
|
||||
- [ ] Feature-forge integration (system description context, discovery recommendation)
|
||||
- [ ] Namespace change + directory restructure
|
||||
- [ ] YAML workflow definition schema + DAG manifest
|
||||
- [ ] Narrative document restructure
|
||||
- [ ] CI portability check (`npx skills` detection in GitHub Actions)
|
||||
**New issues created for v0.5.0:**
|
||||
- [x] #119 Backend adapter reference files
|
||||
- [x] #120 Intake commands (document-codebase, capture-behavior, create-system-description)
|
||||
- [x] #121 Discovery command rework (topic-based, local-first)
|
||||
- [x] #122 Feature-forge integration (system description context, discovery recommendation)
|
||||
- [x] #123 Namespace change + directory restructure
|
||||
- [x] #124 YAML workflow definition schema + DAG manifest
|
||||
- [x] #125 Narrative document restructure
|
||||
- [x] #126 CI portability check (`npx skills` detection in GitHub Actions)
|
||||
|
||||
**Verification:**
|
||||
- [ ] Every open issue has a milestone (except #98, #100, #106, #107)
|
||||
- [ ] No issue is assigned to multiple milestones
|
||||
- [x] Every open issue has a milestone (except #64, #98, #100, #106, #107)
|
||||
- [x] No issue is assigned to multiple milestones
|
||||
- [x] Removed stale v0.5.0 label from all issues (milestones are source of truth)
|
||||
|
||||
### Phase 4: Roadmap Update
|
||||
- [ ] Mark v0.3.0 as completed (note actual release info)
|
||||
- [ ] Mark v0.4.0, v0.4.1, v0.4.2 as completed
|
||||
- [ ] Rewrite v0.5.0 section: workflow overhaul (backend adapters, intake, discovery rework, feature-forge integration, namespace/directory restructure, YAML workflow definitions)
|
||||
- [ ] Add v0.6.0 section: global-to-local config migration (Discussion #112, meta-skill/project analyzer, per-project `.claude/skills/`, #50-55 workflow infra)
|
||||
- [ ] Add v0.7.0 section: enhanced skill routing (#64-72 with feasibility notes), common-ground improvements (#108-111), common-ground invocation points in new workflow
|
||||
- [ ] Update v0.8.0+ / v1.0.0 sections to reflect updated roadmap
|
||||
- [ ] Update development timeline ASCII diagram
|
||||
- [ ] Run `python scripts/update-docs.py` to sync counts
|
||||
### Phase 4: Roadmap Update (DONE)
|
||||
- [x] Mark v0.3.0 as completed (released 2025-12-26)
|
||||
- [x] Mark v0.4.0, v0.4.1, v0.4.2 as completed (2026-01-18, 2026-01-19, 2026-01-29)
|
||||
- [x] Rewrite v0.5.0 section: workflow overhaul (backend adapters, intake, discovery rework, feature-forge integration, namespace/directory restructure, YAML workflow definitions)
|
||||
- [x] Add v0.6.0 section: global-to-local config migration (Discussion #112, meta-skill/project analyzer, per-project `.claude/skills/`, #50-55 workflow infra)
|
||||
- [x] Add v0.7.0 section: enhanced skill routing (#64-72 with feasibility notes), common-ground improvements (#108-111)
|
||||
- [x] Update v1.0.0 section to reflect updated roadmap
|
||||
- [x] Update development timeline ASCII diagram
|
||||
- [ ] Run `python scripts/update-docs.py` to sync counts (deferred to v0.5.0 release)
|
||||
|
||||
### Phase 5: Validation Script Extension
|
||||
- [ ] Extend `scripts/validate-skills.py` to validate `.yaml` workflow definitions
|
||||
- [ ] Add DAG cycle detection for `workflow-manifest.yaml`
|
||||
- [ ] Add orphan detection (YAML without .md, .md without YAML)
|
||||
- [ ] Ensure `scripts/update-docs.py` excludes `.yaml` from workflow count
|
||||
### Phase 5: Validation Script Extension (DONE)
|
||||
- [x] Extend `scripts/validate-skills.py` to validate `.yaml` workflow definitions (`--check workflows`)
|
||||
- [x] Add DAG cycle detection for `workflow-manifest.yaml`
|
||||
- [x] Add orphan detection (.md without YAML)
|
||||
- [x] Add manifest ↔ definition consistency check (command names match)
|
||||
- [x] Verified `scripts/update-docs.py` already excludes `.yaml` from workflow count (uses `rglob("*.md")`)
|
||||
|
||||
### Phase 6: CI Portability Check
|
||||
- [ ] Add GitHub Action that runs `npx skills add . --non-interactive --list` on PRs
|
||||
- [ ] Assert detected skill count matches expected count from `version.json`
|
||||
- [ ] Catches portability regressions that `validate-skills.py` (project-specific) would miss
|
||||
- [ ] Validates skills remain discoverable by the standard ecosystem tooling (`add-skill`/`skills` CLI, VS Code Copilot, OpenCode, etc.)
|
||||
### Phase 6: CI Portability Check (DROPPED)
|
||||
Dropped — `npx skills add` resolves from the published registry, not the local working tree. Running it in CI on PRs would validate the last released version, not the PR's changes. The local `validate-skills.py` (Phase 5) is the pre-merge gate. Post-release smoke testing can be done manually.
|
||||
|
||||
## Out of Scope
|
||||
|
||||
|
||||
Reference in New Issue
Block a user