# discussion-validator - Validate discussion format and check for issues # Usage: cat discussion.md | discussion-validator | jq . name: discussion-validator description: Validate discussion format and check for issues category: Discussion steps: - type: code code: | import re import json issues = [] warnings = [] # Check for DISCUSSION marker if not re.search(r'', input, re.IGNORECASE): issues.append("Missing marker") # Check for required headers required_headers = ['Title', 'Phase', 'Status'] for header in required_headers: if not re.search(rf'', input, re.IGNORECASE): issues.append(f"Missing required header: {header}") # Check for valid phase phase_match = re.search(r'', input, re.IGNORECASE) if phase_match: valid_phases = [ 'initial_feedback', 'detailed_review', 'consensus_vote', 'final_vote', 'signoff', 'completed', 'proposal', 'review' ] phase = phase_match.group(1) # Build lowercase list explicitly to avoid exec() scope issues valid_phases_lower = [] for p in valid_phases: valid_phases_lower.append(p.lower()) if phase.lower() not in valid_phases_lower: warnings.append(f"Unknown phase: {phase}") # Check for valid status status_match = re.search(r'', input, re.IGNORECASE) if status_match: valid_statuses = [ 'OPEN', 'PROPOSED', 'READY_FOR_DESIGN', 'READY_FOR_IMPLEMENTATION', 'READY_FOR_TESTING', 'CLOSED', 'REJECTED' ] status = status_match.group(1).upper() if status not in valid_statuses: warnings.append(f"Unknown status: {status}") # Check for orphaned mentions (mentioned but no response) mentions = set(re.findall(r'@(\w+)', input)) # Get responders from Name: lines responders = set() for match in re.finditer(r'^Name:\s*(?:AI-)?(\w+)', input, re.MULTILINE | re.IGNORECASE): responders.add(match.group(1).lower()) pending = mentions - responders - {'all'} if pending: warnings.append(f"Pending responses from: {', '.join(sorted(pending))}") # Check for empty comment blocks for match in re.finditer(r'^---\s*\n\s*Name:\s*(.+?)\n\s*(?=^---|\Z)', input, re.MULTILINE): author = match.group(1).strip() warnings.append(f"Empty comment block from: {author}") # Check for duplicate votes from same author votes = {} for match in re.finditer(r'^---\s*\nName:\s*(.+?)\n.*?VOTE:\s*(READY|CHANGES|REJECT)', input, re.MULTILINE | re.DOTALL | re.IGNORECASE): author = match.group(1).strip() vote = match.group(2).upper() if author in votes and votes[author] != vote: warnings.append(f"Multiple different votes from {author}: {votes[author]} -> {vote}") votes[author] = vote validation = json.dumps({ "valid": len(issues) == 0, "issues": issues, "warnings": warnings, "metadata_found": { "phase": phase_match.group(1) if phase_match else None, "status": status_match.group(1) if status_match else None } }, indent=2) output_var: validation output: "{validation}"