Skip to main content

scripts-template-expert

""" Template Expert - Type Expert for Template Documents

Identifies template files - reusable document structures with placeholders that serve as starting points for creating new documents.

Key signals:

  • TEMPLATE in filename
  • Placeholder patterns ([PLACEHOLDER], {{placeholder}}, )
  • "Fill in" or "Replace" instructions
  • Generic/abstract content
  • Section headers with placeholder content """

import re from typing import Dict, List from pathlib import Path

import sys sys.path.insert(0, str(Path(file).parent.parent)) from core.models import Document, AnalystVote

from .base import TypeExpert, TypeAnalysis, ContentEnhancement

class TemplateExpert(TypeExpert): """Expert for identifying template documents."""

EXPERT_TYPE = 'template'

# Placeholder patterns
PLACEHOLDER_PATTERNS = [
r'\[[\w\s-]+\]', # [PLACEHOLDER]
r'\{\{[\w\s-]+\}\}', # {{placeholder}}
r'<[\w\s-]+>', # <placeholder>
r'\[TODO:.*?\]', # [TODO: ...]
r'\[INSERT.*?\]', # [INSERT ...]
r'\[REPLACE.*?\]', # [REPLACE ...]
r'\[YOUR.*?\]', # [YOUR ...]
r'___+', # Blank lines
r'\.\.\.', # Ellipsis as placeholder
]

# Template instruction patterns
INSTRUCTION_PATTERNS = [
r'fill\s+(in|out)',
r'replace\s+(with|this)',
r'update\s+this',
r'customize\s+(this|as)',
r'modify\s+as\s+needed',
r'add\s+your',
r'insert\s+your',
r'example:?\s*$',
r'template\s+(for|to)',
]

def analyze(self, document: Document, analyst_votes: List[AnalystVote]) -> TypeAnalysis:
"""Analyze if document is a template."""
content = document.content
content_lower = content.lower()
evidence_for = []
evidence_against = []
missing_signals = []

# Check filename - strongest signal
filename = Path(document.path).stem.upper()
is_template_file = 'TEMPLATE' in filename
if is_template_file:
evidence_for.append(f"Filename contains TEMPLATE: {Path(document.path).name}")

# Check frontmatter
if re.search(r'type:\s*template', content_lower[:500]):
evidence_for.append("Frontmatter indicates template type")

# Count placeholders
placeholder_count = 0
for pattern in self.PLACEHOLDER_PATTERNS:
matches = re.findall(pattern, content, re.IGNORECASE)
placeholder_count += len(matches)
if matches and len(evidence_for) < 5:
evidence_for.append(f"Has placeholder pattern: '{matches[0][:30]}'")

if placeholder_count > 5:
evidence_for.append(f"High placeholder density: {placeholder_count} placeholders")

# Check for instruction patterns
instruction_count = 0
for pattern in self.INSTRUCTION_PATTERNS:
if re.search(pattern, content_lower):
instruction_count += 1
if instruction_count <= 2:
evidence_for.append(f"Has template instruction: '{pattern}'")

# Check for "How to Use" section (common in templates)
if re.search(r'#+\s*(how\s+to\s+use|usage|instructions)', content_lower):
evidence_for.append("Has 'How to Use' section")

# Check for generic/abstract content
if re.search(r'(this\s+template|use\s+this\s+as|starting\s+point)', content_lower):
evidence_for.append("Contains template self-reference language")

# Evidence against
if re.search(r'you\s+are\s+(a|an)\s+\w+\s+agent', content_lower):
evidence_against.append("Has agent persona - might be agent doc")
if placeholder_count < 2 and not is_template_file:
evidence_against.append("Low placeholder count for a template")

# Check if content is too specific/filled in
specific_patterns = [
r'\d{4}-\d{2}-\d{2}', # Specific dates
r'version:\s*\d+\.\d+\.\d+', # Specific versions
]
specific_count = sum(1 for p in specific_patterns if re.search(p, content))
if specific_count > 3:
evidence_against.append("Contains specific values - might be filled document")

# Missing signals
if placeholder_count < 3:
missing_signals.append('placeholders')
if instruction_count == 0:
missing_signals.append('usage_instructions')
if not re.search(r'#+\s*(how\s+to\s+use|usage)', content_lower):
missing_signals.append('how_to_use_section')

# Calculate confidence
confidence = self._calculate_confidence(
is_template_file, evidence_for, evidence_against,
placeholder_count, instruction_count
)

is_template = confidence > 0.6 or (is_template_file and confidence > 0.4)

# Determine which analysts to sway
analysts_to_sway = {}
for vote in analyst_votes:
if vote.classification != 'template' and is_template:
analysts_to_sway[vote.agent] = f"Document is template, not {vote.classification}"

return TypeAnalysis(
is_this_type=is_template,
confidence=confidence,
evidence_for=evidence_for,
evidence_against=evidence_against,
semantic_purpose="Provide reusable document structure with placeholders" if is_template else "Unknown",
missing_signals=missing_signals,
recommended_changes=[],
analysts_to_sway=analysts_to_sway,
expert_type=self.EXPERT_TYPE
)

def _calculate_confidence(
self,
is_template_file: bool,
evidence_for: List[str],
evidence_against: List[str],
placeholder_count: int,
instruction_count: int
) -> float:
"""Calculate confidence score."""
# Filename is strong signal
base = 0.6 if is_template_file else 0.15

# Placeholders are key indicator
base += min(0.25, placeholder_count * 0.03)

# Instructions help
base += min(0.1, instruction_count * 0.05)

# Other evidence
base += min(0.15, len(evidence_for) * 0.03)

# Subtract for counter-evidence
base -= len(evidence_against) * 0.12

return max(0.0, min(0.98, base))

def generate_enhancements(
self,
document: Document,
analysis: TypeAnalysis
) -> List[ContentEnhancement]:
"""Generate enhancements for template documents."""
enhancements = []

for signal in analysis.missing_signals:
if signal == 'placeholders':
enhancements.append(ContentEnhancement(
signal_type='placeholders',
content=self._generate_placeholder_examples(),
insertion_point='content',
reason='Templates need clear placeholder patterns',
expected_analyst_boost={'pattern': 0.2, 'content': 0.15},
priority=1
))
elif signal == 'usage_instructions':
enhancements.append(ContentEnhancement(
signal_type='usage_instructions',
content=self._generate_usage_instructions(),
insertion_point='after_title',
reason='Templates should include usage instructions',
expected_analyst_boost={'content': 0.15, 'semantic': 0.1},
priority=1
))
elif signal == 'how_to_use_section':
enhancements.append(ContentEnhancement(
signal_type='how_to_use_section',
content=self._generate_how_to_use(),
insertion_point='start',
reason='Templates need How to Use section',
expected_analyst_boost={'structural': 0.15, 'content': 0.1},
priority=2
))

return enhancements

def _generate_placeholder_examples(self) -> str:
"""Generate placeholder pattern examples."""
return '''
  • [PROJECT_NAME] - Your project name

  • [DESCRIPTION] - Brief description

  • [AUTHOR] - Author name

  • [DATE] - Current date (YYYY-MM-DD) '''

    def _generate_usage_instructions(self) -> str: """Generate usage instructions.""" return '''> Template Usage:

  1. Copy this template to your target location
  2. Replace all [PLACEHOLDER] values with your content
  3. Remove this instruction block when done
  4. Customize sections as needed for your use case

'''

def _generate_how_to_use(self) -> str:
"""Generate how to use section."""
return '''## How to Use This Template
  1. Copy this template to your desired location
  2. Rename the file appropriately
  3. Replace all placeholder values (marked with [BRACKETS])
  4. Customize sections as needed
  5. Remove these instructions when complete

Placeholders

PlaceholderDescription
[TITLE]Document title
[DESCRIPTION]Brief description
[CONTENT]Main content

'''