Initial commit
This commit is contained in:
commit
430ae2e266
56 files changed
+10826
No files matched your search
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Template Compliance Checker for Prompt Library
|
||||
|
||||
This script validates that all prompt files follow the standard template structure
|
||||
and reports any missing or incorrectly formatted sections.
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
# Required sections in the correct order
|
||||
REQUIRED_SECTIONS = [
|
||||
"Description",
|
||||
"Usage",
|
||||
"Prompt",
|
||||
"Example Input",
|
||||
"Example Output",
|
||||
"Variations",
|
||||
"Tips",
|
||||
"Related Prompts",
|
||||
"Tags",
|
||||
]
|
||||
|
||||
|
||||
def extract_sections(content: str) -> Dict[str, str]:
|
||||
"""Extract sections from markdown content."""
|
||||
sections = {}
|
||||
current_section = None
|
||||
current_content = []
|
||||
|
||||
lines = content.split("\n")
|
||||
|
||||
for line in lines:
|
||||
# Check if this is a section header (## Section Name)
|
||||
section_match = re.match(r"^## (.+)$", line.strip())
|
||||
if section_match:
|
||||
# Save previous section
|
||||
if current_section:
|
||||
sections[current_section] = "\n".join(current_content).strip()
|
||||
|
||||
# Start new section
|
||||
current_section = section_match.group(1)
|
||||
current_content = []
|
||||
else:
|
||||
# Add content to current section
|
||||
if current_section:
|
||||
current_content.append(line)
|
||||
|
||||
# Save last section
|
||||
if current_section:
|
||||
sections[current_section] = "\n".join(current_content).strip()
|
||||
|
||||
return sections
|
||||
|
||||
|
||||
def validate_prompt_file(file_path: Path) -> Tuple[bool, List[str]]:
|
||||
"""Validate a single prompt file against the template."""
|
||||
errors = []
|
||||
|
||||
try:
|
||||
with open(file_path, encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
except Exception as e:
|
||||
return False, [f"Could not read file: {e}"]
|
||||
|
||||
# Extract sections
|
||||
sections = extract_sections(content)
|
||||
|
||||
# Check for required sections
|
||||
missing_sections = []
|
||||
for required_section in REQUIRED_SECTIONS:
|
||||
if required_section not in sections:
|
||||
missing_sections.append(required_section)
|
||||
elif not sections[required_section].strip():
|
||||
errors.append(f"Section '{required_section}' is empty")
|
||||
|
||||
if missing_sections:
|
||||
errors.append(f"Missing required sections: {', '.join(missing_sections)}")
|
||||
|
||||
# Check section order
|
||||
found_sections = [s for s in REQUIRED_SECTIONS if s in sections]
|
||||
section_headers = []
|
||||
|
||||
for line in content.split("\n"):
|
||||
section_match = re.match(r"^## (.+)$", line.strip())
|
||||
if section_match:
|
||||
section_name = section_match.group(1)
|
||||
if section_name in REQUIRED_SECTIONS:
|
||||
section_headers.append(section_name)
|
||||
|
||||
if section_headers != found_sections:
|
||||
errors.append(
|
||||
f"Sections are not in the correct order. Expected: {', '.join(REQUIRED_SECTIONS)}"
|
||||
)
|
||||
|
||||
# Validate specific section content
|
||||
if "Tags" in sections:
|
||||
tags_content = sections["Tags"].strip()
|
||||
if not tags_content.startswith("`") or not tags_content.endswith("`"):
|
||||
errors.append("Tags section should be formatted as code with backticks")
|
||||
|
||||
if "Prompt" in sections:
|
||||
prompt_content = sections["Prompt"].strip()
|
||||
if not prompt_content.startswith("```") or not prompt_content.endswith("```"):
|
||||
errors.append(
|
||||
"Prompt section should contain a properly formatted code block"
|
||||
)
|
||||
|
||||
return len(errors) == 0, errors
|
||||
|
||||
|
||||
def find_prompt_files(root_path: Path) -> List[Path]:
|
||||
"""Find all prompt markdown files."""
|
||||
prompt_files = []
|
||||
|
||||
# Skip template files and root-level docs
|
||||
skip_patterns = [
|
||||
"template",
|
||||
"README",
|
||||
"CONTRIBUTING",
|
||||
"SECURITY",
|
||||
"LICENSE",
|
||||
]
|
||||
|
||||
for md_file in root_path.rglob("*.md"):
|
||||
# Skip if it's in .github, templates, or examples directory
|
||||
excluded_dirs = [".github", "templates", "examples"]
|
||||
if any(excluded_dir in md_file.parts for excluded_dir in excluded_dirs):
|
||||
continue
|
||||
|
||||
# Skip if filename contains skip patterns
|
||||
if any(pattern.lower() in md_file.name.lower() for pattern in skip_patterns):
|
||||
continue
|
||||
|
||||
prompt_files.append(md_file)
|
||||
|
||||
return sorted(prompt_files)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to run compliance checks."""
|
||||
root_path = Path(".")
|
||||
|
||||
print("Prompt Library Template Compliance Checker")
|
||||
print("=" * 50)
|
||||
|
||||
prompt_files = find_prompt_files(root_path)
|
||||
|
||||
if not prompt_files:
|
||||
print("ERROR: No prompt files found!")
|
||||
return 1
|
||||
|
||||
print(f"Found {len(prompt_files)} prompt files to validate")
|
||||
print()
|
||||
|
||||
total_files = len(prompt_files)
|
||||
valid_files = 0
|
||||
|
||||
for file_path in prompt_files:
|
||||
relative_path = file_path.relative_to(root_path)
|
||||
is_valid, errors = validate_prompt_file(file_path)
|
||||
|
||||
if is_valid:
|
||||
print(f"PASS: {relative_path}")
|
||||
valid_files += 1
|
||||
else:
|
||||
print(f"FAIL: {relative_path}")
|
||||
for error in errors:
|
||||
print(f" * {error}")
|
||||
print()
|
||||
|
||||
print("=" * 50)
|
||||
print(f"Summary: {valid_files}/{total_files} files passed validation")
|
||||
|
||||
if valid_files == total_files:
|
||||
print("SUCCESS: All prompt files are compliant with the template!")
|
||||
return 0
|
||||
else:
|
||||
print(f"WARNING: {total_files - valid_files} files need attention")
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple test runner for prompt library validation.
|
||||
This script runs basic checks that can be automated in CI/CD.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def run_markdown_lint():
|
||||
"""Run markdownlint on all markdown files."""
|
||||
print("Running markdown lint checks...")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["markdownlint", "**/*.md", "--config", ".markdownlint.json"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=Path.cwd(),
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
print("PASS: Markdown lint passed")
|
||||
return True
|
||||
else:
|
||||
print("FAIL: Markdown lint failed:")
|
||||
print(result.stdout)
|
||||
print(result.stderr)
|
||||
return False
|
||||
except FileNotFoundError:
|
||||
print("SKIP: markdownlint not found, skipping")
|
||||
return True
|
||||
|
||||
|
||||
def run_template_compliance():
|
||||
"""Run template compliance checker."""
|
||||
print("Running template compliance checks...")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["python", "scripts/check-template-compliance.py"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=Path.cwd(),
|
||||
)
|
||||
|
||||
print(result.stdout)
|
||||
if result.stderr:
|
||||
print(result.stderr)
|
||||
|
||||
return result.returncode == 0
|
||||
except Exception as e:
|
||||
print(f"FAIL: Template compliance check failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def check_required_files():
|
||||
"""Check that all required files exist."""
|
||||
print("Checking required files...")
|
||||
required_files = [
|
||||
"README.md",
|
||||
"CONTRIBUTING.md",
|
||||
"LICENSE",
|
||||
"SECURITY.md",
|
||||
".markdownlint.json",
|
||||
".markdown-link-check.json",
|
||||
".spellcheck.yml",
|
||||
"scripts/check-template-compliance.py",
|
||||
]
|
||||
|
||||
missing_files = []
|
||||
for file_path in required_files:
|
||||
if not Path(file_path).exists():
|
||||
missing_files.append(file_path)
|
||||
|
||||
if missing_files:
|
||||
print(f"FAIL: Missing required files: {', '.join(missing_files)}")
|
||||
return False
|
||||
else:
|
||||
print("PASS: All required files present")
|
||||
return True
|
||||
|
||||
|
||||
def check_directory_structure():
|
||||
"""Check that expected directory structure exists."""
|
||||
print("Checking directory structure...")
|
||||
required_dirs = [
|
||||
"development",
|
||||
"writing",
|
||||
"business",
|
||||
"analysis",
|
||||
"creative",
|
||||
"education",
|
||||
"productivity",
|
||||
"templates",
|
||||
"examples",
|
||||
"scripts",
|
||||
".github",
|
||||
]
|
||||
|
||||
missing_dirs = []
|
||||
for dir_path in required_dirs:
|
||||
if not Path(dir_path).is_dir():
|
||||
missing_dirs.append(dir_path)
|
||||
|
||||
if missing_dirs:
|
||||
print(f"FAIL: Missing required directories: {', '.join(missing_dirs)}")
|
||||
return False
|
||||
else:
|
||||
print("PASS: All required directories present")
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
"""Run all validation checks."""
|
||||
print("Prompt Library Validation Suite")
|
||||
print("=" * 40)
|
||||
|
||||
checks = [
|
||||
check_required_files,
|
||||
check_directory_structure,
|
||||
run_template_compliance,
|
||||
run_markdown_lint,
|
||||
]
|
||||
|
||||
passed = 0
|
||||
total = len(checks)
|
||||
|
||||
for check in checks:
|
||||
if check():
|
||||
passed += 1
|
||||
print()
|
||||
|
||||
print("=" * 40)
|
||||
print(f"Results: {passed}/{total} checks passed")
|
||||
|
||||
if passed == total:
|
||||
print("SUCCESS: All validation checks passed!")
|
||||
return 0
|
||||
else:
|
||||
print("FAIL: Some validation checks failed")
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple test runner for prompt library validation.
|
||||
This script runs basic checks that can be automated in CI/CD.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def run_markdown_lint():
|
||||
"""Run markdownlint on all markdown files."""
|
||||
print("🔍 Running markdown lint checks...")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["markdownlint", "**/*.md", "--config", ".markdownlint.json"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=Path.cwd(),
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
print("✅ Markdown lint passed")
|
||||
return True
|
||||
else:
|
||||
print("❌ Markdown lint failed:")
|
||||
print(result.stdout)
|
||||
print(result.stderr)
|
||||
return False
|
||||
except FileNotFoundError:
|
||||
print("⚠️ markdownlint not found, skipping")
|
||||
return True
|
||||
|
||||
|
||||
def run_template_compliance():
|
||||
"""Run template compliance checker."""
|
||||
print("🔍 Running template compliance checks...")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["python", "scripts/check-template-compliance.py"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=Path.cwd(),
|
||||
)
|
||||
|
||||
print(result.stdout)
|
||||
if result.stderr:
|
||||
print(result.stderr)
|
||||
|
||||
return result.returncode == 0
|
||||
except Exception as e:
|
||||
print(f"❌ Template compliance check failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def check_required_files():
|
||||
"""Check that all required files exist."""
|
||||
print("🔍 Checking required files...")
|
||||
required_files = [
|
||||
"README.md",
|
||||
"CONTRIBUTING.md",
|
||||
"LICENSE",
|
||||
"SECURITY.md",
|
||||
".markdownlint.json",
|
||||
".markdown-link-check.json",
|
||||
".spellcheck.yml",
|
||||
"scripts/check-template-compliance.py",
|
||||
]
|
||||
|
||||
missing_files = []
|
||||
for file_path in required_files:
|
||||
if not Path(file_path).exists():
|
||||
missing_files.append(file_path)
|
||||
|
||||
if missing_files:
|
||||
print(f"❌ Missing required files: {', '.join(missing_files)}")
|
||||
return False
|
||||
else:
|
||||
print("✅ All required files present")
|
||||
return True
|
||||
|
||||
|
||||
def check_directory_structure():
|
||||
"""Check that expected directory structure exists."""
|
||||
print("🔍 Checking directory structure...")
|
||||
required_dirs = [
|
||||
"development",
|
||||
"writing",
|
||||
"business",
|
||||
"analysis",
|
||||
"creative",
|
||||
"education",
|
||||
"productivity",
|
||||
"templates",
|
||||
"examples",
|
||||
"scripts",
|
||||
".github",
|
||||
]
|
||||
|
||||
missing_dirs = []
|
||||
for dir_path in required_dirs:
|
||||
if not Path(dir_path).is_dir():
|
||||
missing_dirs.append(dir_path)
|
||||
|
||||
if missing_dirs:
|
||||
print(f"❌ Missing required directories: {', '.join(missing_dirs)}")
|
||||
return False
|
||||
else:
|
||||
print("✅ All required directories present")
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
"""Run all validation checks."""
|
||||
print("🚀 Prompt Library Validation Suite")
|
||||
print("=" * 40)
|
||||
|
||||
checks = [
|
||||
check_required_files,
|
||||
check_directory_structure,
|
||||
run_template_compliance,
|
||||
run_markdown_lint,
|
||||
]
|
||||
|
||||
passed = 0
|
||||
total = len(checks)
|
||||
|
||||
for check in checks:
|
||||
if check():
|
||||
passed += 1
|
||||
print()
|
||||
|
||||
print("=" * 40)
|
||||
print(f"📊 Results: {passed}/{total} checks passed")
|
||||
|
||||
if passed == total:
|
||||
print("🎉 All validation checks passed!")
|
||||
return 0
|
||||
else:
|
||||
print("❌ Some validation checks failed")
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user