cc-devflow 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +83 -0
- package/.claude/agents/architecture-designer.md +443 -0
- package/.claude/agents/bug-analyzer.md +382 -0
- package/.claude/agents/checklist-agent.md +175 -0
- package/.claude/agents/clarify-analyst.md +50 -0
- package/.claude/agents/code-reviewer.md +71 -0
- package/.claude/agents/codex-analyzer.md +39 -0
- package/.claude/agents/compatibility-checker.md +580 -0
- package/.claude/agents/consistency-checker.md +532 -0
- package/.claude/agents/impact-analyzer.md +441 -0
- package/.claude/agents/planner.md +230 -0
- package/.claude/agents/prd-writer.md +320 -0
- package/.claude/agents/project-guidelines-generator.md +1329 -0
- package/.claude/agents/qa-tester.md +313 -0
- package/.claude/agents/release-manager.md +295 -0
- package/.claude/agents/security-reviewer.md +314 -0
- package/.claude/agents/style-guide-generator.md +458 -0
- package/.claude/agents/tech-architect.md +516 -0
- package/.claude/agents/ui-designer.md +485 -0
- package/.claude/commands/code-review-high.md +58 -0
- package/.claude/commands/core-architecture.md +429 -0
- package/.claude/commands/core-guidelines.md +486 -0
- package/.claude/commands/core-roadmap.md +439 -0
- package/.claude/commands/core-style.md +293 -0
- package/.claude/commands/flow-archive.md +245 -0
- package/.claude/commands/flow-checklist.md +260 -0
- package/.claude/commands/flow-clarify.md +136 -0
- package/.claude/commands/flow-constitution.md +82 -0
- package/.claude/commands/flow-dev.md +134 -0
- package/.claude/commands/flow-epic.md +150 -0
- package/.claude/commands/flow-fix.md +104 -0
- package/.claude/commands/flow-ideate.md +214 -0
- package/.claude/commands/flow-init.md +313 -0
- package/.claude/commands/flow-new.md +394 -0
- package/.claude/commands/flow-prd.md +131 -0
- package/.claude/commands/flow-qa.md +93 -0
- package/.claude/commands/flow-release.md +92 -0
- package/.claude/commands/flow-restart.md +98 -0
- package/.claude/commands/flow-status.md +64 -0
- package/.claude/commands/flow-tech.md +142 -0
- package/.claude/commands/flow-ui.md +189 -0
- package/.claude/commands/flow-update.md +111 -0
- package/.claude/commands/flow-upgrade.md +115 -0
- package/.claude/commands/flow-verify.md +96 -0
- package/.claude/commands/problem-analyzer.md +60 -0
- package/.claude/config/quality-rules.yml +161 -0
- package/.claude/docs/SPEC_KIT_CONSTITUTION_ANALYSIS.md +426 -0
- package/.claude/docs/design/consistency-conflict-detection-algorithms.md +658 -0
- package/.claude/docs/design/intent-driven-input-design.md +380 -0
- package/.claude/docs/design/prd-version-management-design.md +437 -0
- package/.claude/docs/guides/INIT_TROUBLESHOOTING.md +117 -0
- package/.claude/docs/guides/NEW_TROUBLESHOOTING.md +151 -0
- package/.claude/docs/guides/ROADMAP_TROUBLESHOOTING.md +188 -0
- package/.claude/docs/guides/TASK_COMPLETION_MARKING.md +338 -0
- package/.claude/docs/templates/ARCHITECTURE_TEMPLATE.md +633 -0
- package/.claude/docs/templates/BACKLOG_TEMPLATE.md +261 -0
- package/.claude/docs/templates/CHECKLIST_TEMPLATE.md +52 -0
- package/.claude/docs/templates/CLARIFICATION_REPORT_TEMPLATE.md +206 -0
- package/.claude/docs/templates/CODE_REVIEW_TEMPLATE.md +71 -0
- package/.claude/docs/templates/EPIC_TEMPLATE.md +805 -0
- package/.claude/docs/templates/INIT_FLOW_TEMPLATE.md +213 -0
- package/.claude/docs/templates/INTENT_CLARIFICATION_TEMPLATE.md +57 -0
- package/.claude/docs/templates/NEW_ORCHESTRATION_TEMPLATE.md +148 -0
- package/.claude/docs/templates/PRD_TEMPLATE.md +562 -0
- package/.claude/docs/templates/RESEARCH_TEMPLATE.md +276 -0
- package/.claude/docs/templates/REVIEW-HIGH.md +57 -0
- package/.claude/docs/templates/ROADMAP_DIALOGUE_TEMPLATE.md +198 -0
- package/.claude/docs/templates/ROADMAP_TEMPLATE.md +310 -0
- package/.claude/docs/templates/STYLE_TEMPLATE.md +1266 -0
- package/.claude/docs/templates/TASKS_TEMPLATE.md +523 -0
- package/.claude/docs/templates/TECH_DESIGN_TEMPLATE.md +1019 -0
- package/.claude/docs/templates/UI_PROTOTYPE_TEMPLATE.md +1436 -0
- package/.claude/guides/agent-guides/agent-coordination-guide.md +459 -0
- package/.claude/guides/project-guidelines-system.md +463 -0
- package/.claude/guides/technical-guides/datetime-handling-guide.md +563 -0
- package/.claude/guides/technical-guides/git-github-guide.md +642 -0
- package/.claude/guides/technical-guides/test-execution-guide.md +618 -0
- package/.claude/guides/workflow-guides/bug-fix-orchestrator.md +217 -0
- package/.claude/guides/workflow-guides/flow-orchestrator.md +282 -0
- package/.claude/hooks/checklist-gate.js +397 -0
- package/.claude/hooks/error-handling-reminder.sh +12 -0
- package/.claude/hooks/error-handling-reminder.ts +459 -0
- package/.claude/hooks/post-tool-use-tracker.sh +280 -0
- package/.claude/hooks/pre-tool-use-guardrail.sh +36 -0
- package/.claude/hooks/pre-tool-use-guardrail.ts +342 -0
- package/.claude/hooks/skill-activation-prompt.sh +36 -0
- package/.claude/hooks/skill-activation-prompt.ts +214 -0
- package/.claude/hooks/state/skills-used-test-guard.json +3 -0
- package/.claude/rules/devflow-conventions.md +305 -0
- package/.claude/rules/project-constitution.md +748 -0
- package/.claude/schemas/constitution.schema.json +43 -0
- package/.claude/scripts/analyze-upgrade-impact.sh +200 -0
- package/.claude/scripts/archive-requirement.sh +351 -0
- package/.claude/scripts/calculate-checklist-completion.sh +243 -0
- package/.claude/scripts/calculate-quarter.sh +206 -0
- package/.claude/scripts/check-dependencies.sh +409 -0
- package/.claude/scripts/check-prerequisites.sh +232 -0
- package/.claude/scripts/check-task-status.sh +264 -0
- package/.claude/scripts/checklist-errors.sh +131 -0
- package/.claude/scripts/common.sh +570 -0
- package/.claude/scripts/consolidate-research.sh +182 -0
- package/.claude/scripts/create-requirement.sh +426 -0
- package/.claude/scripts/export-contracts.sh +117 -0
- package/.claude/scripts/extract-data-model.sh +78 -0
- package/.claude/scripts/generate-clarification-questions.sh +377 -0
- package/.claude/scripts/generate-clarification-report.sh +463 -0
- package/.claude/scripts/generate-quickstart.sh +146 -0
- package/.claude/scripts/generate-research-tasks.sh +157 -0
- package/.claude/scripts/generate-status-report.sh +523 -0
- package/.claude/scripts/generate-tech-analysis.sh +46 -0
- package/.claude/scripts/locate-requirement-in-roadmap.sh +233 -0
- package/.claude/scripts/manage-constitution.sh +602 -0
- package/.claude/scripts/mark-task-complete.sh +198 -0
- package/.claude/scripts/populate-research-tasks.sh +259 -0
- package/.claude/scripts/recover-workflow.sh +460 -0
- package/.claude/scripts/run-clarify-scan.sh +601 -0
- package/.claude/scripts/run-high-review.sh +62 -0
- package/.claude/scripts/run-problem-analysis.sh +68 -0
- package/.claude/scripts/setup-epic.sh +173 -0
- package/.claude/scripts/sync-roadmap-progress.sh +300 -0
- package/.claude/scripts/sync-task-marks.sh +199 -0
- package/.claude/scripts/test-clarify-scan.sh +515 -0
- package/.claude/scripts/update-agent-context.sh +806 -0
- package/.claude/scripts/validate-constitution.sh +567 -0
- package/.claude/scripts/validate-hooks.sh +487 -0
- package/.claude/scripts/validate-research.sh +332 -0
- package/.claude/scripts/validate-scope-boundary.sh +493 -0
- package/.claude/scripts/verify-setup.sh +37 -0
- package/.claude/settings.json +76 -0
- package/.claude/skills/_reference-implementations/README.md +96 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/SKILL.md +302 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/architecture-overview.md +451 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/async-and-errors.md +307 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/complete-examples.md +638 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/configuration.md +275 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/database-patterns.md +224 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/middleware-guide.md +213 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/routing-and-controllers.md +756 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/sentry-and-monitoring.md +336 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/services-and-repositories.md +789 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/testing-guide.md +235 -0
- package/.claude/skills/_reference-implementations/backend-express-prisma/resources/validation-patterns.md +754 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/SKILL.md +399 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/common-patterns.md +331 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/complete-examples.md +872 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/component-patterns.md +502 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/data-fetching.md +767 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/file-organization.md +502 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/loading-and-error-states.md +501 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/performance.md +406 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/routing-guide.md +364 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/styling-guide.md +428 -0
- package/.claude/skills/_reference-implementations/frontend-react-mui/resources/typescript-standards.md +418 -0
- package/.claude/skills/cc-devflow-orchestrator/SKILL.md +229 -0
- package/.claude/skills/constitution-guardian/SKILL.md +306 -0
- package/.claude/skills/devflow-constitution-quick-ref/SKILL.md +374 -0
- package/.claude/skills/devflow-file-standards/SKILL.md +353 -0
- package/.claude/skills/devflow-tdd-enforcer/SKILL.md +192 -0
- package/.claude/skills/skill-developer/ADVANCED.md +197 -0
- package/.claude/skills/skill-developer/HOOK_MECHANISMS.md +306 -0
- package/.claude/skills/skill-developer/PATTERNS_LIBRARY.md +152 -0
- package/.claude/skills/skill-developer/SKILL.md +426 -0
- package/.claude/skills/skill-developer/SKILL_RULES_REFERENCE.md +315 -0
- package/.claude/skills/skill-developer/TRIGGER_TYPES.md +305 -0
- package/.claude/skills/skill-developer/TROUBLESHOOTING.md +514 -0
- package/.claude/skills/skill-rules.json +213 -0
- package/.claude/tests/README.md +300 -0
- package/.claude/tests/TODO.md +69 -0
- package/.claude/tests/__pycache__/test_analyze_upgrade_impact.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/__pycache__/test_consolidate_research.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/__pycache__/test_export_contracts.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/__pycache__/test_extract_data_model.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/__pycache__/test_generate_quickstart.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/__pycache__/test_generate_research_tasks.cpython-311-pytest-7.2.2.pyc +0 -0
- package/.claude/tests/constitution/run_all_constitution_tests.sh +111 -0
- package/.claude/tests/constitution/test_agent_assignment.sh +207 -0
- package/.claude/tests/constitution/test_article_coverage.sh +201 -0
- package/.claude/tests/constitution/test_template_completeness.sh +150 -0
- package/.claude/tests/constitution/test_version_consistency.sh +120 -0
- package/.claude/tests/fixtures/spec_delta_full.md +16 -0
- package/.claude/tests/fixtures/tasks_progress_sample.md +5 -0
- package/.claude/tests/run-all-tests.sh +229 -0
- package/.claude/tests/scripts/run.sh +30 -0
- package/.claude/tests/scripts/test-framework.sh +128 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh +511 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh.bak +504 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh.bak2 +505 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh.bak3 +506 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh.bak4 +507 -0
- package/.claude/tests/scripts/test_check_prerequisites.sh.bak5 +508 -0
- package/.claude/tests/scripts/test_check_task_status.sh +499 -0
- package/.claude/tests/scripts/test_common.sh +244 -0
- package/.claude/tests/scripts/test_generate_status_report.sh +71 -0
- package/.claude/tests/scripts/test_mark_task_complete.sh +441 -0
- package/.claude/tests/scripts/test_mark_task_complete.sh.backup +410 -0
- package/.claude/tests/scripts/test_recover_workflow.sh +304 -0
- package/.claude/tests/scripts/test_setup_epic.sh +437 -0
- package/.claude/tests/scripts/test_sync_task_marks.sh +196 -0
- package/.claude/tests/scripts/test_validate_constitution.sh +74 -0
- package/.claude/tests/scripts/test_validate_research.sh +462 -0
- package/.claude/tests/slugify.bats +82 -0
- package/.claude/tests/test-framework.sh +732 -0
- package/.claude/tests/test_analyze_upgrade_impact.py +34 -0
- package/.claude/tests/test_consolidate_research.py +48 -0
- package/.claude/tests/test_export_contracts.py +43 -0
- package/.claude/tests/test_extract_data_model.py +33 -0
- package/.claude/tests/test_generate_quickstart.py +50 -0
- package/.claude/tests/test_generate_research_tasks.py +52 -0
- package/.claude/tsc-cache/6e64f818-6398-49ca-8623-581a9af85c44/edited-files.log +1 -0
- package/.claude/tsc-cache/795ba6e3-b98a-423b-bab2-51aa62812569/affected-repos.txt +1 -0
- package/.claude/tsc-cache/795ba6e3-b98a-423b-bab2-51aa62812569/edited-files.log +1 -0
- package/.claude/tsc-cache/ae335694-be5a-4ba4-a1a0-b676c09a7906/affected-repos.txt +1 -0
- package/.claude/tsc-cache/ae335694-be5a-4ba4-a1a0-b676c09a7906/edited-files.log +1 -0
- package/CHANGELOG.md +507 -0
- package/LICENSE +21 -0
- package/README.md +534 -0
- package/README.zh-CN.md +530 -0
- package/bin/adapt.js +240 -0
- package/bin/cc-devflow-cli.js +185 -0
- package/bin/cc-devflow.js +78 -0
- package/config/adapters.yml +5 -0
- package/config/schema/adapters.schema.json +44 -0
- package/docs/CLAUDE.md +26 -0
- package/docs/commands/README.md +61 -0
- package/docs/commands/README.zh-CN.md +55 -0
- package/docs/commands/core-roadmap.md +106 -0
- package/docs/commands/core-roadmap.zh-CN.md +102 -0
- package/docs/commands/core-style.md +405 -0
- package/docs/commands/core-style.zh-CN.md +405 -0
- package/docs/commands/flow-init.md +134 -0
- package/docs/commands/flow-init.zh-CN.md +163 -0
- package/docs/commands/flow-new.md +274 -0
- package/docs/commands/flow-new.zh-CN.md +270 -0
- package/docs/guides/getting-started.md +204 -0
- package/docs/guides/getting-started.zh-CN.md +152 -0
- package/lib/adapters/adapter-interface.js +57 -0
- package/lib/adapters/claude-adapter.js +74 -0
- package/lib/adapters/codex-adapter.js +40 -0
- package/lib/adapters/config-validator.js +68 -0
- package/lib/adapters/logger.js +42 -0
- package/lib/adapters/registry.js +153 -0
- package/lib/compiler/CLAUDE.md +92 -0
- package/lib/compiler/__tests__/drift.test.js +215 -0
- package/lib/compiler/__tests__/errors.test.js +184 -0
- package/lib/compiler/__tests__/incremental.test.js +174 -0
- package/lib/compiler/__tests__/integration.test.js +174 -0
- package/lib/compiler/__tests__/manifest.test.js +233 -0
- package/lib/compiler/__tests__/parser.test.js +456 -0
- package/lib/compiler/__tests__/schemas.test.js +301 -0
- package/lib/compiler/__tests__/skills-registry.test.js +125 -0
- package/lib/compiler/__tests__/transformer.test.js +286 -0
- package/lib/compiler/emitters/antigravity-emitter.js +171 -0
- package/lib/compiler/emitters/base-emitter.js +73 -0
- package/lib/compiler/emitters/codex-emitter.js +52 -0
- package/lib/compiler/emitters/cursor-emitter.js +31 -0
- package/lib/compiler/emitters/index.js +50 -0
- package/lib/compiler/emitters/qwen-emitter.js +39 -0
- package/lib/compiler/errors.js +119 -0
- package/lib/compiler/index.js +256 -0
- package/lib/compiler/manifest.js +242 -0
- package/lib/compiler/parser.js +258 -0
- package/lib/compiler/platforms.js +113 -0
- package/lib/compiler/resource-copier.js +320 -0
- package/lib/compiler/rules-emitters/__tests__/antigravity-rules-emitter.test.js +191 -0
- package/lib/compiler/rules-emitters/__tests__/codex-rules-emitter.test.js +109 -0
- package/lib/compiler/rules-emitters/__tests__/cursor-rules-emitter.test.js +123 -0
- package/lib/compiler/rules-emitters/__tests__/qwen-rules-emitter.test.js +123 -0
- package/lib/compiler/rules-emitters/antigravity-rules-emitter.js +253 -0
- package/lib/compiler/rules-emitters/base-rules-emitter.js +83 -0
- package/lib/compiler/rules-emitters/codex-rules-emitter.js +116 -0
- package/lib/compiler/rules-emitters/cursor-rules-emitter.js +98 -0
- package/lib/compiler/rules-emitters/index.js +71 -0
- package/lib/compiler/rules-emitters/qwen-rules-emitter.js +70 -0
- package/lib/compiler/schemas.js +144 -0
- package/lib/compiler/skills-registry.js +225 -0
- package/lib/compiler/transformer.js +236 -0
- package/package.json +50 -0
|
@@ -0,0 +1,1329 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: project-guidelines-generator
|
|
3
|
+
description: Generates project-specific development guidelines (frontend-guidelines OR backend-guidelines). DOES NOT interact with user. Receives all required information via prompt including tech stack and target skill name.
|
|
4
|
+
tools: Read, Write, Grep, Glob, mcp__context7__resolve-library-id, mcp__context7__get-library-docs
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Project Guidelines Generator Agent
|
|
9
|
+
|
|
10
|
+
## Mission
|
|
11
|
+
|
|
12
|
+
Generate a single, focused development guidelines skill (either `frontend-guidelines` OR `backend-guidelines`) based on provided tech stack information.
|
|
13
|
+
|
|
14
|
+
## CRITICAL RULES
|
|
15
|
+
|
|
16
|
+
1. **NO USER INTERACTION**: This agent NEVER asks questions. All information must be in the prompt.
|
|
17
|
+
2. **SINGLE SKILL ONLY**: Generate exactly ONE skill per invocation (frontend OR backend, not both).
|
|
18
|
+
3. **SEPARATION OF CONCERNS**: Frontend and backend are INDEPENDENT skills with distinct activation boundaries.
|
|
19
|
+
4. **REFERENCE-DRIVEN**: Learn structure and patterns from reference implementations.
|
|
20
|
+
5. **DOCUMENTATION-POWERED**: Fetch official docs via Context7 MCP for accuracy.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Input Format
|
|
25
|
+
|
|
26
|
+
Expects the following in prompt:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"target_skill": "frontend-guidelines", // OR "backend-guidelines"
|
|
31
|
+
"scope": "frontend-only", // OR "backend-only"
|
|
32
|
+
"tech_stack": {
|
|
33
|
+
"framework": "React",
|
|
34
|
+
"version": "18.2.0",
|
|
35
|
+
"ui_library": "Material-UI v7",
|
|
36
|
+
"data_fetching": "TanStack Query",
|
|
37
|
+
"router": "TanStack Router",
|
|
38
|
+
"language": "TypeScript"
|
|
39
|
+
},
|
|
40
|
+
"project_structure": {
|
|
41
|
+
"frontend_dirs": ["src", "frontend"],
|
|
42
|
+
"backend_dirs": [],
|
|
43
|
+
"file_extensions": [".tsx", ".ts"]
|
|
44
|
+
},
|
|
45
|
+
"options": {
|
|
46
|
+
"force": false,
|
|
47
|
+
"dry_run": false
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Backend Example**:
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"target_skill": "backend-guidelines",
|
|
56
|
+
"scope": "backend-only",
|
|
57
|
+
"tech_stack": {
|
|
58
|
+
"framework": "Express",
|
|
59
|
+
"version": "4.18.2",
|
|
60
|
+
"orm": "Prisma",
|
|
61
|
+
"database": "PostgreSQL",
|
|
62
|
+
"language": "TypeScript"
|
|
63
|
+
},
|
|
64
|
+
"project_structure": {
|
|
65
|
+
"frontend_dirs": [],
|
|
66
|
+
"backend_dirs": ["backend", "api"],
|
|
67
|
+
"file_extensions": [".ts"]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Workflow
|
|
75
|
+
|
|
76
|
+
### Phase 0: Architecture Discovery (NEW)
|
|
77
|
+
|
|
78
|
+
**Objective**: Attempt to load and parse `devflow/ARCHITECTURE.md` for authoritative architecture information. This provides higher-quality tech stack and module structure data than heuristic detection.
|
|
79
|
+
|
|
80
|
+
**Data Source Priority**:
|
|
81
|
+
```
|
|
82
|
+
1. ARCHITECTURE.md (HIGHEST - human-reviewed, comprehensive)
|
|
83
|
+
2. package.json (MEDIUM - heuristic detection)
|
|
84
|
+
3. Command prompt (LOWEST - user input, may be incomplete)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// ===========================================================================
|
|
89
|
+
// Phase 0: Architecture Discovery
|
|
90
|
+
// ===========================================================================
|
|
91
|
+
|
|
92
|
+
interface ArchitectureData {
|
|
93
|
+
exists: boolean;
|
|
94
|
+
source: 'architecture_md' | 'package_json' | 'command_prompt';
|
|
95
|
+
tech_stack: {
|
|
96
|
+
frontend?: {
|
|
97
|
+
framework?: string; // "React 18 + TypeScript"
|
|
98
|
+
ui_library?: string; // "Material-UI v7"
|
|
99
|
+
state_management?: string;
|
|
100
|
+
data_fetching?: string;
|
|
101
|
+
router?: string;
|
|
102
|
+
build_tool?: string;
|
|
103
|
+
};
|
|
104
|
+
backend?: {
|
|
105
|
+
runtime?: string; // "Node.js 20"
|
|
106
|
+
framework?: string; // "Express.js"
|
|
107
|
+
language?: string; // "TypeScript"
|
|
108
|
+
api_style?: string; // "RESTful"
|
|
109
|
+
orm?: string; // "Prisma"
|
|
110
|
+
};
|
|
111
|
+
database?: {
|
|
112
|
+
primary?: string;
|
|
113
|
+
cache?: string;
|
|
114
|
+
orm?: string;
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
module_structure: {
|
|
118
|
+
directories: string[]; // ["src/", "backend/", ".claude/"]
|
|
119
|
+
tree: Record<string, string[]>; // {"src/": ["components/", "services/"]}
|
|
120
|
+
};
|
|
121
|
+
architecture_decisions: ADRRecord[];
|
|
122
|
+
warnings: string[];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// Main loader with fallback strategy
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
async function loadArchitectureData(
|
|
129
|
+
project_root: string,
|
|
130
|
+
target_skill: 'frontend-guidelines' | 'backend-guidelines'
|
|
131
|
+
): Promise<ArchitectureData> {
|
|
132
|
+
const archPath = `${project_root}/devflow/ARCHITECTURE.md`;
|
|
133
|
+
|
|
134
|
+
// Try ARCHITECTURE.md first
|
|
135
|
+
try {
|
|
136
|
+
const archContent = await Read(archPath);
|
|
137
|
+
console.log('✅ ARCHITECTURE.md found, parsing...');
|
|
138
|
+
|
|
139
|
+
const techStack = await parseTechStackSection(archContent, target_skill);
|
|
140
|
+
const moduleStructure = await parseModuleStructureDiagram(archContent);
|
|
141
|
+
const adrs = await parseADRRecords(archContent);
|
|
142
|
+
|
|
143
|
+
console.log(` Tech Stack: ${JSON.stringify(techStack)}`);
|
|
144
|
+
console.log(` Modules: ${moduleStructure.directories.join(', ')}`);
|
|
145
|
+
console.log(` ADRs: ${adrs.length} records`);
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
exists: true,
|
|
149
|
+
source: 'architecture_md',
|
|
150
|
+
tech_stack: techStack,
|
|
151
|
+
module_structure: moduleStructure,
|
|
152
|
+
architecture_decisions: adrs,
|
|
153
|
+
warnings: []
|
|
154
|
+
};
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.log('⚠️ ARCHITECTURE.md not found, fallback to command prompt data');
|
|
157
|
+
|
|
158
|
+
// Fallback: use tech_stack from command prompt
|
|
159
|
+
return {
|
|
160
|
+
exists: false,
|
|
161
|
+
source: 'command_prompt',
|
|
162
|
+
tech_stack: {}, // Will be populated from prompt
|
|
163
|
+
module_structure: { directories: [], tree: {} },
|
|
164
|
+
architecture_decisions: [],
|
|
165
|
+
warnings: ['ARCHITECTURE.md not found. Using command prompt data.']
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
// Parser 1: Extract Tech Stack from "技术栈" section
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
async function parseTechStackSection(
|
|
174
|
+
content: string,
|
|
175
|
+
target_skill: 'frontend-guidelines' | 'backend-guidelines'
|
|
176
|
+
): Promise<any> {
|
|
177
|
+
const result: any = {};
|
|
178
|
+
|
|
179
|
+
// Frontend extraction
|
|
180
|
+
if (target_skill === 'frontend-guidelines') {
|
|
181
|
+
const frontendMatch = content.match(/### Frontend\n([\s\S]*?)(?=\n### |$)/);
|
|
182
|
+
if (frontendMatch) {
|
|
183
|
+
const section = frontendMatch[1];
|
|
184
|
+
result.frontend = {
|
|
185
|
+
framework: section.match(/\*\*Framework\*\*:\s*(.+)/)?.[1].trim(),
|
|
186
|
+
state_management: section.match(/\*\*State Management\*\*:\s*(.+)/)?.[1].trim(),
|
|
187
|
+
ui_library: section.match(/\*\*UI Library\*\*:\s*(.+)/)?.[1].trim(),
|
|
188
|
+
build_tool: section.match(/\*\*Build Tool\*\*:\s*(.+)/)?.[1].trim(),
|
|
189
|
+
router: section.match(/\*\*Router\*\*:\s*(.+)/)?.[1].trim(),
|
|
190
|
+
data_fetching: section.match(/\*\*Data Fetching\*\*:\s*(.+)/)?.[1].trim()
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Remove undefined fields
|
|
194
|
+
Object.keys(result.frontend).forEach(key => {
|
|
195
|
+
if (!result.frontend[key]) delete result.frontend[key];
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Backend extraction
|
|
201
|
+
if (target_skill === 'backend-guidelines') {
|
|
202
|
+
const backendMatch = content.match(/### Backend\n([\s\S]*?)(?=\n### |$)/);
|
|
203
|
+
if (backendMatch) {
|
|
204
|
+
const section = backendMatch[1];
|
|
205
|
+
result.backend = {
|
|
206
|
+
runtime: section.match(/\*\*Runtime\*\*:\s*(.+)/)?.[1].trim(),
|
|
207
|
+
framework: section.match(/\*\*Framework\*\*:\s*(.+)/)?.[1].trim(),
|
|
208
|
+
language: section.match(/\*\*Language\*\*:\s*(.+)/)?.[1].trim(),
|
|
209
|
+
api_style: section.match(/\*\*API Style\*\*:\s*(.+)/)?.[1].trim(),
|
|
210
|
+
orm: section.match(/\*\*ORM\*\*:\s*(.+)/)?.[1].trim()
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
Object.keys(result.backend).forEach(key => {
|
|
214
|
+
if (!result.backend[key]) delete result.backend[key];
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Database (relevant for both)
|
|
220
|
+
const databaseMatch = content.match(/### Database\n([\s\S]*?)(?=\n### |$)/);
|
|
221
|
+
if (databaseMatch) {
|
|
222
|
+
const section = databaseMatch[1];
|
|
223
|
+
result.database = {
|
|
224
|
+
primary: section.match(/\*\*Primary\*\*:\s*(.+)/)?.[1].trim(),
|
|
225
|
+
cache: section.match(/\*\*Cache\*\*:\s*(.+)/)?.[1].trim(),
|
|
226
|
+
orm: section.match(/\*\*ORM.*?\*\*:\s*(.+)/)?.[1].trim()
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
Object.keys(result.database).forEach(key => {
|
|
230
|
+
if (!result.database[key]) delete result.database[key];
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// Parser 2: Extract Module Structure from Mermaid diagram
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
async function parseModuleStructureDiagram(content: string): Promise<any> {
|
|
241
|
+
const result = {
|
|
242
|
+
directories: [],
|
|
243
|
+
tree: {}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// Find Module Structure diagram (3. 模块划分图)
|
|
247
|
+
const diagramMatch = content.match(
|
|
248
|
+
/## 3\. 模块划分图[\s\S]*?```mermaid\n([\s\S]*?)```/
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
if (!diagramMatch) {
|
|
252
|
+
console.warn('⚠️ Module Structure diagram not found');
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const mermaidCode = diagramMatch[1];
|
|
257
|
+
|
|
258
|
+
// Extract subgraph names (directories)
|
|
259
|
+
const subgraphRegex = /subgraph\s+"([^"]+)"/g;
|
|
260
|
+
let match;
|
|
261
|
+
while ((match = subgraphRegex.exec(mermaidCode)) !== null) {
|
|
262
|
+
const dirName = match[1];
|
|
263
|
+
if (dirName.includes('/')) {
|
|
264
|
+
result.directories.push(dirName);
|
|
265
|
+
result.tree[dirName] = [];
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Extract nodes (subdirectories)
|
|
270
|
+
const lines = mermaidCode.split('\n');
|
|
271
|
+
let currentSubgraph = null;
|
|
272
|
+
|
|
273
|
+
for (const line of lines) {
|
|
274
|
+
const sgMatch = line.match(/subgraph\s+"([^"]+)"/);
|
|
275
|
+
if (sgMatch && sgMatch[1].includes('/')) {
|
|
276
|
+
currentSubgraph = sgMatch[1];
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const nodeMatch = line.match(/\w+\[([^\]]+)\]/);
|
|
281
|
+
if (nodeMatch && currentSubgraph) {
|
|
282
|
+
const label = nodeMatch[1];
|
|
283
|
+
if (label.includes('/')) {
|
|
284
|
+
result.tree[currentSubgraph].push(label);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (line.trim() === 'end') {
|
|
289
|
+
currentSubgraph = null;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ---------------------------------------------------------------------------
|
|
297
|
+
// Parser 3: Extract ADR Records
|
|
298
|
+
// ---------------------------------------------------------------------------
|
|
299
|
+
async function parseADRRecords(content: string): Promise<any[]> {
|
|
300
|
+
const adrs = [];
|
|
301
|
+
|
|
302
|
+
// Find all ADR sections
|
|
303
|
+
const adrRegex = /### ADR-(\d+):\s*(.+?)\n[\s\S]*?(?=### ADR-|\n## |$)/g;
|
|
304
|
+
let match;
|
|
305
|
+
|
|
306
|
+
while ((match = adrRegex.exec(content)) !== null) {
|
|
307
|
+
const adrNumber = match[1];
|
|
308
|
+
const title = match[2];
|
|
309
|
+
const fullText = match[0];
|
|
310
|
+
|
|
311
|
+
adrs.push({
|
|
312
|
+
number: adrNumber,
|
|
313
|
+
title,
|
|
314
|
+
date: fullText.match(/\*\*日期\*\*:\s*(.+)/)?.[1].trim(),
|
|
315
|
+
status: fullText.match(/\*\*状态\*\*:\s*(.+)/)?.[1].trim()?.split(' ')[0],
|
|
316
|
+
context: fullText.match(/\*\*背景.*?\*\*:\s*(.+)/)?.[1].trim(),
|
|
317
|
+
decision: fullText.match(/\*\*决策.*?\*\*:\s*(.+)/)?.[1].trim(),
|
|
318
|
+
rationale: fullText.match(/\*\*理由.*?\*\*:\s*([\s\S]*?)(?=\*\*影响|$)/)?.[1].trim()
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return adrs;
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
**Usage in Workflow**:
|
|
327
|
+
```typescript
|
|
328
|
+
// Execute Phase 0 first
|
|
329
|
+
const archData = await loadArchitectureData('.', target_skill);
|
|
330
|
+
|
|
331
|
+
// Merge with command prompt data if ARCHITECTURE.md doesn't exist
|
|
332
|
+
if (!archData.exists) {
|
|
333
|
+
archData.tech_stack = tech_stack_from_prompt; // From command prompt
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Log data source for transparency
|
|
337
|
+
console.log(`📊 Data Source: ${archData.source}`);
|
|
338
|
+
if (archData.warnings.length > 0) {
|
|
339
|
+
archData.warnings.forEach(w => console.warn(`⚠️ ${w}`));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Pass archData to subsequent phases
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
### Phase 1: Load Reference Implementation
|
|
348
|
+
|
|
349
|
+
**Objective**: Read appropriate reference implementation to understand structure and patterns.
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
// Determine reference directory
|
|
353
|
+
const referenceDir = target_skill === 'frontend-guidelines'
|
|
354
|
+
? '.claude/skills/_reference-implementations/frontend-react-mui/'
|
|
355
|
+
: '.claude/skills/_reference-implementations/backend-express-prisma/';
|
|
356
|
+
|
|
357
|
+
// Read reference SKILL.md
|
|
358
|
+
const referenceSkill = await Read(`${referenceDir}SKILL.md`);
|
|
359
|
+
|
|
360
|
+
// Read all resource files
|
|
361
|
+
const resourceFiles = await Glob(`${referenceDir}resources/*.md`);
|
|
362
|
+
const resources = {};
|
|
363
|
+
for (const file of resourceFiles) {
|
|
364
|
+
const content = await Read(file);
|
|
365
|
+
resources[basename(file)] = content;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Extract patterns:
|
|
369
|
+
// - Document structure
|
|
370
|
+
// - Section organization
|
|
371
|
+
// - Progressive disclosure approach
|
|
372
|
+
// - Table of contents style
|
|
373
|
+
// - Code example format
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**What to learn from reference**:
|
|
377
|
+
- How SKILL.md is structured (<500 lines)
|
|
378
|
+
- How resources/ are organized
|
|
379
|
+
- Naming conventions for resource files
|
|
380
|
+
- Quick reference tables format
|
|
381
|
+
- Navigation guide structure
|
|
382
|
+
- When to link to resources vs inline content
|
|
383
|
+
|
|
384
|
+
**ENHANCED: Integrate archData from Phase 0**:
|
|
385
|
+
```typescript
|
|
386
|
+
// Pass archData from Phase 0 to enrich context
|
|
387
|
+
const enrichedContext = {
|
|
388
|
+
reference: {
|
|
389
|
+
skill: referenceSkill,
|
|
390
|
+
resources
|
|
391
|
+
},
|
|
392
|
+
architecture: archData, // From Phase 0
|
|
393
|
+
techStackMatch: analyzeTechStackMatch(
|
|
394
|
+
referenceSkill,
|
|
395
|
+
archData.tech_stack,
|
|
396
|
+
target_skill
|
|
397
|
+
)
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
// Analyze Tech Stack Match
|
|
401
|
+
function analyzeTechStackMatch(reference, actualTechStack, target_skill) {
|
|
402
|
+
const report = {
|
|
403
|
+
score: 0, // 0-100
|
|
404
|
+
warnings: [],
|
|
405
|
+
recommendations: []
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
if (target_skill === 'frontend-guidelines') {
|
|
409
|
+
const actual = actualTechStack.frontend;
|
|
410
|
+
|
|
411
|
+
// Check framework match
|
|
412
|
+
if (actual?.framework?.includes('React')) {
|
|
413
|
+
report.score += 50;
|
|
414
|
+
} else if (actual?.framework?.includes('Vue')) {
|
|
415
|
+
report.score += 20;
|
|
416
|
+
report.warnings.push('Large framework difference: Vue vs React reference');
|
|
417
|
+
report.recommendations.push('Focus on framework-agnostic patterns (file organization, performance)');
|
|
418
|
+
} else if (actual?.framework?.includes('Angular')) {
|
|
419
|
+
report.score += 10;
|
|
420
|
+
report.warnings.push('Very different framework: Angular vs React');
|
|
421
|
+
report.recommendations.push('Extract layered architecture patterns only');
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Check UI library match
|
|
425
|
+
if (actual?.ui_library?.includes('Material-UI') || actual?.ui_library?.includes('MUI')) {
|
|
426
|
+
report.score += 30;
|
|
427
|
+
} else if (actual?.ui_library) {
|
|
428
|
+
report.score += 10;
|
|
429
|
+
report.warnings.push(`UI library mismatch: ${actual.ui_library} vs MUI reference`);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (target_skill === 'backend-guidelines') {
|
|
434
|
+
const actual = actualTechStack.backend;
|
|
435
|
+
|
|
436
|
+
if (actual?.framework?.includes('Express')) {
|
|
437
|
+
report.score += 50;
|
|
438
|
+
} else if (actual?.framework?.includes('Koa') || actual?.framework?.includes('Fastify')) {
|
|
439
|
+
report.score += 30;
|
|
440
|
+
report.warnings.push('Similar Node.js framework, minor adaptation needed');
|
|
441
|
+
} else if (actual?.framework?.includes('Django') || actual?.framework?.includes('Flask')) {
|
|
442
|
+
report.score += 10;
|
|
443
|
+
report.warnings.push('Different language: Python vs Node.js reference');
|
|
444
|
+
report.recommendations.push('Focus on layered architecture (Controllers→Services→Repositories)');
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (actual?.orm?.includes('Prisma')) {
|
|
448
|
+
report.score += 20;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return report;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Log match analysis
|
|
456
|
+
if (archData.exists) {
|
|
457
|
+
console.log('📊 Tech Stack Match Analysis:');
|
|
458
|
+
console.log(` Score: ${enrichedContext.techStackMatch.score}/100`);
|
|
459
|
+
|
|
460
|
+
if (enrichedContext.techStackMatch.warnings.length > 0) {
|
|
461
|
+
console.warn(' Warnings:');
|
|
462
|
+
enrichedContext.techStackMatch.warnings.forEach(w => console.warn(` - ${w}`));
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (enrichedContext.techStackMatch.recommendations.length > 0) {
|
|
466
|
+
console.log(' Recommendations:');
|
|
467
|
+
enrichedContext.techStackMatch.recommendations.forEach(r => console.log(` - ${r}`));
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
### Phase 2: Fetch Official Documentation (Context7 MCP)
|
|
475
|
+
|
|
476
|
+
**Objective**: Get up-to-date official documentation for each technology in the stack.
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
const docs = {};
|
|
480
|
+
|
|
481
|
+
// For frontend-guidelines
|
|
482
|
+
if (scope === 'frontend-only') {
|
|
483
|
+
// Fetch framework docs
|
|
484
|
+
const frameworkId = await mcp__context7__resolve-library-id({
|
|
485
|
+
libraryName: tech_stack.framework
|
|
486
|
+
});
|
|
487
|
+
docs.framework = await mcp__context7__get-library-docs({
|
|
488
|
+
context7CompatibleLibraryID: frameworkId.selected,
|
|
489
|
+
topic: "components hooks patterns",
|
|
490
|
+
tokens: 10000
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
// Fetch UI library docs (if applicable)
|
|
494
|
+
if (tech_stack.ui_library) {
|
|
495
|
+
const uiLibId = await mcp__context7__resolve-library-id({
|
|
496
|
+
libraryName: tech_stack.ui_library
|
|
497
|
+
});
|
|
498
|
+
docs.ui_library = await mcp__context7__get-library-docs({
|
|
499
|
+
context7CompatibleLibraryID: uiLibId.selected,
|
|
500
|
+
topic: "components styling theming",
|
|
501
|
+
tokens: 8000
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// Fetch data fetching library docs (if applicable)
|
|
506
|
+
if (tech_stack.data_fetching) {
|
|
507
|
+
const dataLibId = await mcp__context7__resolve-library-id({
|
|
508
|
+
libraryName: tech_stack.data_fetching
|
|
509
|
+
});
|
|
510
|
+
docs.data_fetching = await mcp__context7__get-library-docs({
|
|
511
|
+
context7CompatibleLibraryID: dataLibId.selected,
|
|
512
|
+
topic: "queries mutations caching",
|
|
513
|
+
tokens: 8000
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// For backend-guidelines
|
|
519
|
+
if (scope === 'backend-only') {
|
|
520
|
+
// Fetch framework docs
|
|
521
|
+
const frameworkId = await mcp__context7__resolve-library-id({
|
|
522
|
+
libraryName: tech_stack.framework
|
|
523
|
+
});
|
|
524
|
+
docs.framework = await mcp__context7__get-library-docs({
|
|
525
|
+
context7CompatibleLibraryID: frameworkId.selected,
|
|
526
|
+
topic: "routing middleware error-handling",
|
|
527
|
+
tokens: 10000
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// Fetch ORM docs (if applicable)
|
|
531
|
+
if (tech_stack.orm) {
|
|
532
|
+
const ormId = await mcp__context7__resolve-library-id({
|
|
533
|
+
libraryName: tech_stack.orm
|
|
534
|
+
});
|
|
535
|
+
docs.orm = await mcp__context7__get-library-docs({
|
|
536
|
+
context7CompatibleLibraryID: ormId.selected,
|
|
537
|
+
topic: "schema queries migrations",
|
|
538
|
+
tokens: 8000
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
**Fallback Strategy**:
|
|
545
|
+
```typescript
|
|
546
|
+
// If Context7 fails or library not found
|
|
547
|
+
if (!docs.framework) {
|
|
548
|
+
console.warn(`⚠️ Context7 failed for ${tech_stack.framework}`);
|
|
549
|
+
console.warn(`⚠️ Using reference implementation patterns without official docs`);
|
|
550
|
+
console.warn(`⚠️ Recommendation: Add official examples manually later`);
|
|
551
|
+
|
|
552
|
+
// Use reference as-is with placeholders
|
|
553
|
+
docs.framework = {
|
|
554
|
+
fallback: true,
|
|
555
|
+
message: "Official docs not available. Using generic patterns."
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
---
|
|
561
|
+
|
|
562
|
+
### Phase 3: Adapt Reference to Target Tech Stack
|
|
563
|
+
|
|
564
|
+
**Objective**: Transform reference implementation to target technology.
|
|
565
|
+
|
|
566
|
+
```typescript
|
|
567
|
+
// Generate SKILL.md
|
|
568
|
+
const skillContent = adaptSkillMd({
|
|
569
|
+
reference: referenceSkill,
|
|
570
|
+
tech_stack,
|
|
571
|
+
docs,
|
|
572
|
+
target_skill
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
// Generate resources/
|
|
576
|
+
const adaptedResources = {};
|
|
577
|
+
|
|
578
|
+
if (scope === 'frontend-only') {
|
|
579
|
+
adaptedResources['component-patterns.md'] = adaptComponentPatterns({
|
|
580
|
+
reference: resources['component-patterns.md'],
|
|
581
|
+
framework: tech_stack.framework,
|
|
582
|
+
docs: docs.framework
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
adaptedResources['data-fetching.md'] = adaptDataFetching({
|
|
586
|
+
reference: resources['data-fetching.md'],
|
|
587
|
+
library: tech_stack.data_fetching,
|
|
588
|
+
docs: docs.data_fetching
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
adaptedResources['styling-guide.md'] = adaptStyling({
|
|
592
|
+
reference: resources['styling-guide.md'],
|
|
593
|
+
ui_library: tech_stack.ui_library,
|
|
594
|
+
docs: docs.ui_library
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
// ... other frontend resources
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (scope === 'backend-only') {
|
|
601
|
+
adaptedResources['architecture-overview.md'] = adaptArchitecture({
|
|
602
|
+
reference: resources['architecture-overview.md'],
|
|
603
|
+
framework: tech_stack.framework,
|
|
604
|
+
docs: docs.framework
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
adaptedResources['routing-controllers.md'] = adaptRouting({
|
|
608
|
+
reference: resources['routing-and-controllers.md'],
|
|
609
|
+
framework: tech_stack.framework,
|
|
610
|
+
docs: docs.framework
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
adaptedResources['database-patterns.md'] = adaptDatabase({
|
|
614
|
+
reference: resources['database-patterns.md'],
|
|
615
|
+
orm: tech_stack.orm,
|
|
616
|
+
docs: docs.orm
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
// ... other backend resources
|
|
620
|
+
}
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
**Adaptation Rules**:
|
|
624
|
+
|
|
625
|
+
1. **Framework-Specific Code**:
|
|
626
|
+
```typescript
|
|
627
|
+
// React → Vue example
|
|
628
|
+
"React.FC<Props>" → "defineComponent"
|
|
629
|
+
"import React from 'react'" → "import { defineComponent } from 'vue'"
|
|
630
|
+
"useState" → "ref"
|
|
631
|
+
"useEffect" → "onMounted"
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
2. **UI Library Specifics**:
|
|
635
|
+
```typescript
|
|
636
|
+
// MUI → Ant Design example
|
|
637
|
+
"import { Box, Paper } from '@mui/material'" → "import { Card, Space } from 'antd'"
|
|
638
|
+
"sx={{ p: 2 }}" → "style={{ padding: '16px' }}"
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
3. **Keep Framework-Agnostic Content**:
|
|
642
|
+
- File organization principles
|
|
643
|
+
- Performance optimization strategies
|
|
644
|
+
- TypeScript best practices
|
|
645
|
+
- Architecture patterns (layered architecture works everywhere)
|
|
646
|
+
|
|
647
|
+
4. **Extract Code Examples from Context7 Docs**:
|
|
648
|
+
```typescript
|
|
649
|
+
function extractCodeExample(docs, keyword) {
|
|
650
|
+
// Parse Context7 docs for relevant code blocks
|
|
651
|
+
const codeBlockRegex = /```(\w+)\n([\s\S]*?)```/g;
|
|
652
|
+
const matches = [...docs.matchAll(codeBlockRegex)];
|
|
653
|
+
|
|
654
|
+
// Find most relevant match
|
|
655
|
+
const relevant = matches.find(m =>
|
|
656
|
+
m[2].toLowerCase().includes(keyword.toLowerCase())
|
|
657
|
+
);
|
|
658
|
+
|
|
659
|
+
return relevant ? relevant[2] : null;
|
|
660
|
+
}
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
### Phase 4: Generate Files
|
|
666
|
+
|
|
667
|
+
**Objective**: Write generated content to correct locations.
|
|
668
|
+
|
|
669
|
+
```typescript
|
|
670
|
+
const outputDir = `.claude/skills/${target_skill}/`;
|
|
671
|
+
|
|
672
|
+
// Create directory if doesn't exist
|
|
673
|
+
await Bash(`mkdir -p ${outputDir}resources/`);
|
|
674
|
+
|
|
675
|
+
// Write SKILL.md
|
|
676
|
+
await Write(`${outputDir}SKILL.md`, skillContent);
|
|
677
|
+
|
|
678
|
+
// Write resources/
|
|
679
|
+
for (const [filename, content] of Object.entries(adaptedResources)) {
|
|
680
|
+
await Write(`${outputDir}resources/${filename}`, content);
|
|
681
|
+
}
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
**Validation**:
|
|
685
|
+
```typescript
|
|
686
|
+
// Verify SKILL.md line count
|
|
687
|
+
const lineCount = skillContent.split('\n').length;
|
|
688
|
+
if (lineCount > 500) {
|
|
689
|
+
console.warn(`⚠️ SKILL.md is ${lineCount} lines (should be <500)`);
|
|
690
|
+
console.warn(`⚠️ Consider moving more content to resources/`);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// Verify no hardcoded paths
|
|
694
|
+
const hardcodedPaths = [
|
|
695
|
+
/\/Users\/\w+/,
|
|
696
|
+
/~\/git\//,
|
|
697
|
+
/C:\\Users/
|
|
698
|
+
];
|
|
699
|
+
for (const pattern of hardcodedPaths) {
|
|
700
|
+
if (pattern.test(skillContent)) {
|
|
701
|
+
throw new Error(`Constitution violation: Hardcoded path detected in SKILL.md`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
### Phase 5: Update skill-rules.json
|
|
709
|
+
|
|
710
|
+
**Objective**: Register skill with appropriate triggers.
|
|
711
|
+
|
|
712
|
+
```typescript
|
|
713
|
+
// Read existing skill-rules.json
|
|
714
|
+
const rulesPath = '.claude/skills/skill-rules.json';
|
|
715
|
+
const rules = JSON.parse(await Read(rulesPath));
|
|
716
|
+
|
|
717
|
+
// Generate path patterns based on project structure
|
|
718
|
+
const pathPatterns = generatePathPatterns({
|
|
719
|
+
target_skill,
|
|
720
|
+
project_structure,
|
|
721
|
+
tech_stack
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
// Generate keywords
|
|
725
|
+
const keywords = generateKeywords({
|
|
726
|
+
target_skill,
|
|
727
|
+
tech_stack
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
// Create skill entry
|
|
731
|
+
rules[target_skill] = {
|
|
732
|
+
type: "domain",
|
|
733
|
+
enforcement: "suggest",
|
|
734
|
+
priority: "high",
|
|
735
|
+
promptTriggers: {
|
|
736
|
+
keywords,
|
|
737
|
+
intentPatterns: generateIntentPatterns(target_skill, tech_stack)
|
|
738
|
+
},
|
|
739
|
+
fileTriggers: {
|
|
740
|
+
pathPatterns
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
|
|
744
|
+
// Write back
|
|
745
|
+
await Write(rulesPath, JSON.stringify(rules, null, 2));
|
|
746
|
+
|
|
747
|
+
// Validate JSON
|
|
748
|
+
await Bash(`jq . ${rulesPath}`);
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
**Path Pattern Generation (ENHANCED with ARCHITECTURE.md)**:
|
|
752
|
+
```typescript
|
|
753
|
+
function generatePathPatterns({ target_skill, project_structure, tech_stack, archData }) {
|
|
754
|
+
const patterns = [];
|
|
755
|
+
|
|
756
|
+
// ------------------------
|
|
757
|
+
// Strategy 1: Use ARCHITECTURE.md Module Structure (HIGHEST PRIORITY)
|
|
758
|
+
// ------------------------
|
|
759
|
+
if (archData?.exists && archData.module_structure.directories.length > 0) {
|
|
760
|
+
console.log('✅ Using Module Structure from ARCHITECTURE.md');
|
|
761
|
+
|
|
762
|
+
if (target_skill === 'frontend-guidelines') {
|
|
763
|
+
// Extract frontend-related directories
|
|
764
|
+
const frontendDirs = archData.module_structure.directories.filter(dir =>
|
|
765
|
+
dir.includes('src') ||
|
|
766
|
+
dir.includes('frontend') ||
|
|
767
|
+
dir.includes('client') ||
|
|
768
|
+
dir.includes('web') ||
|
|
769
|
+
dir.includes('app') ||
|
|
770
|
+
dir.includes('components')
|
|
771
|
+
);
|
|
772
|
+
|
|
773
|
+
for (const dir of frontendDirs) {
|
|
774
|
+
patterns.push(`${dir}**/*.tsx`);
|
|
775
|
+
patterns.push(`${dir}**/*.ts`);
|
|
776
|
+
patterns.push(`${dir}**/*.jsx`);
|
|
777
|
+
patterns.push(`${dir}**/*.vue`);
|
|
778
|
+
patterns.push(`${dir}**/*.svelte`);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Use subdirectories from tree for more specific patterns
|
|
782
|
+
for (const [parent, children] of Object.entries(archData.module_structure.tree)) {
|
|
783
|
+
if (frontendDirs.some(fd => parent.includes(fd) || fd.includes(parent))) {
|
|
784
|
+
for (const child of children) {
|
|
785
|
+
patterns.push(`${parent}${child}**/*`);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
if (target_skill === 'backend-guidelines') {
|
|
792
|
+
const backendDirs = archData.module_structure.directories.filter(dir =>
|
|
793
|
+
dir.includes('backend') ||
|
|
794
|
+
dir.includes('api') ||
|
|
795
|
+
dir.includes('server') ||
|
|
796
|
+
dir.includes('services')
|
|
797
|
+
);
|
|
798
|
+
|
|
799
|
+
for (const dir of backendDirs) {
|
|
800
|
+
patterns.push(`${dir}**/*.ts`);
|
|
801
|
+
patterns.push(`${dir}**/*.js`);
|
|
802
|
+
patterns.push(`${dir}**/*.py`);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// Use subdirectories
|
|
806
|
+
for (const [parent, children] of Object.entries(archData.module_structure.tree)) {
|
|
807
|
+
if (backendDirs.some(bd => parent.includes(bd) || bd.includes(parent))) {
|
|
808
|
+
for (const child of children) {
|
|
809
|
+
patterns.push(`${parent}${child}**/*`);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
console.log(` Generated ${patterns.length} path patterns from ARCHITECTURE.md`);
|
|
816
|
+
return patterns; // Return early if ARCHITECTURE.md provides data
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// ------------------------
|
|
820
|
+
// Strategy 2: Fallback to project_structure detection
|
|
821
|
+
// ------------------------
|
|
822
|
+
console.log('⚠️ No ARCHITECTURE.md, using project_structure from command prompt');
|
|
823
|
+
|
|
824
|
+
if (target_skill === 'frontend-guidelines') {
|
|
825
|
+
// Use detected frontend directories
|
|
826
|
+
for (const dir of project_structure.frontend_dirs) {
|
|
827
|
+
patterns.push(`${dir}/**/*.${tech_stack.file_extension}`);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// Add common patterns
|
|
831
|
+
patterns.push('src/**/*.tsx', 'src/**/*.jsx', 'src/**/*.vue', 'src/**/*.svelte');
|
|
832
|
+
patterns.push('frontend/**/*', 'client/**/*', 'web/**/*');
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
if (target_skill === 'backend-guidelines') {
|
|
836
|
+
for (const dir of project_structure.backend_dirs) {
|
|
837
|
+
patterns.push(`${dir}/**/*.${tech_stack.file_extension}`);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
patterns.push('backend/**/*', 'api/**/*', 'server/**/*');
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
return patterns;
|
|
844
|
+
}
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
**Keyword Generation (ENHANCED with ARCHITECTURE.md)**:
|
|
848
|
+
```typescript
|
|
849
|
+
function generateKeywords({ target_skill, tech_stack, archData }) {
|
|
850
|
+
const keywords = [];
|
|
851
|
+
|
|
852
|
+
// ------------------------
|
|
853
|
+
// Strategy 1: Use ARCHITECTURE.md tech stack (HIGHEST PRIORITY)
|
|
854
|
+
// ------------------------
|
|
855
|
+
if (archData?.exists && archData.tech_stack) {
|
|
856
|
+
console.log('✅ Using Tech Stack from ARCHITECTURE.md for keywords');
|
|
857
|
+
|
|
858
|
+
if (target_skill === 'frontend-guidelines' && archData.tech_stack.frontend) {
|
|
859
|
+
const fe = archData.tech_stack.frontend;
|
|
860
|
+
|
|
861
|
+
// Extract framework keyword
|
|
862
|
+
if (fe.framework) {
|
|
863
|
+
const frameworkKeyword = fe.framework.split(' ')[0].toLowerCase(); // "React" from "React 18"
|
|
864
|
+
keywords.push(frameworkKeyword);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// Extract UI library keyword
|
|
868
|
+
if (fe.ui_library) {
|
|
869
|
+
const uiKeyword = fe.ui_library.split(' ')[0].toLowerCase(); // "Material" from "Material-UI v7"
|
|
870
|
+
keywords.push(uiKeyword);
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// Extract state management keyword
|
|
874
|
+
if (fe.state_management) {
|
|
875
|
+
keywords.push(fe.state_management.toLowerCase());
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
// Extract router keyword
|
|
879
|
+
if (fe.router) {
|
|
880
|
+
const routerKeyword = fe.router.split(' ')[0].toLowerCase();
|
|
881
|
+
keywords.push(routerKeyword);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// Add common frontend keywords
|
|
885
|
+
keywords.push('component', 'page', 'route', 'frontend', 'UI', 'styling', 'hooks');
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
if (target_skill === 'backend-guidelines' && archData.tech_stack.backend) {
|
|
889
|
+
const be = archData.tech_stack.backend;
|
|
890
|
+
|
|
891
|
+
// Extract framework keyword
|
|
892
|
+
if (be.framework) {
|
|
893
|
+
const frameworkKeyword = be.framework.split(/\s|\./)[0].toLowerCase(); // "Express" from "Express.js"
|
|
894
|
+
keywords.push(frameworkKeyword);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// Extract ORM keyword
|
|
898
|
+
if (be.orm) {
|
|
899
|
+
keywords.push(be.orm.toLowerCase());
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// Extract API style keyword
|
|
903
|
+
if (be.api_style) {
|
|
904
|
+
keywords.push(be.api_style.toLowerCase()); // "restful"
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// Add common backend keywords
|
|
908
|
+
keywords.push('controller', 'service', 'repository', 'backend', 'API', 'endpoint', 'middleware');
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// Add database keywords if available
|
|
912
|
+
if (archData.tech_stack.database?.primary) {
|
|
913
|
+
const dbKeyword = archData.tech_stack.database.primary.split(' ')[0].toLowerCase();
|
|
914
|
+
keywords.push(dbKeyword);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
console.log(` Generated ${keywords.length} keywords from ARCHITECTURE.md`);
|
|
918
|
+
return keywords;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// ------------------------
|
|
922
|
+
// Strategy 2: Fallback to tech_stack from command prompt
|
|
923
|
+
// ------------------------
|
|
924
|
+
console.log('⚠️ No ARCHITECTURE.md, using tech_stack from command prompt');
|
|
925
|
+
|
|
926
|
+
if (target_skill === 'frontend-guidelines') {
|
|
927
|
+
keywords.push('component', 'page', 'route', 'frontend', 'UI', 'styling');
|
|
928
|
+
keywords.push(tech_stack.framework.toLowerCase());
|
|
929
|
+
if (tech_stack.ui_library) {
|
|
930
|
+
keywords.push(tech_stack.ui_library.toLowerCase().split(' ')[0]);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
if (target_skill === 'backend-guidelines') {
|
|
935
|
+
keywords.push('controller', 'service', 'repository', 'backend', 'API', 'endpoint');
|
|
936
|
+
keywords.push(tech_stack.framework.toLowerCase());
|
|
937
|
+
if (tech_stack.orm) {
|
|
938
|
+
keywords.push(tech_stack.orm.toLowerCase());
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
return keywords;
|
|
943
|
+
}
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
---
|
|
947
|
+
|
|
948
|
+
### Phase 6: Return Result
|
|
949
|
+
|
|
950
|
+
**Objective**: Provide comprehensive summary to command layer.
|
|
951
|
+
|
|
952
|
+
```json
|
|
953
|
+
{
|
|
954
|
+
"status": "success",
|
|
955
|
+
"skill_name": "frontend-guidelines",
|
|
956
|
+
"scope": "frontend-only",
|
|
957
|
+
"tech_stack": {
|
|
958
|
+
"framework": "React",
|
|
959
|
+
"ui_library": "Material-UI v7",
|
|
960
|
+
"data_fetching": "TanStack Query"
|
|
961
|
+
},
|
|
962
|
+
"files_created": [
|
|
963
|
+
".claude/skills/frontend-guidelines/SKILL.md",
|
|
964
|
+
".claude/skills/frontend-guidelines/resources/component-patterns.md",
|
|
965
|
+
".claude/skills/frontend-guidelines/resources/data-fetching.md",
|
|
966
|
+
".claude/skills/frontend-guidelines/resources/styling-guide.md",
|
|
967
|
+
".claude/skills/frontend-guidelines/resources/routing-guide.md",
|
|
968
|
+
".claude/skills/frontend-guidelines/resources/performance.md",
|
|
969
|
+
".claude/skills/frontend-guidelines/resources/typescript-standards.md"
|
|
970
|
+
],
|
|
971
|
+
"skill_rules_updated": true,
|
|
972
|
+
"triggers": {
|
|
973
|
+
"file_patterns": [
|
|
974
|
+
"src/**/*.tsx",
|
|
975
|
+
"src/**/*.ts",
|
|
976
|
+
"frontend/**/*.tsx"
|
|
977
|
+
],
|
|
978
|
+
"keywords": [
|
|
979
|
+
"component",
|
|
980
|
+
"React",
|
|
981
|
+
"MUI",
|
|
982
|
+
"styling",
|
|
983
|
+
"hooks",
|
|
984
|
+
"page",
|
|
985
|
+
"route"
|
|
986
|
+
]
|
|
987
|
+
},
|
|
988
|
+
"context7_status": {
|
|
989
|
+
"React": "success",
|
|
990
|
+
"Material-UI": "success",
|
|
991
|
+
"TanStack Query": "success"
|
|
992
|
+
},
|
|
993
|
+
"validation": {
|
|
994
|
+
"skill_md_line_count": 487,
|
|
995
|
+
"constitution_compliant": true,
|
|
996
|
+
"skill_rules_valid_json": true
|
|
997
|
+
},
|
|
998
|
+
"warnings": [],
|
|
999
|
+
"recommendations": [
|
|
1000
|
+
"Try editing src/components/App.tsx - skill should activate",
|
|
1001
|
+
"Customize resources/ with project-specific patterns",
|
|
1002
|
+
"Run /core-guidelines --force to regenerate if tech stack changes"
|
|
1003
|
+
]
|
|
1004
|
+
}
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
---
|
|
1008
|
+
|
|
1009
|
+
## Error Handling
|
|
1010
|
+
|
|
1011
|
+
### Context7 Library Not Found
|
|
1012
|
+
|
|
1013
|
+
```typescript
|
|
1014
|
+
try {
|
|
1015
|
+
const libId = await mcp__context7__resolve-library-id({ libraryName: "Vuetify" });
|
|
1016
|
+
} catch (error) {
|
|
1017
|
+
console.warn(`⚠️ Context7: Library "Vuetify" not found`);
|
|
1018
|
+
console.warn(`⚠️ Fallback: Using reference implementation patterns`);
|
|
1019
|
+
console.warn(`⚠️ Recommendation: Visit https://vuetifyjs.com for official patterns`);
|
|
1020
|
+
|
|
1021
|
+
// Use reference with generic placeholders
|
|
1022
|
+
docs.ui_library = {
|
|
1023
|
+
fallback: true,
|
|
1024
|
+
library: "Vuetify",
|
|
1025
|
+
recommendation_url: "https://vuetifyjs.com"
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
```
|
|
1029
|
+
|
|
1030
|
+
### Tech Stack Mismatch
|
|
1031
|
+
|
|
1032
|
+
```typescript
|
|
1033
|
+
// If user specifies tech stack but reference is very different
|
|
1034
|
+
if (tech_stack.framework === "Angular" && referenceDir.includes("react")) {
|
|
1035
|
+
console.warn(`⚠️ Large tech stack difference: Angular vs React reference`);
|
|
1036
|
+
console.warn(`⚠️ Generated guidelines may need manual review`);
|
|
1037
|
+
console.warn(`⚠️ Focus on framework-agnostic patterns`);
|
|
1038
|
+
}
|
|
1039
|
+
```
|
|
1040
|
+
|
|
1041
|
+
### Constitution Violations
|
|
1042
|
+
|
|
1043
|
+
```typescript
|
|
1044
|
+
// Check for hardcoded paths
|
|
1045
|
+
const violations = [];
|
|
1046
|
+
if (/\/Users\/\w+/.test(content)) {
|
|
1047
|
+
violations.push("Hardcoded user path detected");
|
|
1048
|
+
}
|
|
1049
|
+
if (/secret|password|api_key/i.test(content)) {
|
|
1050
|
+
violations.push("Potential secret detected");
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
if (violations.length > 0) {
|
|
1054
|
+
throw new Error(`Constitution violations: ${violations.join(', ')}`);
|
|
1055
|
+
}
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
---
|
|
1059
|
+
|
|
1060
|
+
## Adaptation Examples
|
|
1061
|
+
|
|
1062
|
+
### React → Vue Component Pattern
|
|
1063
|
+
|
|
1064
|
+
**React Reference**:
|
|
1065
|
+
```typescript
|
|
1066
|
+
import React from 'react';
|
|
1067
|
+
|
|
1068
|
+
interface MyComponentProps {
|
|
1069
|
+
userId: number;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
export const MyComponent: React.FC<MyComponentProps> = ({ userId }) => {
|
|
1073
|
+
return <div>User: {userId}</div>;
|
|
1074
|
+
};
|
|
1075
|
+
|
|
1076
|
+
export default MyComponent;
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
**Adapted to Vue**:
|
|
1080
|
+
```typescript
|
|
1081
|
+
<script setup lang="ts">
|
|
1082
|
+
interface Props {
|
|
1083
|
+
userId: number;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
const props = defineProps<Props>();
|
|
1087
|
+
</script>
|
|
1088
|
+
|
|
1089
|
+
<template>
|
|
1090
|
+
<div>User: {{ userId }}</div>
|
|
1091
|
+
</template>
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
### Express → Django Routing
|
|
1095
|
+
|
|
1096
|
+
**Express Reference**:
|
|
1097
|
+
```typescript
|
|
1098
|
+
router.get('/users/:id', userController.getUser);
|
|
1099
|
+
```
|
|
1100
|
+
|
|
1101
|
+
**Adapted to Django**:
|
|
1102
|
+
```python
|
|
1103
|
+
path('users/<int:id>/', views.get_user, name='get_user'),
|
|
1104
|
+
```
|
|
1105
|
+
|
|
1106
|
+
---
|
|
1107
|
+
|
|
1108
|
+
## Constitution Compliance Checklist
|
|
1109
|
+
|
|
1110
|
+
Before returning success:
|
|
1111
|
+
- [ ] SKILL.md < 500 lines
|
|
1112
|
+
- [ ] No hardcoded paths (no /Users/, ~/git/, C:\)
|
|
1113
|
+
- [ ] No secrets or credentials
|
|
1114
|
+
- [ ] skill-rules.json is valid JSON
|
|
1115
|
+
- [ ] All resources/ files have clear purpose
|
|
1116
|
+
- [ ] Progressive disclosure implemented (SKILL.md → resources/)
|
|
1117
|
+
- [ ] Code examples are syntactically correct for target framework
|
|
1118
|
+
- [ ] File patterns match actual project structure
|
|
1119
|
+
|
|
1120
|
+
---
|
|
1121
|
+
|
|
1122
|
+
## Edge Case Handling
|
|
1123
|
+
|
|
1124
|
+
### Case 1: ARCHITECTURE.md Exists But Outdated
|
|
1125
|
+
|
|
1126
|
+
```typescript
|
|
1127
|
+
async function detectOutdatedArchitecture(archData, project_root) {
|
|
1128
|
+
const warnings = [];
|
|
1129
|
+
|
|
1130
|
+
if (!archData.exists) {
|
|
1131
|
+
return { is_outdated: false, warnings: [] };
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
// Check 1: Module Structure mismatch
|
|
1135
|
+
const actualDirs = await listTopLevelDirectories(project_root);
|
|
1136
|
+
const declaredDirs = archData.module_structure.directories.map(d => d.replace(/\/$/, ''));
|
|
1137
|
+
|
|
1138
|
+
const missingInArch = actualDirs.filter(d => !declaredDirs.some(dd => dd.includes(d) || d.includes(dd)));
|
|
1139
|
+
const missingInCode = declaredDirs.filter(d => !actualDirs.some(ad => ad.includes(d) || d.includes(ad)));
|
|
1140
|
+
|
|
1141
|
+
if (missingInArch.length > 0) {
|
|
1142
|
+
warnings.push({
|
|
1143
|
+
type: 'missing_in_architecture',
|
|
1144
|
+
message: `Directories exist but not in ARCHITECTURE.md: ${missingInArch.join(', ')}`,
|
|
1145
|
+
recommendation: 'Run /core-architecture to update ARCHITECTURE.md'
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
if (missingInCode.length > 0) {
|
|
1150
|
+
warnings.push({
|
|
1151
|
+
type: 'missing_in_codebase',
|
|
1152
|
+
message: `ARCHITECTURE.md mentions directories that don't exist: ${missingInCode.join(', ')}`,
|
|
1153
|
+
recommendation: 'Remove stale entries from ARCHITECTURE.md or create missing directories'
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
// Check 2: Tech Stack mismatch (if package.json exists)
|
|
1158
|
+
try {
|
|
1159
|
+
const packageJson = JSON.parse(await Read(`${project_root}/package.json`));
|
|
1160
|
+
const declaredFrontend = archData.tech_stack.frontend?.framework;
|
|
1161
|
+
|
|
1162
|
+
if (declaredFrontend?.includes('React') && !packageJson.dependencies?.react) {
|
|
1163
|
+
warnings.push({
|
|
1164
|
+
type: 'tech_stack_mismatch',
|
|
1165
|
+
message: 'ARCHITECTURE.md declares React but package.json does not have it',
|
|
1166
|
+
recommendation: 'Update ARCHITECTURE.md or install React'
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
if (declaredFrontend?.includes('Vue') && !packageJson.dependencies?.vue) {
|
|
1171
|
+
warnings.push({
|
|
1172
|
+
type: 'tech_stack_mismatch',
|
|
1173
|
+
message: 'ARCHITECTURE.md declares Vue but package.json does not have it',
|
|
1174
|
+
recommendation: 'Update ARCHITECTURE.md or install Vue'
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
} catch (error) {
|
|
1178
|
+
// package.json doesn't exist or can't be read, skip this check
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
return {
|
|
1182
|
+
is_outdated: warnings.length > 0,
|
|
1183
|
+
warnings
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// Usage in Phase 0
|
|
1188
|
+
async function loadArchitectureDataWithValidation(project_root, target_skill) {
|
|
1189
|
+
const archData = await loadArchitectureData(project_root, target_skill);
|
|
1190
|
+
|
|
1191
|
+
if (archData.exists) {
|
|
1192
|
+
const outdateReport = await detectOutdatedArchitecture(archData, project_root);
|
|
1193
|
+
|
|
1194
|
+
if (outdateReport.is_outdated) {
|
|
1195
|
+
console.warn('⚠️ ARCHITECTURE.md may be outdated:');
|
|
1196
|
+
for (const warning of outdateReport.warnings) {
|
|
1197
|
+
console.warn(` - ${warning.message}`);
|
|
1198
|
+
console.warn(` Recommendation: ${warning.recommendation}`);
|
|
1199
|
+
}
|
|
1200
|
+
console.warn('⚠️ Proceeding with available data, but results may be inaccurate.');
|
|
1201
|
+
|
|
1202
|
+
// Add warnings to archData
|
|
1203
|
+
archData.warnings.push(...outdateReport.warnings.map(w => w.message));
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
return archData;
|
|
1208
|
+
}
|
|
1209
|
+
```
|
|
1210
|
+
|
|
1211
|
+
### Case 2: ARCHITECTURE.md Exists But No Tech Stack Info
|
|
1212
|
+
|
|
1213
|
+
```typescript
|
|
1214
|
+
function handleMissingTechStack(archData, tech_stack_from_prompt) {
|
|
1215
|
+
if (archData.exists && !archData.tech_stack.frontend && !archData.tech_stack.backend) {
|
|
1216
|
+
console.warn('⚠️ ARCHITECTURE.md exists but contains no tech stack information');
|
|
1217
|
+
console.warn('⚠️ Using tech stack from command prompt');
|
|
1218
|
+
|
|
1219
|
+
// Merge with command prompt data
|
|
1220
|
+
archData.tech_stack = tech_stack_from_prompt;
|
|
1221
|
+
archData.source = 'architecture_md + command_prompt';
|
|
1222
|
+
archData.warnings.push('ARCHITECTURE.md has no tech stack info. Using command prompt data.');
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
return archData;
|
|
1226
|
+
}
|
|
1227
|
+
```
|
|
1228
|
+
|
|
1229
|
+
### Case 3: Monorepo Detection
|
|
1230
|
+
|
|
1231
|
+
```typescript
|
|
1232
|
+
function detectMonorepo(archData) {
|
|
1233
|
+
if (!archData.exists || archData.module_structure.directories.length === 0) {
|
|
1234
|
+
return null;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
// Check for multiple app directories
|
|
1238
|
+
const appPatterns = ['apps/', 'packages/'];
|
|
1239
|
+
const detectedApps = archData.module_structure.directories.filter(dir =>
|
|
1240
|
+
appPatterns.some(pattern => dir.includes(pattern))
|
|
1241
|
+
);
|
|
1242
|
+
|
|
1243
|
+
if (detectedApps.length >= 2) {
|
|
1244
|
+
return {
|
|
1245
|
+
type: 'monorepo',
|
|
1246
|
+
apps: detectedApps,
|
|
1247
|
+
message: `Monorepo detected with ${detectedApps.length} apps: ${detectedApps.join(', ')}`,
|
|
1248
|
+
recommendation: 'Specify target app in command prompt or generate separate guidelines for each app'
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
// Check for multiple tech stacks in same layer
|
|
1253
|
+
const hasMixedFrontend = archData.module_structure.directories.some(d => d.includes('react')) &&
|
|
1254
|
+
archData.module_structure.directories.some(d => d.includes('vue'));
|
|
1255
|
+
|
|
1256
|
+
if (hasMixedFrontend) {
|
|
1257
|
+
return {
|
|
1258
|
+
type: 'mixed_tech_stack',
|
|
1259
|
+
message: 'Multiple frontend frameworks detected in directory structure',
|
|
1260
|
+
recommendation: 'Generate separate guidelines for each framework or choose primary framework'
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
return null;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
// Usage in Phase 0
|
|
1268
|
+
const monorepoInfo = detectMonorepo(archData);
|
|
1269
|
+
if (monorepoInfo) {
|
|
1270
|
+
console.warn(`⚠️ ${monorepoInfo.message}`);
|
|
1271
|
+
console.warn(`⚠️ ${monorepoInfo.recommendation}`);
|
|
1272
|
+
|
|
1273
|
+
archData.warnings.push(monorepoInfo.message);
|
|
1274
|
+
// Note: Don't throw error, just warn. Let command layer decide how to handle.
|
|
1275
|
+
}
|
|
1276
|
+
```
|
|
1277
|
+
|
|
1278
|
+
### Case 4: ARCHITECTURE.md Parsing Errors
|
|
1279
|
+
|
|
1280
|
+
```typescript
|
|
1281
|
+
function handleParsingError(error, section) {
|
|
1282
|
+
console.error(`❌ Failed to parse ${section} from ARCHITECTURE.md: ${error.message}`);
|
|
1283
|
+
|
|
1284
|
+
// Return empty/fallback data
|
|
1285
|
+
if (section === 'tech_stack') {
|
|
1286
|
+
return {};
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
if (section === 'module_structure') {
|
|
1290
|
+
return { directories: [], tree: {} };
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
if (section === 'adrs') {
|
|
1294
|
+
return [];
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
// Usage in parsers
|
|
1299
|
+
async function parseTechStackSection(content, target_skill) {
|
|
1300
|
+
try {
|
|
1301
|
+
// ... parsing logic ...
|
|
1302
|
+
} catch (error) {
|
|
1303
|
+
return handleParsingError(error, 'tech_stack');
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
---
|
|
1309
|
+
|
|
1310
|
+
## Summary of Responsibilities
|
|
1311
|
+
|
|
1312
|
+
**This agent**:
|
|
1313
|
+
- ✅ Reads reference implementations
|
|
1314
|
+
- ✅ Fetches official documentation via Context7
|
|
1315
|
+
- ✅ Adapts content to target tech stack
|
|
1316
|
+
- ✅ Generates SKILL.md + resources/
|
|
1317
|
+
- ✅ Updates skill-rules.json
|
|
1318
|
+
- ✅ Validates output
|
|
1319
|
+
- ✅ Returns comprehensive result
|
|
1320
|
+
|
|
1321
|
+
**This agent DOES NOT**:
|
|
1322
|
+
- ❌ Ask user questions
|
|
1323
|
+
- ❌ Make assumptions (all info in prompt)
|
|
1324
|
+
- ❌ Generate both frontend and backend in one call
|
|
1325
|
+
- ❌ Modify files outside .claude/skills/
|
|
1326
|
+
|
|
1327
|
+
---
|
|
1328
|
+
|
|
1329
|
+
Now execute the workflow above based on the tech stack provided in the prompt!
|