Files
gh-overlord-z-claudeshack-g…/skills/guardian/scripts/template_loader.py
2025-11-30 08:46:58 +08:00

304 lines
8.4 KiB
Python

#!/usr/bin/env python3
"""
Guardian Template Loader
Loads and applies Guardian review/planning templates for consistent,
structured agent interactions.
Usage:
# List available templates
python template_loader.py --list
# Load a template
python template_loader.py --template security_review
# Load template and apply to context
python template_loader.py --template security_review --file auth.py --output prompt.txt
# Create custom template
python template_loader.py --create my_review --based-on security_review
"""
import os
import sys
import json
import argparse
from pathlib import Path
from typing import Dict, List, Optional, Any
def find_templates_dir() -> Path:
"""Find the Guardian Templates directory."""
# First try relative to this script
script_dir = Path(__file__).parent
templates_dir = script_dir.parent / 'Templates'
if templates_dir.exists():
return templates_dir
# Try from current directory
templates_dir = Path.cwd() / 'skills' / 'guardian' / 'Templates'
if templates_dir.exists():
return templates_dir
raise FileNotFoundError("Guardian Templates directory not found")
def list_templates() -> List[Dict[str, str]]:
"""List all available Guardian templates.
Returns:
List of template metadata dictionaries
"""
templates_dir = find_templates_dir()
templates = []
for template_file in templates_dir.glob('*.json'):
try:
with open(template_file, 'r', encoding='utf-8') as f:
template = json.load(f)
templates.append({
'name': template.get('name', template_file.stem),
'description': template.get('description', 'No description'),
'task_type': template.get('task_type', 'unknown'),
'file': str(template_file)
})
except (json.JSONDecodeError, OSError, IOError):
continue
return templates
def load_template(template_name: str) -> Dict[str, Any]:
"""Load a Guardian template by name.
Args:
template_name: Name of the template (with or without .json extension)
Returns:
Template configuration dictionary
"""
templates_dir = find_templates_dir()
# Remove .json extension if provided
if template_name.endswith('.json'):
template_name = template_name[:-5]
template_file = templates_dir / f"{template_name}.json"
if not template_file.exists():
raise FileNotFoundError(f"Template not found: {template_name}")
try:
with open(template_file, 'r', encoding='utf-8') as f:
return json.load(f)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid template JSON: {e}")
def apply_template_to_context(
template: Dict[str, Any],
context: str
) -> str:
"""Apply a template to extracted context.
Args:
template: Template configuration
context: Extracted minimal context
Returns:
Formatted agent prompt
"""
prompt_template = template.get('agent_prompt_template', '')
# Replace context placeholder
prompt = prompt_template.replace('{context}', context)
return prompt
def get_template_config(template: Dict[str, Any]) -> Dict[str, Any]:
"""Extract configuration parameters from template.
Args:
template: Template configuration
Returns:
Configuration dictionary for context_filter.py
"""
return {
'task_type': template.get('task_type', 'review'),
'focus': template.get('focus', ''),
'oracle_categories': template.get('oracle_categories', ['patterns', 'gotchas']),
'oracle_tags': template.get('oracle_tags_required', []),
'max_patterns': template.get('max_oracle_patterns', 5),
'max_gotchas': template.get('max_oracle_gotchas', 5),
'validation_rules': template.get('validation_rules', {})
}
def create_custom_template(
name: str,
base_template: Optional[str] = None,
description: str = "",
task_type: str = "review"
) -> Path:
"""Create a new custom template.
Args:
name: Name for the new template
base_template: Optional template to base this on
description: Template description
task_type: Type of task (review, plan, debug)
Returns:
Path to the created template file
"""
templates_dir = find_templates_dir()
if base_template:
# Load base template
base = load_template(base_template)
new_template = base.copy()
new_template['name'] = name
if description:
new_template['description'] = description
else:
# Create minimal template
new_template = {
"name": name,
"description": description or f"Custom {task_type} template",
"task_type": task_type,
"focus": "",
"agent_prompt_template": "You are a READ-ONLY code reviewer for Guardian.\n\nCRITICAL CONSTRAINTS:\n- DO NOT modify any files\n- ONLY read and analyze\n\n{context}\n\nReturn suggestions as JSON array.",
"oracle_categories": ["patterns", "gotchas"],
"oracle_tags_required": [],
"max_oracle_patterns": 5,
"max_oracle_gotchas": 5,
"always_include_files": [],
"validation_rules": {
"min_confidence": 0.5,
"block_contradictions": true
}
}
# Save template
template_file = templates_dir / f"{name}.json"
with open(template_file, 'w', encoding='utf-8') as f:
json.dump(new_template, f, indent=2)
return template_file
def main():
parser = argparse.ArgumentParser(
description='Guardian template loader and manager',
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
'--list',
action='store_true',
help='List all available templates'
)
parser.add_argument(
'--template',
help='Template name to load'
)
parser.add_argument(
'--file',
help='File to apply template to (used with --output)'
)
parser.add_argument(
'--output',
help='Output file for generated prompt'
)
parser.add_argument(
'--create',
help='Create a new custom template with this name'
)
parser.add_argument(
'--based-on',
help='Base the new template on an existing one'
)
parser.add_argument(
'--description',
help='Description for new template'
)
parser.add_argument(
'--show-config',
action='store_true',
help='Show template configuration (for use with context_filter.py)'
)
args = parser.parse_args()
# List templates
if args.list:
templates = list_templates()
print("Available Guardian Templates:")
print("=" * 60)
for template in templates:
print(f"\nName: {template['name']}")
print(f" Type: {template['task_type']}")
print(f" Description: {template['description']}")
print(f" File: {template['file']}")
print("\n" + "=" * 60)
print(f"Total: {len(templates)} templates")
sys.exit(0)
# Create template
if args.create:
template_file = create_custom_template(
args.create,
args.based_on,
args.description or "",
"review"
)
print(f"Created template: {template_file}")
print("Edit this file to customize your template")
sys.exit(0)
# Load template
if args.template:
template = load_template(args.template)
if args.show_config:
config = get_template_config(template)
print(json.dumps(config, indent=2))
sys.exit(0)
if args.output and args.file:
# Apply template to file
# This would integrate with context_filter.py
print(f"Applying template '{args.template}' to {args.file}...")
print(f"Output will be saved to: {args.output}")
print("\nTo apply this template:")
print(f" 1. Run context_filter.py with template config")
print(f" 2. Apply template to extracted context")
print(f" 3. Save to {args.output}")
else:
# Just show template
print(json.dumps(template, indent=2))
sys.exit(0)
parser.print_help()
sys.exit(1)
if __name__ == '__main__':
main()