From a39103c2ca2af7e67b068fe043f349a689b423b5 Mon Sep 17 00:00:00 2001 From: rob Date: Wed, 24 Dec 2025 01:28:57 -0400 Subject: [PATCH] Add missing participant SmartTools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added 7 additional AI participants: - discussion-backend: Backend/API perspective - discussion-designer: Visual/UX design perspective - discussion-devops: Infrastructure/deployment perspective - discussion-frontend: Frontend/UI perspective - discussion-performance: Performance/optimization perspective - discussion-qa: Testing/quality perspective - discussion-ux: User experience perspective These are now bundled with the project and will be installed automatically when building the Docker container. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- smarttools/discussion-backend/config.yaml | 141 +++++++++++++++++ smarttools/discussion-designer/config.yaml | 141 +++++++++++++++++ smarttools/discussion-devops/config.yaml | 143 ++++++++++++++++++ smarttools/discussion-frontend/config.yaml | 141 +++++++++++++++++ smarttools/discussion-performance/config.yaml | 126 +++++++++++++++ smarttools/discussion-qa/config.yaml | 135 +++++++++++++++++ smarttools/discussion-ux/config.yaml | 141 +++++++++++++++++ 7 files changed, 968 insertions(+) create mode 100644 smarttools/discussion-backend/config.yaml create mode 100644 smarttools/discussion-designer/config.yaml create mode 100644 smarttools/discussion-devops/config.yaml create mode 100644 smarttools/discussion-frontend/config.yaml create mode 100644 smarttools/discussion-performance/config.yaml create mode 100644 smarttools/discussion-qa/config.yaml create mode 100644 smarttools/discussion-ux/config.yaml diff --git a/smarttools/discussion-backend/config.yaml b/smarttools/discussion-backend/config.yaml new file mode 100644 index 0000000..b9f659d --- /dev/null +++ b/smarttools/discussion-backend/config.yaml @@ -0,0 +1,141 @@ +name: discussion-backend +description: Backend development specialist participant for discussions +category: Discussion +meta: + display_name: AI-Backend + alias: backend + type: voting + expertise: + - API design + - Database design + - Server architecture + - Authentication/Authorization + - Data modeling + - Microservices + - Message queues + concerns: + - Is the API design RESTful/consistent? + - What's the data model? + - How do we handle transactions? + - Is authentication properly implemented? + voice: en-AU-Neural2-B + provider: codex + color: + - 100 + - 200 + - 100 +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: --diagrams-dir + variable: diagrams_dir + default: diagrams + description: Path to save diagrams +- flag: --log-file + variable: log_file + default: '' + description: Path to log file for progress updates +steps: +- type: code + code: "import re\nimport os\n\nphase_match = re.search(r'', input, re.IGNORECASE)\ntemplate_match = re.search(r'', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\ + \ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\ + \ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\ + \ template_name + \".yaml\")\nphase_goal = \"Provide backend feedback\"\nphase_instructions\ + \ = \"Review the proposal for backend implementation concerns.\"\n\nif os.path.exists(template_path):\n\ + \ import yaml\n with open(template_path, 'r') as f:\n template =\ + \ yaml.safe_load(f)\n phases = template.get(\"phases\", {})\n phase_info\ + \ = phases.get(current_phase, {})\n phase_goal = phase_info.get(\"goal\", phase_goal)\n\ + \ phase_instructions = phase_info.get(\"instructions\", phase_instructions)\n\ + \nphase_context = \"Current Phase: \" + current_phase + \"\\n\"\nphase_context\ + \ += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context += \"Phase Instructions:\\\ + n\" + phase_instructions\n" + output_var: phase_context, current_phase +- type: code + code: "import re\nimport os\n\ntitle_match = re.search(r'', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\ + \ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\ + \ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\ + \ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\ + \ if f.startswith(discussion_name):\n existing.append(f)\n\n\ + next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\ + \ + \"_backend_\" + str(next_num) + \".puml\"\n" + output_var: diagram_path +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\ + ]:\n line = f\"[{timestamp}] [backend] {msg}\"\n print(line, file=sys.stderr)\n\ + \ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\ + \ f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress1 +- type: prompt + prompt: "You are AI-Backend (also known as Blake), a backend development specialist\ + \ who\ndesigns robust APIs, efficient databases, and scalable server architectures.\n\ + \n## Your Role\n- Design clean, consistent API interfaces\n- Model data relationships\ + \ and storage strategies\n- Ensure proper authentication and authorization\n-\ + \ Consider transaction handling and data integrity\n- Apply backend best practices\ + \ and patterns\n\n## Your Perspective\n- APIs are contracts - design them carefully\n\ + - Database design determines application limits\n- N+1 queries are the silent\ + \ performance killer\n- Idempotency matters for reliability\n- Think about the\ + \ data lifecycle\n\n## Backend Checklist\n- API design (REST/GraphQL conventions)\n\ + - Database schema and indexes\n- Authentication/Authorization flow\n- Transaction\ + \ boundaries\n- Caching strategy\n- Error handling and logging\n- Rate limiting\ + \ and quotas\n- Migration strategy\n\n## Phase Context\n{phase_context}\n\n##\ + \ Diagrams\nWhen creating API or database diagrams, include a reference marker.\n\ + Diagram path to use: {diagram_path}\n\nIMPORTANT: When you create a diagram, your\ + \ comment MUST include:\nDIAGRAM: {diagram_path}\n\n## Current Discussion\n{input}\n\ + \n## Your Task\n{callout}\n\nFollow the phase instructions. Analyze from a backend\ + \ development perspective.\n\n## Response Format\nRespond with valid JSON only.\ + \ Use \\n for newlines in strings:\n{{\n \"comment\": \"Your backend analysis...\\\ + n\\nDIAGRAM: path/file.puml (if created)\",\n \"vote\": \"READY\" or \"CHANGES\"\ + \ or \"REJECT\" or null,\n \"diagram\": \"@startuml\\n...\\n@enduml\"\n}}\n\n\ + Vote meanings:\n- READY: Backend implementation is solid\n- CHANGES: Backend improvements\ + \ needed\n- REJECT: Significant backend issues\n- null: Comment only, no vote\ + \ change\n\nIf you have nothing meaningful to add, respond: {{\"sentinel\": \"\ + NO_RESPONSE\"}}\n" + provider: codex + output_var: response +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nline = f\"[{timestamp}] [backend] AI response received\"\nprint(line,\ + \ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\ + \ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress2 +- type: code + code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\ + \ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\ + \ if code_block:\n json_text = code_block.group(1).strip()\n" + output_var: json_text +- type: code + code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\ + \ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\ + \ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \ + \ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\ + \ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\ + ?\\w+\"?|null)', json_text)\n diagram_match = re.search(r'\"diagram\"\\\ + s*:\\s*\"(.*?)\"(?=\\s*[,}])', json_text, re.DOTALL)\n parsed = {\n \ + \ \"comment\": comment_match.group(1).replace('\\n', ' ') if comment_match\ + \ else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"')\ + \ if vote_match else None,\n \"diagram\": diagram_match.group(1) if\ + \ diagram_match else None\n }\n if parsed[\"vote\"] == \"null\"\ + :\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\ + )\nvote = parsed.get(\"vote\")\ndiagram_content = parsed.get(\"diagram\")\nhas_diagram\ + \ = \"true\" if diagram_content else \"false\"\n" + output_var: comment, vote, diagram_content, has_diagram +- type: code + code: "if has_diagram == \"true\" and diagram_content:\n with open(diagram_path,\ + \ 'w') as f:\n f.write(diagram_content)\n saved_diagram = diagram_path\n\ + else:\n saved_diagram = \"\"\n" + output_var: saved_diagram +- type: code + code: "import json\nresult = {\"comment\": comment, \"vote\": vote}\nif saved_diagram:\n\ + \ result[\"diagram_file\"] = saved_diagram\nfinal_response = json.dumps(result)\n" + output_var: final_response +output: '{final_response}' diff --git a/smarttools/discussion-designer/config.yaml b/smarttools/discussion-designer/config.yaml new file mode 100644 index 0000000..32666d5 --- /dev/null +++ b/smarttools/discussion-designer/config.yaml @@ -0,0 +1,141 @@ +name: discussion-designer +description: UI/Visual design specialist participant for discussions +category: Discussion +meta: + display_name: AI-Designer + alias: designer + type: voting + expertise: + - Visual design + - UI patterns + - Color theory + - Typography + - Layout systems + - Design systems + - Accessibility (visual) + concerns: + - Is the visual hierarchy clear? + - Does this follow design system guidelines? + - Is the interface aesthetically pleasing and consistent? + - Are visual elements accessible (contrast, sizing)? + voice: en-GB-Neural2-A + provider: claude-haiku + color: + - 200 + - 100 + - 255 +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: --diagrams-dir + variable: diagrams_dir + default: diagrams + description: Path to save diagrams +- flag: --log-file + variable: log_file + default: '' + description: Path to log file for progress updates +steps: +- type: code + code: "import re\nimport os\n\nphase_match = re.search(r'', input, re.IGNORECASE)\ntemplate_match = re.search(r'', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\ + \ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\ + \ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\ + \ template_name + \".yaml\")\nphase_goal = \"Provide design feedback\"\nphase_instructions\ + \ = \"Review the proposal for visual design concerns.\"\n\nif os.path.exists(template_path):\n\ + \ import yaml\n with open(template_path, 'r') as f:\n template =\ + \ yaml.safe_load(f)\n phases = template.get(\"phases\", {})\n phase_info\ + \ = phases.get(current_phase, {})\n phase_goal = phase_info.get(\"goal\", phase_goal)\n\ + \ phase_instructions = phase_info.get(\"instructions\", phase_instructions)\n\ + \nphase_context = \"Current Phase: \" + current_phase + \"\\n\"\nphase_context\ + \ += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context += \"Phase Instructions:\\\ + n\" + phase_instructions\n" + output_var: phase_context, current_phase +- type: code + code: "import re\nimport os\n\ntitle_match = re.search(r'', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\ + \ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\ + \ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\ + \ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\ + \ if f.startswith(discussion_name):\n existing.append(f)\n\n\ + next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\ + \ + \"_designer_\" + str(next_num) + \".puml\"\n" + output_var: diagram_path +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\ + ]:\n line = f\"[{timestamp}] [designer] {msg}\"\n print(line, file=sys.stderr)\n\ + \ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\ + \ f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress1 +- type: prompt + prompt: "You are AI-Designer (also known as Dana), a visual design specialist who\ + \ focuses on\ncreating beautiful, intuitive, and consistent user interfaces.\n\ + \n## Your Role\n- Evaluate visual design decisions and aesthetics\n- Ensure consistency\ + \ with design systems and patterns\n- Consider visual hierarchy and information\ + \ architecture\n- Suggest improvements for clarity and usability\n- Balance aesthetics\ + \ with functionality\n\n## Your Perspective\n- Design is how it works, not just\ + \ how it looks\n- Consistency builds trust and reduces cognitive load\n- White\ + \ space is a design element, not empty space\n- Every visual element should serve\ + \ a purpose\n- Accessible design is good design\n\n## Design Checklist\n- Visual\ + \ hierarchy (what draws attention first?)\n- Color usage and contrast ratios\n\ + - Typography (readability, scale, weight)\n- Spacing and alignment\n- Component\ + \ consistency\n- Responsive considerations\n- Brand alignment\n\n## Phase Context\n\ + {phase_context}\n\n## Diagrams\nWhen creating wireframes or layout diagrams, include\ + \ a reference marker.\nDiagram path to use: {diagram_path}\n\nIMPORTANT: When\ + \ you create a diagram, your comment MUST include:\nDIAGRAM: {diagram_path}\n\n\ + ## Current Discussion\n{input}\n\n## Your Task\n{callout}\n\nFollow the phase\ + \ instructions. Analyze from a visual design perspective.\n\n## Response Format\n\ + Respond with valid JSON only. Use \\n for newlines in strings:\n{{\n \"comment\"\ + : \"Your design analysis...\\n\\nDIAGRAM: path/file.puml (if created)\",\n \"\ + vote\": \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\": \"@startuml\\\ + n...\\n@enduml\"\n}}\n\nVote meanings:\n- READY: Design is solid and consistent\n\ + - CHANGES: Design improvements needed\n- REJECT: Fundamental design issues\n-\ + \ null: Comment only, no vote change\n\nIf you have nothing meaningful to add,\ + \ respond: {{\"sentinel\": \"NO_RESPONSE\"}}\n" + provider: claude-haiku + output_var: response +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nline = f\"[{timestamp}] [designer] AI response received\"\nprint(line,\ + \ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\ + \ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress2 +- type: code + code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\ + \ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\ + \ if code_block:\n json_text = code_block.group(1).strip()\n" + output_var: json_text +- type: code + code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\ + \ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\ + \ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \ + \ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\ + \ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\ + ?\\w+\"?|null)', json_text)\n diagram_match = re.search(r'\"diagram\"\\\ + s*:\\s*\"(.*?)\"(?=\\s*[,}])', json_text, re.DOTALL)\n parsed = {\n \ + \ \"comment\": comment_match.group(1).replace('\\n', ' ') if comment_match\ + \ else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"')\ + \ if vote_match else None,\n \"diagram\": diagram_match.group(1) if\ + \ diagram_match else None\n }\n if parsed[\"vote\"] == \"null\"\ + :\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\ + )\nvote = parsed.get(\"vote\")\ndiagram_content = parsed.get(\"diagram\")\nhas_diagram\ + \ = \"true\" if diagram_content else \"false\"\n" + output_var: comment, vote, diagram_content, has_diagram +- type: code + code: "if has_diagram == \"true\" and diagram_content:\n with open(diagram_path,\ + \ 'w') as f:\n f.write(diagram_content)\n saved_diagram = diagram_path\n\ + else:\n saved_diagram = \"\"\n" + output_var: saved_diagram +- type: code + code: "import json\nresult = {\"comment\": comment, \"vote\": vote}\nif saved_diagram:\n\ + \ result[\"diagram_file\"] = saved_diagram\nfinal_response = json.dumps(result)\n" + output_var: final_response +output: '{final_response}' diff --git a/smarttools/discussion-devops/config.yaml b/smarttools/discussion-devops/config.yaml new file mode 100644 index 0000000..dd49167 --- /dev/null +++ b/smarttools/discussion-devops/config.yaml @@ -0,0 +1,143 @@ +name: discussion-devops +description: DevOps specialist participant for discussions +category: Discussion +meta: + display_name: AI-DevOps + alias: devops + type: voting + expertise: + - CI/CD pipelines + - Infrastructure as Code + - Container orchestration + - Monitoring and observability + - Cloud platforms (AWS + - GCP + - Azure) + - Configuration management + - Deployment strategies + concerns: + - How do we deploy this? + - What's the monitoring strategy? + - Is this infrastructure scalable? + - How do we handle rollbacks? + voice: en-US-Neural2-F + provider: claude + color: + - 100 + - 200 + - 255 +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: --diagrams-dir + variable: diagrams_dir + default: diagrams + description: Path to save diagrams +- flag: --log-file + variable: log_file + default: '' + description: Path to log file for progress updates +steps: +- type: code + code: "import re\nimport os\n\nphase_match = re.search(r'', input, re.IGNORECASE)\ntemplate_match = re.search(r'', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\ + \ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\ + \ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\ + \ template_name + \".yaml\")\nphase_goal = \"Provide DevOps feedback\"\nphase_instructions\ + \ = \"Review the proposal for deployment and infrastructure concerns.\"\n\nif\ + \ os.path.exists(template_path):\n import yaml\n with open(template_path,\ + \ 'r') as f:\n template = yaml.safe_load(f)\n phases = template.get(\"\ + phases\", {})\n phase_info = phases.get(current_phase, {})\n phase_goal\ + \ = phase_info.get(\"goal\", phase_goal)\n phase_instructions = phase_info.get(\"\ + instructions\", phase_instructions)\n\nphase_context = \"Current Phase: \" + current_phase\ + \ + \"\\n\"\nphase_context += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context\ + \ += \"Phase Instructions:\\n\" + phase_instructions\n" + output_var: phase_context, current_phase +- type: code + code: "import re\nimport os\n\ntitle_match = re.search(r'', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\ + \ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\ + \ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\ + \ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\ + \ if f.startswith(discussion_name):\n existing.append(f)\n\n\ + next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\ + \ + \"_devops_\" + str(next_num) + \".puml\"\n" + output_var: diagram_path +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\ + ]:\n line = f\"[{timestamp}] [devops] {msg}\"\n print(line, file=sys.stderr)\n\ + \ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\ + \ f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress1 +- type: prompt + prompt: "You are AI-DevOps (also known as Devon), a DevOps specialist who ensures\n\ + reliable deployments, robust infrastructure, and comprehensive observability.\n\ + \n## Your Role\n- Design deployment pipelines and strategies\n- Plan infrastructure\ + \ and scaling approaches\n- Ensure monitoring and alerting coverage\n- Consider\ + \ disaster recovery and rollback procedures\n- Apply DevOps and SRE best practices\n\ + \n## Your Perspective\n- If it's not automated, it's a future incident\n- Monitoring\ + \ is not optional - you can't fix what you can't see\n- Every deployment should\ + \ be reversible\n- Infrastructure as code prevents configuration drift\n- Chaos\ + \ is inevitable - plan for it\n\n## DevOps Checklist\n- CI/CD pipeline requirements\n\ + - Container/orchestration needs\n- Environment configuration\n- Secrets management\n\ + - Monitoring and alerting\n- Logging and tracing\n- Backup and recovery\n- Scaling\ + \ strategy (horizontal/vertical)\n- Deployment strategy (blue-green, canary, rolling)\n\ + \n## Phase Context\n{phase_context}\n\n## Diagrams\nWhen creating infrastructure\ + \ or deployment diagrams, include a reference marker.\nDiagram path to use: {diagram_path}\n\ + \nIMPORTANT: When you create a diagram, your comment MUST include:\nDIAGRAM: {diagram_path}\n\ + \n## Current Discussion\n{input}\n\n## Your Task\n{callout}\n\nFollow the phase\ + \ instructions. Analyze from a DevOps/infrastructure perspective.\n\n## Response\ + \ Format\nRespond with valid JSON only. Use \\n for newlines in strings:\n{{\n\ + \ \"comment\": \"Your DevOps analysis...\\n\\nDIAGRAM: path/file.puml (if created)\"\ + ,\n \"vote\": \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\"\ + : \"@startuml\\n...\\n@enduml\"\n}}\n\nVote meanings:\n- READY: Deployment/infrastructure\ + \ is solid\n- CHANGES: DevOps improvements needed\n- REJECT: Significant infrastructure\ + \ issues\n- null: Comment only, no vote change\n\nIf you have nothing meaningful\ + \ to add, respond: {{\"sentinel\": \"NO_RESPONSE\"}}\n" + provider: claude + output_var: response +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nline = f\"[{timestamp}] [devops] AI response received\"\nprint(line,\ + \ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\ + \ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress2 +- type: code + code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\ + \ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\ + \ if code_block:\n json_text = code_block.group(1).strip()\n" + output_var: json_text +- type: code + code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\ + \ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\ + \ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \ + \ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\ + \ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\ + ?\\w+\"?|null)', json_text)\n diagram_match = re.search(r'\"diagram\"\\\ + s*:\\s*\"(.*?)\"(?=\\s*[,}])', json_text, re.DOTALL)\n parsed = {\n \ + \ \"comment\": comment_match.group(1).replace('\\n', ' ') if comment_match\ + \ else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"')\ + \ if vote_match else None,\n \"diagram\": diagram_match.group(1) if\ + \ diagram_match else None\n }\n if parsed[\"vote\"] == \"null\"\ + :\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\ + )\nvote = parsed.get(\"vote\")\ndiagram_content = parsed.get(\"diagram\")\nhas_diagram\ + \ = \"true\" if diagram_content else \"false\"\n" + output_var: comment, vote, diagram_content, has_diagram +- type: code + code: "if has_diagram == \"true\" and diagram_content:\n with open(diagram_path,\ + \ 'w') as f:\n f.write(diagram_content)\n saved_diagram = diagram_path\n\ + else:\n saved_diagram = \"\"\n" + output_var: saved_diagram +- type: code + code: "import json\nresult = {\"comment\": comment, \"vote\": vote}\nif saved_diagram:\n\ + \ result[\"diagram_file\"] = saved_diagram\nfinal_response = json.dumps(result)\n" + output_var: final_response +output: '{final_response}' diff --git a/smarttools/discussion-frontend/config.yaml b/smarttools/discussion-frontend/config.yaml new file mode 100644 index 0000000..a339f52 --- /dev/null +++ b/smarttools/discussion-frontend/config.yaml @@ -0,0 +1,141 @@ +name: discussion-frontend +description: Frontend development specialist participant for discussions +category: Discussion +meta: + display_name: AI-Frontend + alias: frontend + type: voting + expertise: + - React/Vue/Angular + - CSS/Styling + - Component architecture + - State management + - Browser APIs + - Performance optimization + - Responsive design + concerns: + - Is this component reusable? + - What's the state management strategy? + - How does this affect bundle size? + - Is this accessible and responsive? + voice: en-US-Neural2-C + provider: opencode-pickle + color: + - 255 + - 150 + - 200 +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: --diagrams-dir + variable: diagrams_dir + default: diagrams + description: Path to save diagrams +- flag: --log-file + variable: log_file + default: '' + description: Path to log file for progress updates +steps: +- type: code + code: "import re\nimport os\n\nphase_match = re.search(r'', input, re.IGNORECASE)\ntemplate_match = re.search(r'', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\ + \ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\ + \ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\ + \ template_name + \".yaml\")\nphase_goal = \"Provide frontend feedback\"\nphase_instructions\ + \ = \"Review the proposal for frontend implementation concerns.\"\n\nif os.path.exists(template_path):\n\ + \ import yaml\n with open(template_path, 'r') as f:\n template =\ + \ yaml.safe_load(f)\n phases = template.get(\"phases\", {})\n phase_info\ + \ = phases.get(current_phase, {})\n phase_goal = phase_info.get(\"goal\", phase_goal)\n\ + \ phase_instructions = phase_info.get(\"instructions\", phase_instructions)\n\ + \nphase_context = \"Current Phase: \" + current_phase + \"\\n\"\nphase_context\ + \ += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context += \"Phase Instructions:\\\ + n\" + phase_instructions\n" + output_var: phase_context, current_phase +- type: code + code: "import re\nimport os\n\ntitle_match = re.search(r'', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\ + \ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\ + \ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\ + \ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\ + \ if f.startswith(discussion_name):\n existing.append(f)\n\n\ + next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\ + \ + \"_frontend_\" + str(next_num) + \".puml\"\n" + output_var: diagram_path +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\ + ]:\n line = f\"[{timestamp}] [frontend] {msg}\"\n print(line, file=sys.stderr)\n\ + \ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\ + \ f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress1 +- type: prompt + prompt: "You are AI-Frontend (also known as Fiona), a frontend development specialist\ + \ who\nbuilds performant, accessible, and maintainable user interfaces.\n\n##\ + \ Your Role\n- Evaluate frontend architecture and component design\n- Consider\ + \ state management and data flow\n- Ensure responsive and accessible implementations\n\ + - Optimize for performance and bundle size\n- Apply modern frontend best practices\n\ + \n## Your Perspective\n- Components should be composable and reusable\n- Performance\ + \ matters - every millisecond counts\n- CSS is code - it needs architecture too\n\ + - Progressive enhancement over graceful degradation\n- Don't fight the browser\ + \ - work with it\n\n## Frontend Checklist\n- Component hierarchy and data flow\n\ + - State management approach\n- CSS strategy (modules, styled-components, etc.)\n\ + - Bundle size impact\n- Browser compatibility\n- Mobile/responsive behavior\n\ + - Loading and error states\n- Accessibility (keyboard, screen readers)\n\n## Phase\ + \ Context\n{phase_context}\n\n## Diagrams\nWhen creating component diagrams, include\ + \ a reference marker.\nDiagram path to use: {diagram_path}\n\nIMPORTANT: When\ + \ you create a diagram, your comment MUST include:\nDIAGRAM: {diagram_path}\n\n\ + ## Current Discussion\n{input}\n\n## Your Task\n{callout}\n\nFollow the phase\ + \ instructions. Analyze from a frontend development perspective.\n\n## Response\ + \ Format\nRespond with valid JSON only. Use \\n for newlines in strings:\n{{\n\ + \ \"comment\": \"Your frontend analysis...\\n\\nDIAGRAM: path/file.puml (if created)\"\ + ,\n \"vote\": \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\"\ + : \"@startuml\\n...\\n@enduml\"\n}}\n\nVote meanings:\n- READY: Frontend implementation\ + \ is solid\n- CHANGES: Frontend improvements needed\n- REJECT: Significant frontend\ + \ issues\n- null: Comment only, no vote change\n\nIf you have nothing meaningful\ + \ to add, respond: {{\"sentinel\": \"NO_RESPONSE\"}}\n" + provider: opencode-pickle + output_var: response +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nline = f\"[{timestamp}] [frontend] AI response received\"\nprint(line,\ + \ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\ + \ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress2 +- type: code + code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\ + \ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\ + \ if code_block:\n json_text = code_block.group(1).strip()\n" + output_var: json_text +- type: code + code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\ + \ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\ + \ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \ + \ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\ + \ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\ + ?\\w+\"?|null)', json_text)\n diagram_match = re.search(r'\"diagram\"\\\ + s*:\\s*\"(.*?)\"(?=\\s*[,}])', json_text, re.DOTALL)\n parsed = {\n \ + \ \"comment\": comment_match.group(1).replace('\\n', ' ') if comment_match\ + \ else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"')\ + \ if vote_match else None,\n \"diagram\": diagram_match.group(1) if\ + \ diagram_match else None\n }\n if parsed[\"vote\"] == \"null\"\ + :\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\ + )\nvote = parsed.get(\"vote\")\ndiagram_content = parsed.get(\"diagram\")\nhas_diagram\ + \ = \"true\" if diagram_content else \"false\"\n" + output_var: comment, vote, diagram_content, has_diagram +- type: code + code: "if has_diagram == \"true\" and diagram_content:\n with open(diagram_path,\ + \ 'w') as f:\n f.write(diagram_content)\n saved_diagram = diagram_path\n\ + else:\n saved_diagram = \"\"\n" + output_var: saved_diagram +- type: code + code: "import json\nresult = {\"comment\": comment, \"vote\": vote}\nif saved_diagram:\n\ + \ result[\"diagram_file\"] = saved_diagram\nfinal_response = json.dumps(result)\n" + output_var: final_response +output: '{final_response}' diff --git a/smarttools/discussion-performance/config.yaml b/smarttools/discussion-performance/config.yaml new file mode 100644 index 0000000..2618e40 --- /dev/null +++ b/smarttools/discussion-performance/config.yaml @@ -0,0 +1,126 @@ +name: discussion-performance +description: Performance optimization specialist participant for discussions +category: Discussion +meta: + display_name: AI-Performance + alias: performance + type: voting + expertise: + - Performance profiling + - Algorithm optimization + - Caching strategies + - Database optimization + - Memory management + - Load testing + - Scalability patterns + concerns: + - What's the time complexity? + - Where are the bottlenecks? + - How does this scale under load? + - Are we using resources efficiently? + voice: en-US-Neural2-J + provider: opencode-reasoner + color: + - 255 + - 220 + - 100 +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: --diagrams-dir + variable: diagrams_dir + default: diagrams + description: Path to save diagrams +- flag: --log-file + variable: log_file + default: '' + description: Path to log file for progress updates +steps: +- type: code + code: "import re\nimport os\n\nphase_match = re.search(r'', input, re.IGNORECASE)\ntemplate_match = re.search(r'', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\ + \ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\ + \ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\ + \ template_name + \".yaml\")\nphase_goal = \"Provide performance feedback\"\n\ + phase_instructions = \"Review the proposal for performance and scalability concerns.\"\ + \n\nif os.path.exists(template_path):\n import yaml\n with open(template_path,\ + \ 'r') as f:\n template = yaml.safe_load(f)\n phases = template.get(\"\ + phases\", {})\n phase_info = phases.get(current_phase, {})\n phase_goal\ + \ = phase_info.get(\"goal\", phase_goal)\n phase_instructions = phase_info.get(\"\ + instructions\", phase_instructions)\n\nphase_context = \"Current Phase: \" + current_phase\ + \ + \"\\n\"\nphase_context += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context\ + \ += \"Phase Instructions:\\n\" + phase_instructions\n" + output_var: phase_context, current_phase +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\ + ]:\n line = f\"[{timestamp}] [performance] {msg}\"\n print(line, file=sys.stderr)\n\ + \ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\ + \ f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress1 +- type: prompt + prompt: "You are AI-Performance (also known as Perry), a performance optimization\ + \ specialist\nwho ensures systems are fast, efficient, and scalable.\n\n## Your\ + \ Role\n- Identify potential performance bottlenecks\n- Evaluate algorithmic efficiency\ + \ and complexity\n- Recommend caching and optimization strategies\n- Consider\ + \ resource utilization and cost\n- Plan for scale and load testing\n\n## Your\ + \ Perspective\n- Premature optimization is the root of all evil, but known bottlenecks\ + \ must be addressed\n- Measure first, optimize second\n- O(n) vs O(n^2) matters\ + \ more at scale\n- Memory and CPU have different optimization strategies\n- The\ + \ fastest code is code that doesn't run\n\n## Performance Checklist\n- Time complexity\ + \ of algorithms\n- Space complexity and memory usage\n- Database query efficiency\ + \ (indexes, joins)\n- Network round trips\n- Caching opportunities\n- Batch vs\ + \ real-time processing\n- Concurrency and parallelization\n- Resource pooling\ + \ and reuse\n\n## Phase Context\n{phase_context}\n\n## Current Discussion\n{input}\n\ + \n## Your Task\n{callout}\n\nFollow the phase instructions. Analyze from a performance\ + \ and scalability perspective.\nIdentify bottlenecks, suggest optimizations, and\ + \ consider scaling implications.\n\n## Response Format\nRespond with valid JSON\ + \ only. Use \\n for newlines in strings:\n{{\n \"comment\": \"Your performance\ + \ analysis...\\n\\nOptimization opportunities:\\n1. ...\\n2. ...\",\n \"vote\"\ + : \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\": null\n}}\n\n\ + Vote meanings:\n- READY: Performance is acceptable\n- CHANGES: Performance improvements\ + \ needed\n- REJECT: Significant performance issues\n- null: Comment only, no vote\ + \ change\n\nIf you have nothing meaningful to add, respond: {{\"sentinel\": \"\ + NO_RESPONSE\"}}\n" + provider: opencode-reasoner + output_var: response +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nline = f\"[{timestamp}] [performance] AI response received\"\nprint(line,\ + \ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\ + \ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress2 +- type: code + code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\ + \ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\ + \ if code_block:\n json_text = code_block.group(1).strip()\n" + output_var: json_text +- type: code + code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\ + \ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\ + \ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \ + \ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\ + \ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\ + ?\\w+\"?|null)', json_text)\n parsed = {\n \"comment\": comment_match.group(1).replace('\\\ + n', ' ') if comment_match else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"\ + ') if vote_match else None\n }\n if parsed[\"vote\"] == \"null\"\ + :\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\ + )\nvote = parsed.get(\"vote\")\n" + output_var: comment, vote +- type: code + code: 'import json + + result = {"comment": comment, "vote": vote} + + final_response = json.dumps(result) + + ' + output_var: final_response +output: '{final_response}' diff --git a/smarttools/discussion-qa/config.yaml b/smarttools/discussion-qa/config.yaml new file mode 100644 index 0000000..2f357c6 --- /dev/null +++ b/smarttools/discussion-qa/config.yaml @@ -0,0 +1,135 @@ +name: discussion-qa +description: Quality assurance specialist participant for discussions +category: Discussion +meta: + display_name: AI-QA + alias: qa + type: voting + expertise: + - Test strategy + - Edge case identification + - Regression testing + - Error handling + - Quality metrics + - Bug prevention + - Test automation + concerns: + - What could go wrong? + - How do we test this? + - What are the edge cases? + - Is error handling sufficient? + voice: en-US-Neural2-D + provider: gemini + color: + - 180 + - 255 + - 100 +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: --diagrams-dir + variable: diagrams_dir + default: diagrams + description: Path to save diagrams +- flag: --log-file + variable: log_file + default: '' + description: Path to log file for progress updates +steps: +- type: code + code: "import re\nimport os\n\nphase_match = re.search(r'', input, re.IGNORECASE)\ntemplate_match = re.search(r'', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\ + \ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\ + \ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\ + \ template_name + \".yaml\")\nphase_goal = \"Provide QA feedback\"\nphase_instructions\ + \ = \"Review the proposal for testability and quality concerns.\"\n\nif os.path.exists(template_path):\n\ + \ import yaml\n with open(template_path, 'r') as f:\n template =\ + \ yaml.safe_load(f)\n phases = template.get(\"phases\", {})\n phase_info\ + \ = phases.get(current_phase, {})\n phase_goal = phase_info.get(\"goal\", phase_goal)\n\ + \ phase_instructions = phase_info.get(\"instructions\", phase_instructions)\n\ + \nphase_context = \"Current Phase: \" + current_phase + \"\\n\"\nphase_context\ + \ += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context += \"Phase Instructions:\\\ + n\" + phase_instructions\n" + output_var: phase_context, current_phase +- type: code + code: "import re\nimport os\n\ntitle_match = re.search(r'', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\ + \ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\ + \ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\ + \ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\ + \ if f.startswith(discussion_name):\n existing.append(f)\n\n\ + next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\ + \ + \"_qa_\" + str(next_num) + \".puml\"\n" + output_var: diagram_path +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\ + ]:\n line = f\"[{timestamp}] [qa] {msg}\"\n print(line, file=sys.stderr)\n\ + \ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\ + \ f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress1 +- type: prompt + prompt: "You are AI-QA (also known as Quinn), a quality assurance specialist who\ + \ ensures\nsoftware is reliable, well-tested, and handles edge cases gracefully.\n\ + \n## Your Role\n- Identify potential bugs and edge cases before they happen\n\ + - Design comprehensive test strategies\n- Evaluate error handling and failure\ + \ modes\n- Ensure testability of proposed implementations\n- Think about what\ + \ could go wrong\n\n## Your Perspective\n- If it can break, it will break - in\ + \ production, at 3 AM\n- Edge cases are where most bugs hide\n- Good error messages\ + \ save hours of debugging\n- Tests are documentation that never goes stale\n-\ + \ Prevention is cheaper than debugging\n\n## QA Checklist\n- Happy path testing\n\ + - Error/exception handling\n- Boundary conditions (empty, null, max values)\n\ + - Concurrency and race conditions\n- Integration points and failure modes\n- Rollback\ + \ and recovery scenarios\n- Data validation and sanitization\n- Performance under\ + \ load\n\n## Phase Context\n{phase_context}\n\n## Current Discussion\n{input}\n\ + \n## Your Task\n{callout}\n\nFollow the phase instructions. Analyze from a quality\ + \ assurance perspective.\nIdentify edge cases, failure modes, and testing requirements.\n\ + \n## Response Format\nRespond with valid JSON only. Use \\n for newlines in strings:\n\ + {{\n \"comment\": \"Your QA analysis...\\n\\nTest cases:\\n1. ...\\n2. ...\"\ + ,\n \"vote\": \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\"\ + : null\n}}\n\nVote meanings:\n- READY: Quality is assured, testable\n- CHANGES:\ + \ Testing/quality improvements needed\n- REJECT: Untestable or high-risk implementation\n\ + - null: Comment only, no vote change\n\nIf you have nothing meaningful to add,\ + \ respond: {{\"sentinel\": \"NO_RESPONSE\"}}\n" + provider: gemini + output_var: response +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nline = f\"[{timestamp}] [qa] AI response received\"\nprint(line,\ + \ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\ + \ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress2 +- type: code + code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\ + \ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\ + \ if code_block:\n json_text = code_block.group(1).strip()\n" + output_var: json_text +- type: code + code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\ + \ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\ + \ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \ + \ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\ + \ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\ + ?\\w+\"?|null)', json_text)\n parsed = {\n \"comment\": comment_match.group(1).replace('\\\ + n', ' ') if comment_match else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"\ + ') if vote_match else None\n }\n if parsed[\"vote\"] == \"null\"\ + :\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\ + )\nvote = parsed.get(\"vote\")\n" + output_var: comment, vote +- type: code + code: 'import json + + result = {"comment": comment, "vote": vote} + + final_response = json.dumps(result) + + ' + output_var: final_response +output: '{final_response}' diff --git a/smarttools/discussion-ux/config.yaml b/smarttools/discussion-ux/config.yaml new file mode 100644 index 0000000..cb43484 --- /dev/null +++ b/smarttools/discussion-ux/config.yaml @@ -0,0 +1,141 @@ +name: discussion-ux +description: User experience specialist participant for discussions +category: Discussion +meta: + display_name: AI-UX + alias: ux + type: voting + expertise: + - User research + - Usability testing + - User flows + - Information architecture + - Accessibility (WCAG) + - Interaction design + - User journey mapping + concerns: + - Is this intuitive for users? + - What's the cognitive load? + - Are we meeting accessibility standards? + - What user problems are we solving? + voice: en-AU-Neural2-A + provider: gemini-flash + color: + - 100 + - 220 + - 200 +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: --diagrams-dir + variable: diagrams_dir + default: diagrams + description: Path to save diagrams +- flag: --log-file + variable: log_file + default: '' + description: Path to log file for progress updates +steps: +- type: code + code: "import re\nimport os\n\nphase_match = re.search(r'', input, re.IGNORECASE)\ntemplate_match = re.search(r'', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\ + \ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\ + \ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\ + \ template_name + \".yaml\")\nphase_goal = \"Provide UX feedback\"\nphase_instructions\ + \ = \"Review the proposal for user experience concerns.\"\n\nif os.path.exists(template_path):\n\ + \ import yaml\n with open(template_path, 'r') as f:\n template =\ + \ yaml.safe_load(f)\n phases = template.get(\"phases\", {})\n phase_info\ + \ = phases.get(current_phase, {})\n phase_goal = phase_info.get(\"goal\", phase_goal)\n\ + \ phase_instructions = phase_info.get(\"instructions\", phase_instructions)\n\ + \nphase_context = \"Current Phase: \" + current_phase + \"\\n\"\nphase_context\ + \ += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context += \"Phase Instructions:\\\ + n\" + phase_instructions\n" + output_var: phase_context, current_phase +- type: code + code: "import re\nimport os\n\ntitle_match = re.search(r'', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\ + \ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\ + \ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\ + \ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\ + \ if f.startswith(discussion_name):\n existing.append(f)\n\n\ + next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\ + \ + \"_ux_\" + str(next_num) + \".puml\"\n" + output_var: diagram_path +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\ + ]:\n line = f\"[{timestamp}] [ux] {msg}\"\n print(line, file=sys.stderr)\n\ + \ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\ + \ f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress1 +- type: prompt + prompt: "You are AI-UX (also known as Uma), a user experience specialist who advocates\n\ + for users and ensures products are intuitive, accessible, and delightful to use.\n\ + \n## Your Role\n- Champion the user's perspective in all decisions\n- Evaluate\ + \ usability and intuitiveness of proposals\n- Ensure accessibility compliance\ + \ (WCAG 2.1)\n- Design user flows that minimize friction\n- Consider edge cases\ + \ from the user's viewpoint\n\n## Your Perspective\n- Users don't read manuals\ + \ - make it obvious\n- Every click/tap is a decision point that can lose users\n\ + - Error states are part of the experience\n- Accessibility is not optional\n-\ + \ Test assumptions with real user behavior\n\n## UX Checklist\n- User flow clarity\ + \ (can users complete their goals?)\n- Error handling and recovery\n- Loading\ + \ states and feedback\n- Keyboard navigation\n- Screen reader compatibility\n\ + - Mobile/touch considerations\n- Onboarding and discoverability\n- Cognitive load\ + \ assessment\n\n## Phase Context\n{phase_context}\n\n## Diagrams\nWhen creating\ + \ user flow diagrams, include a reference marker.\nDiagram path to use: {diagram_path}\n\ + \nIMPORTANT: When you create a diagram, your comment MUST include:\nDIAGRAM: {diagram_path}\n\ + \n## Current Discussion\n{input}\n\n## Your Task\n{callout}\n\nFollow the phase\ + \ instructions. Analyze from a user experience perspective.\n\n## Response Format\n\ + Respond with valid JSON only. Use \\n for newlines in strings:\n{{\n \"comment\"\ + : \"Your UX analysis...\\n\\nDIAGRAM: path/file.puml (if created)\",\n \"vote\"\ + : \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\": \"@startuml\\\ + n...\\n@enduml\"\n}}\n\nVote meanings:\n- READY: Good user experience, accessible\n\ + - CHANGES: UX improvements needed\n- REJECT: Significant usability issues\n- null:\ + \ Comment only, no vote change\n\nIf you have nothing meaningful to add, respond:\ + \ {{\"sentinel\": \"NO_RESPONSE\"}}\n" + provider: gemini-flash + output_var: response +- type: code + code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\ + %H:%M:%S\")\nline = f\"[{timestamp}] [ux] AI response received\"\nprint(line,\ + \ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\ + \ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n" + output_var: _progress2 +- type: code + code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\ + \ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\ + \ if code_block:\n json_text = code_block.group(1).strip()\n" + output_var: json_text +- type: code + code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\ + \ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\ + \ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \ + \ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\ + \ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\ + ?\\w+\"?|null)', json_text)\n diagram_match = re.search(r'\"diagram\"\\\ + s*:\\s*\"(.*?)\"(?=\\s*[,}])', json_text, re.DOTALL)\n parsed = {\n \ + \ \"comment\": comment_match.group(1).replace('\\n', ' ') if comment_match\ + \ else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"')\ + \ if vote_match else None,\n \"diagram\": diagram_match.group(1) if\ + \ diagram_match else None\n }\n if parsed[\"vote\"] == \"null\"\ + :\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\ + )\nvote = parsed.get(\"vote\")\ndiagram_content = parsed.get(\"diagram\")\nhas_diagram\ + \ = \"true\" if diagram_content else \"false\"\n" + output_var: comment, vote, diagram_content, has_diagram +- type: code + code: "if has_diagram == \"true\" and diagram_content:\n with open(diagram_path,\ + \ 'w') as f:\n f.write(diagram_content)\n saved_diagram = diagram_path\n\ + else:\n saved_diagram = \"\"\n" + output_var: saved_diagram +- type: code + code: "import json\nresult = {\"comment\": comment, \"vote\": vote}\nif saved_diagram:\n\ + \ result[\"diagram_file\"] = saved_diagram\nfinal_response = json.dumps(result)\n" + output_var: final_response +output: '{final_response}'