superqode 0.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. superqode/__init__.py +33 -0
  2. superqode/acp/__init__.py +23 -0
  3. superqode/acp/client.py +913 -0
  4. superqode/acp/permission_screen.py +457 -0
  5. superqode/acp/types.py +480 -0
  6. superqode/acp_discovery.py +856 -0
  7. superqode/agent/__init__.py +22 -0
  8. superqode/agent/edit_strategies.py +334 -0
  9. superqode/agent/loop.py +892 -0
  10. superqode/agent/qe_report_templates.py +39 -0
  11. superqode/agent/system_prompts.py +353 -0
  12. superqode/agent_output.py +721 -0
  13. superqode/agent_stream.py +953 -0
  14. superqode/agents/__init__.py +59 -0
  15. superqode/agents/acp_registry.py +305 -0
  16. superqode/agents/client.py +249 -0
  17. superqode/agents/data/augmentcode.com.toml +51 -0
  18. superqode/agents/data/cagent.dev.toml +51 -0
  19. superqode/agents/data/claude.com.toml +60 -0
  20. superqode/agents/data/codeassistant.dev.toml +51 -0
  21. superqode/agents/data/codex.openai.com.toml +57 -0
  22. superqode/agents/data/fastagent.ai.toml +66 -0
  23. superqode/agents/data/geminicli.com.toml +77 -0
  24. superqode/agents/data/goose.block.xyz.toml +54 -0
  25. superqode/agents/data/junie.jetbrains.com.toml +56 -0
  26. superqode/agents/data/kimi.moonshot.cn.toml +57 -0
  27. superqode/agents/data/llmlingagent.dev.toml +51 -0
  28. superqode/agents/data/molt.bot.toml +49 -0
  29. superqode/agents/data/opencode.ai.toml +60 -0
  30. superqode/agents/data/stakpak.dev.toml +51 -0
  31. superqode/agents/data/vtcode.dev.toml +51 -0
  32. superqode/agents/discovery.py +266 -0
  33. superqode/agents/messaging.py +160 -0
  34. superqode/agents/persona.py +166 -0
  35. superqode/agents/registry.py +421 -0
  36. superqode/agents/schema.py +72 -0
  37. superqode/agents/unified.py +367 -0
  38. superqode/app/__init__.py +111 -0
  39. superqode/app/constants.py +314 -0
  40. superqode/app/css.py +366 -0
  41. superqode/app/models.py +118 -0
  42. superqode/app/suggester.py +125 -0
  43. superqode/app/widgets.py +1591 -0
  44. superqode/app_enhanced.py +399 -0
  45. superqode/app_main.py +17187 -0
  46. superqode/approval.py +312 -0
  47. superqode/atomic.py +296 -0
  48. superqode/commands/__init__.py +1 -0
  49. superqode/commands/acp.py +965 -0
  50. superqode/commands/agents.py +180 -0
  51. superqode/commands/auth.py +278 -0
  52. superqode/commands/config.py +374 -0
  53. superqode/commands/init.py +826 -0
  54. superqode/commands/providers.py +819 -0
  55. superqode/commands/qe.py +1145 -0
  56. superqode/commands/roles.py +380 -0
  57. superqode/commands/serve.py +172 -0
  58. superqode/commands/suggestions.py +127 -0
  59. superqode/commands/superqe.py +460 -0
  60. superqode/config/__init__.py +51 -0
  61. superqode/config/loader.py +812 -0
  62. superqode/config/schema.py +498 -0
  63. superqode/core/__init__.py +111 -0
  64. superqode/core/roles.py +281 -0
  65. superqode/danger.py +386 -0
  66. superqode/data/superqode-template.yaml +1522 -0
  67. superqode/design_system.py +1080 -0
  68. superqode/dialogs/__init__.py +6 -0
  69. superqode/dialogs/base.py +39 -0
  70. superqode/dialogs/model.py +130 -0
  71. superqode/dialogs/provider.py +870 -0
  72. superqode/diff_view.py +919 -0
  73. superqode/enterprise.py +21 -0
  74. superqode/evaluation/__init__.py +25 -0
  75. superqode/evaluation/adapters.py +93 -0
  76. superqode/evaluation/behaviors.py +89 -0
  77. superqode/evaluation/engine.py +209 -0
  78. superqode/evaluation/scenarios.py +96 -0
  79. superqode/execution/__init__.py +36 -0
  80. superqode/execution/linter.py +538 -0
  81. superqode/execution/modes.py +347 -0
  82. superqode/execution/resolver.py +283 -0
  83. superqode/execution/runner.py +642 -0
  84. superqode/file_explorer.py +811 -0
  85. superqode/file_viewer.py +471 -0
  86. superqode/flash.py +183 -0
  87. superqode/guidance/__init__.py +58 -0
  88. superqode/guidance/config.py +203 -0
  89. superqode/guidance/prompts.py +71 -0
  90. superqode/harness/__init__.py +54 -0
  91. superqode/harness/accelerator.py +291 -0
  92. superqode/harness/config.py +319 -0
  93. superqode/harness/validator.py +147 -0
  94. superqode/history.py +279 -0
  95. superqode/integrations/superopt_runner.py +124 -0
  96. superqode/logging/__init__.py +49 -0
  97. superqode/logging/adapters.py +219 -0
  98. superqode/logging/formatter.py +923 -0
  99. superqode/logging/integration.py +341 -0
  100. superqode/logging/sinks.py +170 -0
  101. superqode/logging/unified_log.py +417 -0
  102. superqode/lsp/__init__.py +26 -0
  103. superqode/lsp/client.py +544 -0
  104. superqode/main.py +1069 -0
  105. superqode/mcp/__init__.py +89 -0
  106. superqode/mcp/auth_storage.py +380 -0
  107. superqode/mcp/client.py +1236 -0
  108. superqode/mcp/config.py +319 -0
  109. superqode/mcp/integration.py +337 -0
  110. superqode/mcp/oauth.py +436 -0
  111. superqode/mcp/oauth_callback.py +385 -0
  112. superqode/mcp/types.py +290 -0
  113. superqode/memory/__init__.py +31 -0
  114. superqode/memory/feedback.py +342 -0
  115. superqode/memory/store.py +522 -0
  116. superqode/notifications.py +369 -0
  117. superqode/optimization/__init__.py +5 -0
  118. superqode/optimization/config.py +33 -0
  119. superqode/permissions/__init__.py +25 -0
  120. superqode/permissions/rules.py +488 -0
  121. superqode/plan.py +323 -0
  122. superqode/providers/__init__.py +33 -0
  123. superqode/providers/gateway/__init__.py +165 -0
  124. superqode/providers/gateway/base.py +228 -0
  125. superqode/providers/gateway/litellm_gateway.py +1170 -0
  126. superqode/providers/gateway/openresponses_gateway.py +436 -0
  127. superqode/providers/health.py +297 -0
  128. superqode/providers/huggingface/__init__.py +74 -0
  129. superqode/providers/huggingface/downloader.py +472 -0
  130. superqode/providers/huggingface/endpoints.py +442 -0
  131. superqode/providers/huggingface/hub.py +531 -0
  132. superqode/providers/huggingface/inference.py +394 -0
  133. superqode/providers/huggingface/transformers_runner.py +516 -0
  134. superqode/providers/local/__init__.py +100 -0
  135. superqode/providers/local/base.py +438 -0
  136. superqode/providers/local/discovery.py +418 -0
  137. superqode/providers/local/lmstudio.py +256 -0
  138. superqode/providers/local/mlx.py +457 -0
  139. superqode/providers/local/ollama.py +486 -0
  140. superqode/providers/local/sglang.py +268 -0
  141. superqode/providers/local/tgi.py +260 -0
  142. superqode/providers/local/tool_support.py +477 -0
  143. superqode/providers/local/vllm.py +258 -0
  144. superqode/providers/manager.py +1338 -0
  145. superqode/providers/models.py +1016 -0
  146. superqode/providers/models_dev.py +578 -0
  147. superqode/providers/openresponses/__init__.py +87 -0
  148. superqode/providers/openresponses/converters/__init__.py +17 -0
  149. superqode/providers/openresponses/converters/messages.py +343 -0
  150. superqode/providers/openresponses/converters/tools.py +268 -0
  151. superqode/providers/openresponses/schema/__init__.py +56 -0
  152. superqode/providers/openresponses/schema/models.py +585 -0
  153. superqode/providers/openresponses/streaming/__init__.py +5 -0
  154. superqode/providers/openresponses/streaming/parser.py +338 -0
  155. superqode/providers/openresponses/tools/__init__.py +21 -0
  156. superqode/providers/openresponses/tools/apply_patch.py +352 -0
  157. superqode/providers/openresponses/tools/code_interpreter.py +290 -0
  158. superqode/providers/openresponses/tools/file_search.py +333 -0
  159. superqode/providers/openresponses/tools/mcp_adapter.py +252 -0
  160. superqode/providers/registry.py +716 -0
  161. superqode/providers/usage.py +332 -0
  162. superqode/pure_mode.py +384 -0
  163. superqode/qr/__init__.py +23 -0
  164. superqode/qr/dashboard.py +781 -0
  165. superqode/qr/generator.py +1018 -0
  166. superqode/qr/templates.py +135 -0
  167. superqode/safety/__init__.py +41 -0
  168. superqode/safety/sandbox.py +413 -0
  169. superqode/safety/warnings.py +256 -0
  170. superqode/server/__init__.py +33 -0
  171. superqode/server/lsp_server.py +775 -0
  172. superqode/server/web.py +250 -0
  173. superqode/session/__init__.py +25 -0
  174. superqode/session/persistence.py +580 -0
  175. superqode/session/sharing.py +477 -0
  176. superqode/session.py +475 -0
  177. superqode/sidebar.py +2991 -0
  178. superqode/stream_view.py +648 -0
  179. superqode/styles/__init__.py +3 -0
  180. superqode/superqe/__init__.py +184 -0
  181. superqode/superqe/acp_runner.py +1064 -0
  182. superqode/superqe/constitution/__init__.py +62 -0
  183. superqode/superqe/constitution/evaluator.py +308 -0
  184. superqode/superqe/constitution/loader.py +432 -0
  185. superqode/superqe/constitution/schema.py +250 -0
  186. superqode/superqe/events.py +591 -0
  187. superqode/superqe/frameworks/__init__.py +65 -0
  188. superqode/superqe/frameworks/base.py +234 -0
  189. superqode/superqe/frameworks/e2e.py +263 -0
  190. superqode/superqe/frameworks/executor.py +237 -0
  191. superqode/superqe/frameworks/javascript.py +409 -0
  192. superqode/superqe/frameworks/python.py +373 -0
  193. superqode/superqe/frameworks/registry.py +92 -0
  194. superqode/superqe/mcp_tools/__init__.py +47 -0
  195. superqode/superqe/mcp_tools/core_tools.py +418 -0
  196. superqode/superqe/mcp_tools/registry.py +230 -0
  197. superqode/superqe/mcp_tools/testing_tools.py +167 -0
  198. superqode/superqe/noise.py +89 -0
  199. superqode/superqe/orchestrator.py +778 -0
  200. superqode/superqe/roles.py +609 -0
  201. superqode/superqe/session.py +713 -0
  202. superqode/superqe/skills/__init__.py +57 -0
  203. superqode/superqe/skills/base.py +106 -0
  204. superqode/superqe/skills/core_skills.py +899 -0
  205. superqode/superqe/skills/registry.py +90 -0
  206. superqode/superqe/verifier.py +101 -0
  207. superqode/superqe_cli.py +76 -0
  208. superqode/tool_call.py +358 -0
  209. superqode/tools/__init__.py +93 -0
  210. superqode/tools/agent_tools.py +496 -0
  211. superqode/tools/base.py +324 -0
  212. superqode/tools/batch_tool.py +133 -0
  213. superqode/tools/diagnostics.py +311 -0
  214. superqode/tools/edit_tools.py +653 -0
  215. superqode/tools/enhanced_base.py +515 -0
  216. superqode/tools/file_tools.py +269 -0
  217. superqode/tools/file_tracking.py +45 -0
  218. superqode/tools/lsp_tools.py +610 -0
  219. superqode/tools/network_tools.py +350 -0
  220. superqode/tools/permissions.py +400 -0
  221. superqode/tools/question_tool.py +324 -0
  222. superqode/tools/search_tools.py +598 -0
  223. superqode/tools/shell_tools.py +259 -0
  224. superqode/tools/todo_tools.py +121 -0
  225. superqode/tools/validation.py +80 -0
  226. superqode/tools/web_tools.py +639 -0
  227. superqode/tui.py +1152 -0
  228. superqode/tui_integration.py +875 -0
  229. superqode/tui_widgets/__init__.py +27 -0
  230. superqode/tui_widgets/widgets/__init__.py +18 -0
  231. superqode/tui_widgets/widgets/progress.py +185 -0
  232. superqode/tui_widgets/widgets/tool_display.py +188 -0
  233. superqode/undo_manager.py +574 -0
  234. superqode/utils/__init__.py +5 -0
  235. superqode/utils/error_handling.py +323 -0
  236. superqode/utils/fuzzy.py +257 -0
  237. superqode/widgets/__init__.py +477 -0
  238. superqode/widgets/agent_collab.py +390 -0
  239. superqode/widgets/agent_store.py +936 -0
  240. superqode/widgets/agent_switcher.py +395 -0
  241. superqode/widgets/animation_manager.py +284 -0
  242. superqode/widgets/code_context.py +356 -0
  243. superqode/widgets/command_palette.py +412 -0
  244. superqode/widgets/connection_status.py +537 -0
  245. superqode/widgets/conversation_history.py +470 -0
  246. superqode/widgets/diff_indicator.py +155 -0
  247. superqode/widgets/enhanced_status_bar.py +385 -0
  248. superqode/widgets/enhanced_toast.py +476 -0
  249. superqode/widgets/file_browser.py +809 -0
  250. superqode/widgets/file_reference.py +585 -0
  251. superqode/widgets/issue_timeline.py +340 -0
  252. superqode/widgets/leader_key.py +264 -0
  253. superqode/widgets/mode_switcher.py +445 -0
  254. superqode/widgets/model_picker.py +234 -0
  255. superqode/widgets/permission_preview.py +1205 -0
  256. superqode/widgets/prompt.py +358 -0
  257. superqode/widgets/provider_connect.py +725 -0
  258. superqode/widgets/pty_shell.py +587 -0
  259. superqode/widgets/qe_dashboard.py +321 -0
  260. superqode/widgets/resizable_sidebar.py +377 -0
  261. superqode/widgets/response_changes.py +218 -0
  262. superqode/widgets/response_display.py +528 -0
  263. superqode/widgets/rich_tool_display.py +613 -0
  264. superqode/widgets/sidebar_panels.py +1180 -0
  265. superqode/widgets/slash_complete.py +356 -0
  266. superqode/widgets/split_view.py +612 -0
  267. superqode/widgets/status_bar.py +273 -0
  268. superqode/widgets/superqode_display.py +786 -0
  269. superqode/widgets/thinking_display.py +815 -0
  270. superqode/widgets/throbber.py +87 -0
  271. superqode/widgets/toast.py +206 -0
  272. superqode/widgets/unified_output.py +1073 -0
  273. superqode/workspace/__init__.py +75 -0
  274. superqode/workspace/artifacts.py +472 -0
  275. superqode/workspace/coordinator.py +353 -0
  276. superqode/workspace/diff_tracker.py +429 -0
  277. superqode/workspace/git_guard.py +373 -0
  278. superqode/workspace/git_snapshot.py +526 -0
  279. superqode/workspace/manager.py +750 -0
  280. superqode/workspace/snapshot.py +357 -0
  281. superqode/workspace/watcher.py +535 -0
  282. superqode/workspace/worktree.py +440 -0
  283. superqode-0.1.5.dist-info/METADATA +204 -0
  284. superqode-0.1.5.dist-info/RECORD +288 -0
  285. superqode-0.1.5.dist-info/WHEEL +5 -0
  286. superqode-0.1.5.dist-info/entry_points.txt +3 -0
  287. superqode-0.1.5.dist-info/licenses/LICENSE +648 -0
  288. superqode-0.1.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,899 @@
1
+ """
2
+ Core QE Skills - Essential quality engineering skills.
3
+
4
+ Skills included:
5
+ - testability-scoring: Assess code testability
6
+ - tdd-london-chicago: TDD methodology guidance
7
+ - api-testing-patterns: API testing best practices
8
+ - accessibility-testing: A11y testing patterns
9
+ - shift-left-testing: Early testing strategies
10
+ - chaos-engineering-resilience: Chaos testing
11
+ - visual-testing-advanced: Visual regression
12
+ - compliance-testing: Regulatory compliance
13
+ """
14
+
15
+ from typing import Any, Dict, List, Optional
16
+ from pathlib import Path
17
+ import ast
18
+
19
+ from .base import Skill, SkillConfig, SkillResult
20
+
21
+
22
+ class TestabilityScoring(Skill):
23
+ """
24
+ Testability Scoring Skill.
25
+
26
+ Assesses code testability before writing tests,
27
+ identifying areas that need refactoring for better testing.
28
+ """
29
+
30
+ NAME = "testability-scoring"
31
+ DISPLAY_NAME = "Testability Scoring"
32
+ DESCRIPTION = "Pre-test code testability assessment"
33
+ CATEGORY = "analysis"
34
+ TAGS = ["testability", "code-quality", "pre-test"]
35
+
36
+ # Scoring factors
37
+ FACTORS = {
38
+ "cyclomatic_complexity": {"weight": 0.2, "ideal": 5, "max": 20},
39
+ "dependency_count": {"weight": 0.15, "ideal": 3, "max": 10},
40
+ "method_length": {"weight": 0.15, "ideal": 20, "max": 50},
41
+ "nesting_depth": {"weight": 0.15, "ideal": 2, "max": 5},
42
+ "global_state": {"weight": 0.15, "ideal": 0, "max": 3},
43
+ "side_effects": {"weight": 0.1, "ideal": 0, "max": 5},
44
+ "documentation": {"weight": 0.1, "ideal": 1, "max": 1},
45
+ }
46
+
47
+ async def execute(self, **kwargs) -> SkillResult:
48
+ """
49
+ Score code testability.
50
+
51
+ Args:
52
+ file_path: Path to file to analyze
53
+ code: Code string to analyze (alternative)
54
+
55
+ Returns:
56
+ SkillResult with testability score
57
+ """
58
+ file_path = kwargs.get("file_path")
59
+ code = kwargs.get("code")
60
+
61
+ if file_path:
62
+ code = Path(file_path).read_text()
63
+
64
+ if not code:
65
+ return SkillResult(skill_name=self.NAME, success=False, errors=["No code provided"])
66
+
67
+ try:
68
+ tree = ast.parse(code)
69
+ except SyntaxError as e:
70
+ return SkillResult(skill_name=self.NAME, success=False, errors=[f"Syntax error: {e}"])
71
+
72
+ # Analyze testability
73
+ scores = {}
74
+ recommendations = []
75
+
76
+ for node in ast.walk(tree):
77
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
78
+ func_score = self._score_function(node, code)
79
+ scores[node.name] = func_score
80
+
81
+ if func_score["overall"] < 0.7:
82
+ recommendations.append(
83
+ f"Function '{node.name}' has low testability ({func_score['overall']:.2f}). "
84
+ f"Consider refactoring."
85
+ )
86
+
87
+ # Calculate overall score
88
+ overall = sum(s["overall"] for s in scores.values()) / len(scores) if scores else 0
89
+
90
+ return SkillResult(
91
+ skill_name=self.NAME,
92
+ success=True,
93
+ output=f"Testability Score: {overall:.2f}/1.00",
94
+ metrics={
95
+ "overall_score": overall,
96
+ "function_scores": scores,
97
+ "recommendations": recommendations,
98
+ },
99
+ )
100
+
101
+ def _score_function(self, node: ast.FunctionDef, code: str) -> Dict[str, float]:
102
+ """Score a single function."""
103
+ scores = {}
104
+
105
+ # Cyclomatic complexity
106
+ complexity = self._calculate_complexity(node)
107
+ scores["complexity"] = self._normalize(complexity, self.FACTORS["cyclomatic_complexity"])
108
+
109
+ # Method length
110
+ lines = len(code.splitlines())
111
+ scores["length"] = self._normalize(lines, self.FACTORS["method_length"])
112
+
113
+ # Nesting depth
114
+ depth = self._calculate_nesting(node)
115
+ scores["nesting"] = self._normalize(depth, self.FACTORS["nesting_depth"])
116
+
117
+ # Calculate overall
118
+ overall = sum(scores.values()) / len(scores)
119
+ scores["overall"] = overall
120
+
121
+ return scores
122
+
123
+ def _calculate_complexity(self, node: ast.AST) -> int:
124
+ """Calculate cyclomatic complexity."""
125
+ complexity = 1
126
+ for child in ast.walk(node):
127
+ if isinstance(child, (ast.If, ast.While, ast.For, ast.ExceptHandler)):
128
+ complexity += 1
129
+ elif isinstance(child, (ast.And, ast.Or)):
130
+ complexity += 1
131
+ return complexity
132
+
133
+ def _calculate_nesting(self, node: ast.AST, depth: int = 0) -> int:
134
+ """Calculate max nesting depth."""
135
+ max_depth = depth
136
+ for child in ast.iter_child_nodes(node):
137
+ if isinstance(child, (ast.If, ast.While, ast.For, ast.With, ast.Try)):
138
+ child_depth = self._calculate_nesting(child, depth + 1)
139
+ max_depth = max(max_depth, child_depth)
140
+ else:
141
+ child_depth = self._calculate_nesting(child, depth)
142
+ max_depth = max(max_depth, child_depth)
143
+ return max_depth
144
+
145
+ def _normalize(self, value: float, factor: Dict[str, Any]) -> float:
146
+ """Normalize a value to 0-1 score (1 is best)."""
147
+ ideal = factor["ideal"]
148
+ max_val = factor["max"]
149
+
150
+ if value <= ideal:
151
+ return 1.0
152
+ elif value >= max_val:
153
+ return 0.0
154
+ else:
155
+ return 1.0 - (value - ideal) / (max_val - ideal)
156
+
157
+ def get_prompt(self) -> str:
158
+ return """You are an expert in code testability analysis.
159
+
160
+ Evaluate code for testability by considering:
161
+ 1. Cyclomatic complexity (lower is better)
162
+ 2. Dependency injection (prefer constructor injection)
163
+ 3. Pure functions (no side effects)
164
+ 4. Single responsibility (one purpose per function)
165
+ 5. Minimal global state
166
+ 6. Clear interfaces
167
+
168
+ Provide specific recommendations for improving testability."""
169
+
170
+
171
+ class TDDLondonChicago(Skill):
172
+ """
173
+ TDD London/Chicago Skill.
174
+
175
+ Guides TDD implementation using both London (mockist)
176
+ and Chicago (classicist) schools.
177
+ """
178
+
179
+ NAME = "tdd-london-chicago"
180
+ DISPLAY_NAME = "TDD London/Chicago"
181
+ DESCRIPTION = "TDD methodology guidance for both schools"
182
+ CATEGORY = "methodology"
183
+ TAGS = ["tdd", "testing", "methodology", "best-practices"]
184
+
185
+ async def execute(self, **kwargs) -> SkillResult:
186
+ """
187
+ Provide TDD guidance.
188
+
189
+ Args:
190
+ style: "london" or "chicago"
191
+ feature: Feature to implement
192
+ context: Additional context
193
+
194
+ Returns:
195
+ SkillResult with TDD guidance
196
+ """
197
+ style = kwargs.get("style", "chicago")
198
+ feature = kwargs.get("feature", "")
199
+
200
+ if style == "london":
201
+ guidance = self._london_style_guidance(feature)
202
+ else:
203
+ guidance = self._chicago_style_guidance(feature)
204
+
205
+ return SkillResult(
206
+ skill_name=self.NAME, success=True, output=guidance, metrics={"style": style}
207
+ )
208
+
209
+ def _london_style_guidance(self, feature: str) -> str:
210
+ return f"""# TDD London Style (Mockist) for: {feature}
211
+
212
+ ## Approach
213
+ The London school focuses on behavior and uses mocks extensively.
214
+
215
+ ## RED Phase
216
+ 1. Write a failing test that specifies expected behavior
217
+ 2. Mock all collaborators
218
+ 3. Focus on the unit's interaction with dependencies
219
+
220
+ ## GREEN Phase
221
+ 1. Implement minimum code to pass
222
+ 2. Focus on correct message passing
223
+ 3. Don't worry about implementation details
224
+
225
+ ## REFACTOR Phase
226
+ 1. Improve design while tests pass
227
+ 2. Extract interfaces if needed
228
+ 3. Consider dependency injection
229
+
230
+ ## Key Principles
231
+ - Test behavior, not implementation
232
+ - Mock external dependencies
233
+ - Verify interactions
234
+ - One mock per test (usually)
235
+
236
+ ## Example Pattern
237
+ ```python
238
+ def test_should_notify_when_order_placed():
239
+ # Arrange
240
+ notifier = Mock(spec=Notifier)
241
+ order_service = OrderService(notifier=notifier)
242
+
243
+ # Act
244
+ order_service.place_order(order)
245
+
246
+ # Assert
247
+ notifier.send.assert_called_once_with(order.customer_email)
248
+ ```
249
+ """
250
+
251
+ def _chicago_style_guidance(self, feature: str) -> str:
252
+ return f"""# TDD Chicago Style (Classicist) for: {feature}
253
+
254
+ ## Approach
255
+ The Chicago school focuses on state and uses real objects.
256
+
257
+ ## RED Phase
258
+ 1. Write a failing test with real assertions
259
+ 2. Test the final state/outcome
260
+ 3. Use real collaborators when possible
261
+
262
+ ## GREEN Phase
263
+ 1. Implement the simplest thing that works
264
+ 2. Let the design emerge
265
+ 3. Triangulate with more tests
266
+
267
+ ## REFACTOR Phase
268
+ 1. Remove duplication
269
+ 2. Improve naming
270
+ 3. Extract methods/classes
271
+
272
+ ## Key Principles
273
+ - Test state, not interactions
274
+ - Use real objects (not mocks)
275
+ - Triangulate to generalize
276
+ - Let design emerge from tests
277
+
278
+ ## Example Pattern
279
+ ```python
280
+ def test_order_total_includes_tax():
281
+ # Arrange
282
+ order = Order()
283
+ order.add_item(Product("Widget", price=100))
284
+
285
+ # Act
286
+ total = order.calculate_total(tax_rate=0.1)
287
+
288
+ # Assert
289
+ assert total == 110 # Price + 10% tax
290
+ ```
291
+ """
292
+
293
+ def get_prompt(self) -> str:
294
+ return """You are a TDD expert familiar with both London and Chicago schools.
295
+
296
+ London School (Mockist):
297
+ - Focus on behavior and interactions
298
+ - Heavy use of mocks
299
+ - Outside-in development
300
+ - Verify messages between objects
301
+
302
+ Chicago School (Classicist):
303
+ - Focus on state and outcomes
304
+ - Use real objects
305
+ - Inside-out development
306
+ - Assert on final state
307
+
308
+ Guide the user through RED/GREEN/REFACTOR cycles."""
309
+
310
+
311
+ class APITestingPatterns(Skill):
312
+ """
313
+ API Testing Patterns Skill.
314
+
315
+ Provides patterns for comprehensive API testing.
316
+ """
317
+
318
+ NAME = "api-testing-patterns"
319
+ DISPLAY_NAME = "API Testing Patterns"
320
+ DESCRIPTION = "API testing best practices and patterns"
321
+ CATEGORY = "testing"
322
+ TAGS = ["api", "testing", "rest", "patterns"]
323
+
324
+ async def execute(self, **kwargs) -> SkillResult:
325
+ """
326
+ Provide API testing patterns.
327
+
328
+ Args:
329
+ endpoint: API endpoint to test
330
+ method: HTTP method
331
+ pattern: Specific pattern to apply
332
+
333
+ Returns:
334
+ SkillResult with testing patterns
335
+ """
336
+ endpoint = kwargs.get("endpoint", "/api/resource")
337
+ method = kwargs.get("method", "GET")
338
+
339
+ patterns = self._get_patterns(endpoint, method)
340
+
341
+ return SkillResult(
342
+ skill_name=self.NAME,
343
+ success=True,
344
+ output=patterns,
345
+ metrics={"endpoint": endpoint, "method": method},
346
+ )
347
+
348
+ def _get_patterns(self, endpoint: str, method: str) -> str:
349
+ return f"""# API Testing Patterns for {method} {endpoint}
350
+
351
+ ## 1. Happy Path Testing
352
+ Test successful scenarios with valid inputs.
353
+
354
+ ## 2. Validation Testing
355
+ - Missing required fields
356
+ - Invalid data types
357
+ - Boundary values
358
+ - Malformed requests
359
+
360
+ ## 3. Authentication/Authorization
361
+ - Missing auth token
362
+ - Invalid token
363
+ - Expired token
364
+ - Insufficient permissions
365
+
366
+ ## 4. Error Handling
367
+ - 400 Bad Request
368
+ - 401 Unauthorized
369
+ - 403 Forbidden
370
+ - 404 Not Found
371
+ - 500 Internal Server Error
372
+
373
+ ## 5. Performance Testing
374
+ - Response time < 200ms
375
+ - Concurrent requests
376
+ - Rate limiting
377
+
378
+ ## 6. Contract Testing
379
+ - Schema validation
380
+ - Field presence
381
+ - Data types
382
+ - Nullable fields
383
+
384
+ ## Example Test Structure
385
+ ```python
386
+ class Test{method.capitalize()}{endpoint.replace("/", "_").title()}:
387
+
388
+ def test_success_returns_200(self, client):
389
+ response = client.{method.lower()}("{endpoint}")
390
+ assert response.status_code == 200
391
+
392
+ def test_missing_auth_returns_401(self, client):
393
+ response = client.{method.lower()}("{endpoint}", headers={{}})
394
+ assert response.status_code == 401
395
+
396
+ def test_invalid_input_returns_400(self, client):
397
+ response = client.{method.lower()}("{endpoint}", json={{"invalid": True}})
398
+ assert response.status_code == 400
399
+ ```
400
+ """
401
+
402
+ def get_prompt(self) -> str:
403
+ return """You are an API testing expert.
404
+
405
+ Key areas to cover:
406
+ 1. Happy path scenarios
407
+ 2. Error handling (4xx, 5xx)
408
+ 3. Input validation
409
+ 4. Authentication/authorization
410
+ 5. Rate limiting
411
+ 6. Pagination
412
+ 7. Caching headers
413
+ 8. Content negotiation
414
+
415
+ Provide specific test cases for each endpoint."""
416
+
417
+
418
+ class AccessibilityTesting(Skill):
419
+ """
420
+ Accessibility Testing Skill.
421
+
422
+ Guides A11y testing for WCAG compliance.
423
+ """
424
+
425
+ NAME = "accessibility-testing"
426
+ DISPLAY_NAME = "Accessibility Testing"
427
+ DESCRIPTION = "A11y testing patterns for WCAG compliance"
428
+ CATEGORY = "testing"
429
+ TAGS = ["accessibility", "a11y", "wcag", "testing"]
430
+
431
+ async def execute(self, **kwargs) -> SkillResult:
432
+ """
433
+ Provide accessibility testing guidance.
434
+
435
+ Args:
436
+ level: WCAG level (A, AA, AAA)
437
+ component: Component type to test
438
+
439
+ Returns:
440
+ SkillResult with A11y guidance
441
+ """
442
+ level = kwargs.get("level", "AA")
443
+ component = kwargs.get("component", "form")
444
+
445
+ guidance = self._get_guidance(level, component)
446
+
447
+ return SkillResult(
448
+ skill_name=self.NAME,
449
+ success=True,
450
+ output=guidance,
451
+ metrics={"level": level, "component": component},
452
+ )
453
+
454
+ def _get_guidance(self, level: str, component: str) -> str:
455
+ return f"""# Accessibility Testing for {component} (WCAG {level})
456
+
457
+ ## Essential Checks
458
+
459
+ ### 1. Keyboard Navigation
460
+ - All interactive elements focusable
461
+ - Logical focus order
462
+ - No keyboard traps
463
+ - Visible focus indicators
464
+
465
+ ### 2. Screen Reader Compatibility
466
+ - Proper ARIA labels
467
+ - Meaningful alt text
468
+ - Correct heading structure
469
+ - Live regions for dynamic content
470
+
471
+ ### 3. Color and Contrast
472
+ - 4.5:1 contrast for text (AA)
473
+ - 3:1 contrast for large text
474
+ - Information not conveyed by color alone
475
+
476
+ ### 4. Form Accessibility
477
+ - Labels associated with inputs
478
+ - Error messages identified
479
+ - Required fields indicated
480
+ - Form validation accessible
481
+
482
+ ## Testing Tools
483
+ - axe-core for automated testing
484
+ - NVDA/VoiceOver for screen reader testing
485
+ - Keyboard-only navigation testing
486
+ - Color contrast analyzers
487
+
488
+ ## Example Test
489
+ ```python
490
+ def test_form_has_accessible_labels():
491
+ page.goto("/form")
492
+ inputs = page.locator("input")
493
+
494
+ for input_elem in inputs.all():
495
+ # Check for associated label
496
+ label = page.locator(f'label[for="{{input_elem.get_attribute("id")}}"]')
497
+ assert label.count() > 0, f"Input missing label"
498
+ ```
499
+ """
500
+
501
+ def get_prompt(self) -> str:
502
+ return """You are an accessibility expert.
503
+
504
+ Test for WCAG compliance:
505
+ 1. Perceivable - content accessible to all senses
506
+ 2. Operable - keyboard navigable
507
+ 3. Understandable - clear and consistent
508
+ 4. Robust - works with assistive technology
509
+
510
+ Use axe-core for automated testing."""
511
+
512
+
513
+ class ShiftLeftTesting(Skill):
514
+ """
515
+ Shift-Left Testing Skill.
516
+
517
+ Promotes early testing practices.
518
+ """
519
+
520
+ NAME = "shift-left-testing"
521
+ DISPLAY_NAME = "Shift-Left Testing"
522
+ DESCRIPTION = "Early testing strategies and practices"
523
+ CATEGORY = "methodology"
524
+ TAGS = ["shift-left", "early-testing", "prevention"]
525
+
526
+ async def execute(self, **kwargs) -> SkillResult:
527
+ """
528
+ Provide shift-left testing guidance.
529
+
530
+ Args:
531
+ phase: Development phase
532
+ context: Project context
533
+
534
+ Returns:
535
+ SkillResult with guidance
536
+ """
537
+ phase = kwargs.get("phase", "design")
538
+
539
+ guidance = self._get_guidance(phase)
540
+
541
+ return SkillResult(
542
+ skill_name=self.NAME, success=True, output=guidance, metrics={"phase": phase}
543
+ )
544
+
545
+ def _get_guidance(self, phase: str) -> str:
546
+ return f"""# Shift-Left Testing for {phase.title()} Phase
547
+
548
+ ## Core Principle
549
+ Find defects earlier when they're cheaper to fix.
550
+
551
+ ## Activities by Phase
552
+
553
+ ### Requirements Phase
554
+ - Requirements review
555
+ - Testability assessment
556
+ - Risk analysis
557
+ - Acceptance criteria definition
558
+
559
+ ### Design Phase
560
+ - Design review
561
+ - API contract definition
562
+ - Test strategy creation
563
+ - Architecture testing
564
+
565
+ ### Development Phase
566
+ - Unit testing (TDD)
567
+ - Static analysis
568
+ - Code review
569
+ - Pair programming
570
+
571
+ ### Integration Phase
572
+ - Integration testing
573
+ - Contract testing
574
+ - Performance testing
575
+ - Security scanning
576
+
577
+ ## Benefits
578
+ - 10x cheaper to fix bugs in design vs production
579
+ - Faster feedback loops
580
+ - Better code quality
581
+ - Reduced technical debt
582
+
583
+ ## Implementation
584
+ 1. Include QE in planning
585
+ 2. Define test cases during design
586
+ 3. Automate early and often
587
+ 4. Continuous integration
588
+ 5. Quality gates at each phase
589
+ """
590
+
591
+ def get_prompt(self) -> str:
592
+ return """You are a shift-left testing advocate.
593
+
594
+ Key principles:
595
+ 1. Test early and often
596
+ 2. Prevention over detection
597
+ 3. Collaboration between dev and QE
598
+ 4. Automation from the start
599
+ 5. Continuous feedback
600
+
601
+ Help integrate testing into every phase."""
602
+
603
+
604
+ class ChaosEngineeringResilience(Skill):
605
+ """
606
+ Chaos Engineering Skill.
607
+
608
+ Guides chaos testing for system resilience.
609
+ """
610
+
611
+ NAME = "chaos-engineering-resilience"
612
+ DISPLAY_NAME = "Chaos Engineering"
613
+ DESCRIPTION = "Chaos testing for system resilience"
614
+ CATEGORY = "testing"
615
+ TAGS = ["chaos", "resilience", "reliability"]
616
+
617
+ async def execute(self, **kwargs) -> SkillResult:
618
+ """
619
+ Provide chaos engineering guidance.
620
+
621
+ Args:
622
+ target: System component to test
623
+ experiment: Type of chaos experiment
624
+
625
+ Returns:
626
+ SkillResult with chaos testing guidance
627
+ """
628
+ target = kwargs.get("target", "service")
629
+ experiment = kwargs.get("experiment", "latency")
630
+
631
+ guidance = self._get_guidance(target, experiment)
632
+
633
+ return SkillResult(
634
+ skill_name=self.NAME,
635
+ success=True,
636
+ output=guidance,
637
+ metrics={"target": target, "experiment": experiment},
638
+ )
639
+
640
+ def _get_guidance(self, target: str, experiment: str) -> str:
641
+ return f"""# Chaos Engineering for {target}
642
+
643
+ ## Experiment: {experiment.title()} Injection
644
+
645
+ ### Hypothesis
646
+ "When {experiment} is introduced to {target}, the system should..."
647
+
648
+ ### Steady State
649
+ Define normal behavior metrics:
650
+ - Response time < 200ms
651
+ - Error rate < 0.1%
652
+ - Throughput > 1000 req/s
653
+
654
+ ### Experiment Types
655
+ 1. **Latency**: Add network delays
656
+ 2. **Failure**: Kill processes/containers
657
+ 3. **Resource**: CPU/memory stress
658
+ 4. **Network**: Partition, packet loss
659
+ 5. **Dependency**: External service failure
660
+
661
+ ### Safety Measures
662
+ - Start in staging environment
663
+ - Use canary deployments
664
+ - Have rollback plan
665
+ - Monitor closely
666
+ - Limit blast radius
667
+
668
+ ### Tools
669
+ - Chaos Monkey (Netflix)
670
+ - Gremlin
671
+ - Litmus
672
+ - Chaos Toolkit
673
+
674
+ ### Example Experiment
675
+ ```yaml
676
+ experiment:
677
+ name: "{target}-{experiment}-test"
678
+ hypothesis:
679
+ title: "Service remains available under {experiment}"
680
+ method:
681
+ - type: action
682
+ name: inject-{experiment}
683
+ provider:
684
+ type: python
685
+ module: chaoslib.{experiment}
686
+ rollbacks:
687
+ - type: action
688
+ name: restore-normal
689
+ ```
690
+ """
691
+
692
+ def get_prompt(self) -> str:
693
+ return """You are a chaos engineering expert.
694
+
695
+ Guide chaos experiments:
696
+ 1. Define steady state
697
+ 2. Form hypothesis
698
+ 3. Run experiment
699
+ 4. Measure impact
700
+ 5. Improve resilience
701
+
702
+ Always prioritize safety and have rollback plans."""
703
+
704
+
705
+ class VisualTestingAdvanced(Skill):
706
+ """
707
+ Visual Testing Skill.
708
+
709
+ Advanced visual regression testing patterns.
710
+ """
711
+
712
+ NAME = "visual-testing-advanced"
713
+ DISPLAY_NAME = "Visual Testing Advanced"
714
+ DESCRIPTION = "Advanced visual comparison techniques"
715
+ CATEGORY = "testing"
716
+ TAGS = ["visual", "regression", "ui", "screenshot"]
717
+
718
+ async def execute(self, **kwargs) -> SkillResult:
719
+ """
720
+ Provide visual testing guidance.
721
+
722
+ Args:
723
+ component: Component to test
724
+ strategy: Testing strategy
725
+
726
+ Returns:
727
+ SkillResult with visual testing guidance
728
+ """
729
+ component = kwargs.get("component", "page")
730
+ strategy = kwargs.get("strategy", "full-page")
731
+
732
+ guidance = self._get_guidance(component, strategy)
733
+
734
+ return SkillResult(
735
+ skill_name=self.NAME,
736
+ success=True,
737
+ output=guidance,
738
+ metrics={"component": component, "strategy": strategy},
739
+ )
740
+
741
+ def _get_guidance(self, component: str, strategy: str) -> str:
742
+ return f"""# Visual Testing for {component}
743
+
744
+ ## Strategy: {strategy.title()}
745
+
746
+ ### Comparison Algorithms
747
+ 1. **Pixel Diff**: Direct pixel comparison
748
+ 2. **Perceptual**: Human-perception based
749
+ 3. **AI-based**: ML for smart comparison
750
+ 4. **Layout**: Structural comparison
751
+
752
+ ### Best Practices
753
+ - Consistent viewport sizes
754
+ - Stable test data
755
+ - Font loading wait
756
+ - Animation handling
757
+ - Cross-browser testing
758
+
759
+ ### Handling Flakiness
760
+ - Ignore dynamic regions
761
+ - Wait for stability
762
+ - Use tolerance thresholds
763
+ - Retry on failure
764
+
765
+ ### Tools
766
+ - Percy
767
+ - Applitools
768
+ - BackstopJS
769
+ - Playwright visual comparisons
770
+
771
+ ### Example Implementation
772
+ ```python
773
+ def test_visual_regression():
774
+ page.goto("/component")
775
+ page.wait_for_load_state("networkidle")
776
+
777
+ # Capture screenshot
778
+ screenshot = page.screenshot()
779
+
780
+ # Compare with baseline
781
+ assert_visual_match(
782
+ screenshot,
783
+ baseline="component-baseline.png",
784
+ threshold=0.98 # 98% similarity required
785
+ )
786
+ ```
787
+ """
788
+
789
+ def get_prompt(self) -> str:
790
+ return """You are a visual testing expert.
791
+
792
+ Cover:
793
+ 1. Baseline management
794
+ 2. Diff handling
795
+ 3. Cross-browser testing
796
+ 4. Responsive testing
797
+ 5. Dynamic content handling
798
+
799
+ Use appropriate tools and thresholds."""
800
+
801
+
802
+ class ComplianceTesting(Skill):
803
+ """
804
+ Compliance Testing Skill.
805
+
806
+ Regulatory compliance testing patterns.
807
+ """
808
+
809
+ NAME = "compliance-testing"
810
+ DISPLAY_NAME = "Compliance Testing"
811
+ DESCRIPTION = "Regulatory compliance test patterns"
812
+ CATEGORY = "testing"
813
+ TAGS = ["compliance", "regulatory", "gdpr", "hipaa"]
814
+
815
+ async def execute(self, **kwargs) -> SkillResult:
816
+ """
817
+ Provide compliance testing guidance.
818
+
819
+ Args:
820
+ regulation: Regulation to comply with
821
+ area: Area of compliance
822
+
823
+ Returns:
824
+ SkillResult with compliance guidance
825
+ """
826
+ regulation = kwargs.get("regulation", "GDPR")
827
+ area = kwargs.get("area", "data-privacy")
828
+
829
+ guidance = self._get_guidance(regulation, area)
830
+
831
+ return SkillResult(
832
+ skill_name=self.NAME,
833
+ success=True,
834
+ output=guidance,
835
+ metrics={"regulation": regulation, "area": area},
836
+ )
837
+
838
+ def _get_guidance(self, regulation: str, area: str) -> str:
839
+ return f"""# Compliance Testing for {regulation}
840
+
841
+ ## Focus Area: {area.title()}
842
+
843
+ ### {regulation} Requirements
844
+ - Data subject rights
845
+ - Consent management
846
+ - Data minimization
847
+ - Right to erasure
848
+ - Data portability
849
+
850
+ ### Test Categories
851
+
852
+ #### 1. Data Privacy Tests
853
+ - PII identification
854
+ - Data encryption
855
+ - Access controls
856
+ - Audit logging
857
+
858
+ #### 2. Consent Tests
859
+ - Consent collection
860
+ - Consent withdrawal
861
+ - Preference center
862
+ - Cookie consent
863
+
864
+ #### 3. Security Tests
865
+ - Authentication
866
+ - Authorization
867
+ - Data encryption
868
+ - Secure transmission
869
+
870
+ #### 4. Audit Tests
871
+ - Access logs
872
+ - Change history
873
+ - Data lineage
874
+ - Retention policies
875
+
876
+ ### Example Tests
877
+ ```python
878
+ def test_pii_is_encrypted_at_rest():
879
+ user = create_user(email="test@example.com")
880
+ raw_data = database.get_raw_record(user.id)
881
+ assert user.email not in raw_data # Should be encrypted
882
+
883
+ def test_user_can_request_data_deletion():
884
+ user = create_user()
885
+ request_deletion(user.id)
886
+ assert user_data_deleted(user.id)
887
+ ```
888
+ """
889
+
890
+ def get_prompt(self) -> str:
891
+ return """You are a compliance testing expert.
892
+
893
+ Cover regulations:
894
+ - GDPR (EU data protection)
895
+ - HIPAA (healthcare)
896
+ - SOC 2 (security)
897
+ - PCI DSS (payment cards)
898
+
899
+ Ensure tests validate compliance requirements."""