# discussion-moderator - Discussion facilitator and orchestrator # Usage: cat discussion.md | discussion-moderator --templates-dir templates name: discussion-moderator description: Discussion facilitator and orchestrator category: Discussion meta: display_name: AI-Moderator alias: moderator type: voting expertise: - Discussion facilitation - Conflict resolution - Summarization - Progress tracking concerns: - "Is the discussion productive?" - "Are all viewpoints represented?" - "Are we ready to move forward?" arguments: - flag: --callout variable: callout default: "" description: Specific question or @mention context - flag: --templates-dir variable: templates_dir default: "templates" description: Path to templates directory - flag: --participants variable: participants default: "architect,security,pragmatist" description: Comma-separated list of expected participants - flag: --log-file variable: log_file default: "" description: Path to log file for progress updates steps: # Step 1: Analyze discussion state and read template - type: code code: | import re import json import os from collections import Counter # Extract metadata from discussion phase_match = re.search(r'', input, re.IGNORECASE) template_match = re.search(r'', input, re.IGNORECASE) current_phase = phase_match.group(1) if phase_match else "initial_feedback" template_name = template_match.group(1) if template_match else "feature" # Try to read template file for phase context template_path = os.path.join(templates_dir, template_name + ".yaml") phase_goal = "Facilitate the discussion" phase_instructions = "Guide participants through the discussion." next_phase = None if os.path.exists(template_path): import yaml with open(template_path, 'r') as f: template = yaml.safe_load(f) phases = template.get("phases", {}) phase_info = phases.get(current_phase, {}) phase_goal = phase_info.get("goal", phase_goal) phase_instructions = phase_info.get("instructions", phase_instructions) next_phase = phase_info.get("next_phase", None) phase_context = "Current Phase: " + current_phase + "\n\n" phase_context += "Phase Goal: " + phase_goal + "\n\n" phase_context += "Phase Instructions:\n" + phase_instructions if next_phase: phase_context += "\n\nNext Phase: " + next_phase # Extract votes votes = {} for match in re.finditer(r'Name:\s*(.+?)\n.*?VOTE:\s*(READY|CHANGES|REJECT)', input, re.DOTALL | re.IGNORECASE): author = match.group(1).strip() vote = match.group(2).upper() votes[author] = vote vote_counts = Counter(votes.values()) # Extract mentions mentions = set(re.findall(r'@(\w+)', input)) # Get responders responders = set() for match in re.finditer(r'^Name:\s*(.+?)$', input, re.MULTILINE): responders.add(match.group(1).strip().lower().replace("ai-", "")) # Expected participants (explicit loop to avoid exec() scope issues) expected = set() for p in participants.split(','): expected.add(p.strip()) pending = expected - responders # Questions and concerns (explicit loops to avoid exec() scope issues) questions = [] for m in re.finditer(r'^(?:Q|QUESTION):\s*(.+)$', input, re.MULTILINE | re.IGNORECASE): questions.append(m.group(1)) concerns = [] for m in re.finditer(r'^CONCERN:\s*(.+)$', input, re.MULTILINE | re.IGNORECASE): concerns.append(m.group(1)) analysis = json.dumps({ "votes": votes, "vote_counts": dict(vote_counts), "total_votes": sum(vote_counts.values()), "pending_participants": list(pending), "all_responded": len(pending) == 0, "open_questions": questions, "concerns": concerns, "current_phase": current_phase, "next_phase": next_phase }) output_var: analysis, phase_context # Step 2: Generate moderation response - type: prompt prompt: | You are AI-Moderator, responsible for keeping discussions productive and on-track. ## Your Role - Summarize the current state of the discussion - Identify who still needs to respond - Note open questions and concerns - Suggest next steps - Determine if the discussion should advance to the next phase ## Phase Context {phase_context} ## Discussion Analysis {analysis} ## Full Discussion {input} Based on this analysis: 1. Summarize what has been discussed so far 2. List who still needs to respond (use @mentions) 3. Highlight any unresolved questions or concerns 4. Recommend whether to advance to the next phase based on the phase instructions ## Response Format Respond with valid JSON only: {{ "comment": "Your moderation comment in markdown. Use @mentions for pending participants.", "vote": null, "advance_phase": true or false, "pending_participants": ["list", "of", "aliases"] }} As moderator, you typically don't vote (vote: null). Your role is to facilitate. If there's nothing to moderate yet, respond: {{"sentinel": "NO_RESPONSE"}} provider: claude-sonnet output_var: response output: "{response}"