aat-devqa 1.0.0__tar.gz

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 (343) hide show
  1. aat_devqa-1.0.0/.claude/settings.local.json +19 -0
  2. aat_devqa-1.0.0/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  3. aat_devqa-1.0.0/.github/workflows/ci.yml +50 -0
  4. aat_devqa-1.0.0/.gitignore +64 -0
  5. aat_devqa-1.0.0/.pre-commit-config.yaml +7 -0
  6. aat_devqa-1.0.0/CONTRIBUTING.ko.md +286 -0
  7. aat_devqa-1.0.0/CONTRIBUTING.md +225 -0
  8. aat_devqa-1.0.0/LICENSE +21 -0
  9. aat_devqa-1.0.0/Makefile +29 -0
  10. aat_devqa-1.0.0/PKG-INFO +405 -0
  11. aat_devqa-1.0.0/README.ko.md +337 -0
  12. aat_devqa-1.0.0/README.md +348 -0
  13. aat_devqa-1.0.0/awt-skill/.claude-plugin/marketplace.json +28 -0
  14. aat_devqa-1.0.0/awt-skill/CONTRIBUTING.md +66 -0
  15. aat_devqa-1.0.0/awt-skill/LICENSE +669 -0
  16. aat_devqa-1.0.0/awt-skill/README.md +215 -0
  17. aat_devqa-1.0.0/awt-skill/awt/SKILL.md +300 -0
  18. aat_devqa-1.0.0/awt-skill/awt/references/cli-reference.md +140 -0
  19. aat_devqa-1.0.0/awt-skill/awt/references/config-reference.md +98 -0
  20. aat_devqa-1.0.0/awt-skill/awt/references/scenario-schema.md +116 -0
  21. aat_devqa-1.0.0/awt-skill/awt/templates/config-template.yaml +25 -0
  22. aat_devqa-1.0.0/awt-skill/awt/templates/scenario-template.yaml +30 -0
  23. aat_devqa-1.0.0/awt-skill/package.json +17 -0
  24. aat_devqa-1.0.0/blog_Img/awt_devto_cover.png +0 -0
  25. aat_devqa-1.0.0/cloud/BACKUP_RECOVERY.md +91 -0
  26. aat_devqa-1.0.0/cloud/Dockerfile +40 -0
  27. aat_devqa-1.0.0/cloud/README.md +235 -0
  28. aat_devqa-1.0.0/cloud/aat_cloud.db +0 -0
  29. aat_devqa-1.0.0/cloud/app/__init__.py +0 -0
  30. aat_devqa-1.0.0/cloud/app/auth.py +171 -0
  31. aat_devqa-1.0.0/cloud/app/auth_patterns.py +821 -0
  32. aat_devqa-1.0.0/cloud/app/config.py +89 -0
  33. aat_devqa-1.0.0/cloud/app/crawler.py +2072 -0
  34. aat_devqa-1.0.0/cloud/app/crypto.py +59 -0
  35. aat_devqa-1.0.0/cloud/app/database.py +26 -0
  36. aat_devqa-1.0.0/cloud/app/docparse.py +109 -0
  37. aat_devqa-1.0.0/cloud/app/executor.py +960 -0
  38. aat_devqa-1.0.0/cloud/app/fast_mode.py +229 -0
  39. aat_devqa-1.0.0/cloud/app/fix_guide_ai.py +385 -0
  40. aat_devqa-1.0.0/cloud/app/health.py +110 -0
  41. aat_devqa-1.0.0/cloud/app/main.py +197 -0
  42. aat_devqa-1.0.0/cloud/app/middleware.py +163 -0
  43. aat_devqa-1.0.0/cloud/app/models.py +311 -0
  44. aat_devqa-1.0.0/cloud/app/routers/__init__.py +0 -0
  45. aat_devqa-1.0.0/cloud/app/routers/ai_config.py +300 -0
  46. aat_devqa-1.0.0/cloud/app/routers/billing.py +212 -0
  47. aat_devqa-1.0.0/cloud/app/routers/documents.py +157 -0
  48. aat_devqa-1.0.0/cloud/app/routers/fix_guides.py +268 -0
  49. aat_devqa-1.0.0/cloud/app/routers/github.py +393 -0
  50. aat_devqa-1.0.0/cloud/app/routers/keys.py +85 -0
  51. aat_devqa-1.0.0/cloud/app/routers/scan.py +2390 -0
  52. aat_devqa-1.0.0/cloud/app/routers/tests.py +1609 -0
  53. aat_devqa-1.0.0/cloud/app/routers/v1.py +80 -0
  54. aat_devqa-1.0.0/cloud/app/scan_diff.py +197 -0
  55. aat_devqa-1.0.0/cloud/app/scenario_builder.py +588 -0
  56. aat_devqa-1.0.0/cloud/app/scenario_utils.py +2349 -0
  57. aat_devqa-1.0.0/cloud/app/schemas.py +398 -0
  58. aat_devqa-1.0.0/cloud/app/test_patterns.py +447 -0
  59. aat_devqa-1.0.0/cloud/app/worker.py +356 -0
  60. aat_devqa-1.0.0/cloud/app/ws.py +51 -0
  61. aat_devqa-1.0.0/cloud/docs/CI_CD_GUIDE.md +123 -0
  62. aat_devqa-1.0.0/cloud/docs/DEPLOYMENT.md +198 -0
  63. aat_devqa-1.0.0/cloud/frontend/.gitignore +41 -0
  64. aat_devqa-1.0.0/cloud/frontend/README.md +56 -0
  65. aat_devqa-1.0.0/cloud/frontend/eslint.config.mjs +18 -0
  66. aat_devqa-1.0.0/cloud/frontend/messages/en.json +731 -0
  67. aat_devqa-1.0.0/cloud/frontend/messages/ko.json +731 -0
  68. aat_devqa-1.0.0/cloud/frontend/next-env.d.ts +6 -0
  69. aat_devqa-1.0.0/cloud/frontend/next.config.ts +10 -0
  70. aat_devqa-1.0.0/cloud/frontend/package-lock.json +7384 -0
  71. aat_devqa-1.0.0/cloud/frontend/package.json +31 -0
  72. aat_devqa-1.0.0/cloud/frontend/postcss.config.mjs +7 -0
  73. aat_devqa-1.0.0/cloud/frontend/public/demo.gif +0 -0
  74. aat_devqa-1.0.0/cloud/frontend/public/demo.mp4 +0 -0
  75. aat_devqa-1.0.0/cloud/frontend/public/file.svg +1 -0
  76. aat_devqa-1.0.0/cloud/frontend/public/globe.svg +1 -0
  77. aat_devqa-1.0.0/cloud/frontend/public/llms-full.txt +369 -0
  78. aat_devqa-1.0.0/cloud/frontend/public/llms.txt +25 -0
  79. aat_devqa-1.0.0/cloud/frontend/public/logo-dark.png +0 -0
  80. aat_devqa-1.0.0/cloud/frontend/public/next.svg +1 -0
  81. aat_devqa-1.0.0/cloud/frontend/public/og-image.png +0 -0
  82. aat_devqa-1.0.0/cloud/frontend/public/robots.txt +7 -0
  83. aat_devqa-1.0.0/cloud/frontend/public/vercel.svg +1 -0
  84. aat_devqa-1.0.0/cloud/frontend/public/window.svg +1 -0
  85. aat_devqa-1.0.0/cloud/frontend/src/app/auth/callback/route.ts +38 -0
  86. aat_devqa-1.0.0/cloud/frontend/src/app/billing/layout.tsx +10 -0
  87. aat_devqa-1.0.0/cloud/frontend/src/app/billing/page.tsx +145 -0
  88. aat_devqa-1.0.0/cloud/frontend/src/app/dashboard/layout.tsx +13 -0
  89. aat_devqa-1.0.0/cloud/frontend/src/app/dashboard/page.tsx +1553 -0
  90. aat_devqa-1.0.0/cloud/frontend/src/app/favicon.ico +0 -0
  91. aat_devqa-1.0.0/cloud/frontend/src/app/forgot-password/page.tsx +99 -0
  92. aat_devqa-1.0.0/cloud/frontend/src/app/globals.css +38 -0
  93. aat_devqa-1.0.0/cloud/frontend/src/app/layout.tsx +93 -0
  94. aat_devqa-1.0.0/cloud/frontend/src/app/login/layout.tsx +13 -0
  95. aat_devqa-1.0.0/cloud/frontend/src/app/login/page.tsx +117 -0
  96. aat_devqa-1.0.0/cloud/frontend/src/app/opengraph-image.tsx +68 -0
  97. aat_devqa-1.0.0/cloud/frontend/src/app/page.tsx +636 -0
  98. aat_devqa-1.0.0/cloud/frontend/src/app/pricing/layout.tsx +10 -0
  99. aat_devqa-1.0.0/cloud/frontend/src/app/pricing/page.tsx +128 -0
  100. aat_devqa-1.0.0/cloud/frontend/src/app/privacy/page.tsx +281 -0
  101. aat_devqa-1.0.0/cloud/frontend/src/app/settings/layout.tsx +13 -0
  102. aat_devqa-1.0.0/cloud/frontend/src/app/settings/page.tsx +686 -0
  103. aat_devqa-1.0.0/cloud/frontend/src/app/signup/layout.tsx +13 -0
  104. aat_devqa-1.0.0/cloud/frontend/src/app/signup/page.tsx +172 -0
  105. aat_devqa-1.0.0/cloud/frontend/src/app/sitemap.ts +32 -0
  106. aat_devqa-1.0.0/cloud/frontend/src/app/status/layout.tsx +13 -0
  107. aat_devqa-1.0.0/cloud/frontend/src/app/status/page.tsx +180 -0
  108. aat_devqa-1.0.0/cloud/frontend/src/app/terms/page.tsx +260 -0
  109. aat_devqa-1.0.0/cloud/frontend/src/app/tests/[id]/page.tsx +1453 -0
  110. aat_devqa-1.0.0/cloud/frontend/src/app/tests/layout.tsx +13 -0
  111. aat_devqa-1.0.0/cloud/frontend/src/app/tests/page.tsx +212 -0
  112. aat_devqa-1.0.0/cloud/frontend/src/components/AuthProvider.tsx +63 -0
  113. aat_devqa-1.0.0/cloud/frontend/src/components/FileUpload.tsx +137 -0
  114. aat_devqa-1.0.0/cloud/frontend/src/components/Footer.tsx +62 -0
  115. aat_devqa-1.0.0/cloud/frontend/src/components/Header.tsx +165 -0
  116. aat_devqa-1.0.0/cloud/frontend/src/components/HeroAnimation.tsx +161 -0
  117. aat_devqa-1.0.0/cloud/frontend/src/components/LanguageToggle.tsx +25 -0
  118. aat_devqa-1.0.0/cloud/frontend/src/components/ScenarioEditor.tsx +113 -0
  119. aat_devqa-1.0.0/cloud/frontend/src/components/ScenarioReview.tsx +396 -0
  120. aat_devqa-1.0.0/cloud/frontend/src/components/ScenarioViewer.tsx +244 -0
  121. aat_devqa-1.0.0/cloud/frontend/src/components/ServerWarmup.tsx +60 -0
  122. aat_devqa-1.0.0/cloud/frontend/src/components/SocialLoginButtons.tsx +89 -0
  123. aat_devqa-1.0.0/cloud/frontend/src/components/StepIndicator.tsx +86 -0
  124. aat_devqa-1.0.0/cloud/frontend/src/components/TestProgress.tsx +517 -0
  125. aat_devqa-1.0.0/cloud/frontend/src/i18n/request.ts +28 -0
  126. aat_devqa-1.0.0/cloud/frontend/src/lib/api.ts +784 -0
  127. aat_devqa-1.0.0/cloud/frontend/src/lib/errorMessages.ts +75 -0
  128. aat_devqa-1.0.0/cloud/frontend/src/lib/supabase.ts +8 -0
  129. aat_devqa-1.0.0/cloud/frontend/src/middleware.ts +72 -0
  130. aat_devqa-1.0.0/cloud/frontend/tsconfig.json +34 -0
  131. aat_devqa-1.0.0/cloud/frontend/tsconfig.tsbuildinfo +1 -0
  132. aat_devqa-1.0.0/cloud/frontend/vercel.json +5 -0
  133. aat_devqa-1.0.0/cloud/requirements.txt +33 -0
  134. aat_devqa-1.0.0/cloud/scripts/backup.sh +76 -0
  135. aat_devqa-1.0.0/cloud/scripts/capture_fixture.py +132 -0
  136. aat_devqa-1.0.0/cloud/scripts/restore.sh +92 -0
  137. aat_devqa-1.0.0/cloud/tests/__init__.py +0 -0
  138. aat_devqa-1.0.0/cloud/tests/conftest.py +108 -0
  139. aat_devqa-1.0.0/cloud/tests/fixtures/automation_exercise.json +162 -0
  140. aat_devqa-1.0.0/cloud/tests/fixtures/demoqa.json +168 -0
  141. aat_devqa-1.0.0/cloud/tests/fixtures/expand_testing.json +144 -0
  142. aat_devqa-1.0.0/cloud/tests/fixtures/sample_scan_data.json +142 -0
  143. aat_devqa-1.0.0/cloud/tests/fixtures/saucedemo.json +179 -0
  144. aat_devqa-1.0.0/cloud/tests/fixtures/the_internet.json +141 -0
  145. aat_devqa-1.0.0/cloud/tests/output/.gitignore +3 -0
  146. aat_devqa-1.0.0/cloud/tests/output/automation_exercise_postproc_fixed.yaml +254 -0
  147. aat_devqa-1.0.0/cloud/tests/output/automation_exercise_postproc_raw.yaml +254 -0
  148. aat_devqa-1.0.0/cloud/tests/output/automation_exercise_run_single.yaml +254 -0
  149. aat_devqa-1.0.0/cloud/tests/output/demoqa_postproc_fixed.yaml +458 -0
  150. aat_devqa-1.0.0/cloud/tests/output/demoqa_postproc_raw.yaml +458 -0
  151. aat_devqa-1.0.0/cloud/tests/output/demoqa_run_single.yaml +429 -0
  152. aat_devqa-1.0.0/cloud/tests/output/expand_testing_postproc_fixed.yaml +262 -0
  153. aat_devqa-1.0.0/cloud/tests/output/expand_testing_postproc_raw.yaml +262 -0
  154. aat_devqa-1.0.0/cloud/tests/output/expand_testing_run_single.yaml +289 -0
  155. aat_devqa-1.0.0/cloud/tests/output/plan_ab_results.json +580 -0
  156. aat_devqa-1.0.0/cloud/tests/output/postproc_fixed.yaml +347 -0
  157. aat_devqa-1.0.0/cloud/tests/output/postproc_raw.yaml +347 -0
  158. aat_devqa-1.0.0/cloud/tests/output/run_001.yaml +335 -0
  159. aat_devqa-1.0.0/cloud/tests/output/run_002.yaml +335 -0
  160. aat_devqa-1.0.0/cloud/tests/output/run_003.yaml +335 -0
  161. aat_devqa-1.0.0/cloud/tests/output/run_004.yaml +335 -0
  162. aat_devqa-1.0.0/cloud/tests/output/run_005.yaml +335 -0
  163. aat_devqa-1.0.0/cloud/tests/output/run_single.yaml +335 -0
  164. aat_devqa-1.0.0/cloud/tests/output/sample_scan_data_postproc_fixed.yaml +335 -0
  165. aat_devqa-1.0.0/cloud/tests/output/sample_scan_data_postproc_raw.yaml +335 -0
  166. aat_devqa-1.0.0/cloud/tests/output/sample_scan_data_run_001.yaml +343 -0
  167. aat_devqa-1.0.0/cloud/tests/output/sample_scan_data_run_002.yaml +344 -0
  168. aat_devqa-1.0.0/cloud/tests/output/sample_scan_data_run_003.yaml +340 -0
  169. aat_devqa-1.0.0/cloud/tests/output/sample_scan_data_run_004.yaml +384 -0
  170. aat_devqa-1.0.0/cloud/tests/output/sample_scan_data_run_005.yaml +340 -0
  171. aat_devqa-1.0.0/cloud/tests/output/sample_scan_data_run_single.yaml +341 -0
  172. aat_devqa-1.0.0/cloud/tests/output/saucedemo_postproc_fixed.yaml +452 -0
  173. aat_devqa-1.0.0/cloud/tests/output/saucedemo_postproc_raw.yaml +452 -0
  174. aat_devqa-1.0.0/cloud/tests/output/saucedemo_run_single.yaml +451 -0
  175. aat_devqa-1.0.0/cloud/tests/output/saucedemo_scenarios/SC-001.yaml +81 -0
  176. aat_devqa-1.0.0/cloud/tests/output/saucedemo_scenarios/SC-002.yaml +140 -0
  177. aat_devqa-1.0.0/cloud/tests/output/saucedemo_scenarios/SC-003.yaml +230 -0
  178. aat_devqa-1.0.0/cloud/tests/output/the_internet_postproc_fixed.yaml +212 -0
  179. aat_devqa-1.0.0/cloud/tests/output/the_internet_postproc_raw.yaml +212 -0
  180. aat_devqa-1.0.0/cloud/tests/output/the_internet_run_single.yaml +288 -0
  181. aat_devqa-1.0.0/cloud/tests/test_api_key_auth.py +98 -0
  182. aat_devqa-1.0.0/cloud/tests/test_api_keys.py +80 -0
  183. aat_devqa-1.0.0/cloud/tests/test_auth.py +154 -0
  184. aat_devqa-1.0.0/cloud/tests/test_daily_limit.py +47 -0
  185. aat_devqa-1.0.0/cloud/tests/test_e2e_cloud.py +511 -0
  186. aat_devqa-1.0.0/cloud/tests/test_executor.py +67 -0
  187. aat_devqa-1.0.0/cloud/tests/test_health.py +51 -0
  188. aat_devqa-1.0.0/cloud/tests/test_patterns.py +191 -0
  189. aat_devqa-1.0.0/cloud/tests/test_phase_c.py +136 -0
  190. aat_devqa-1.0.0/cloud/tests/test_plan_ab.py +626 -0
  191. aat_devqa-1.0.0/cloud/tests/test_rate_limit.py +68 -0
  192. aat_devqa-1.0.0/cloud/tests/test_scenario_builder.py +218 -0
  193. aat_devqa-1.0.0/cloud/tests/test_schema.py +62 -0
  194. aat_devqa-1.0.0/cloud/tests/test_tests_api.py +353 -0
  195. aat_devqa-1.0.0/cloud/tests/test_v1_api.py +56 -0
  196. aat_devqa-1.0.0/cloud/tests/test_worker.py +366 -0
  197. aat_devqa-1.0.0/docs/API_REFERENCE.md +521 -0
  198. aat_devqa-1.0.0/docs/AWT_Agent_Skill_/341/204/214/341/205/251/341/206/274/341/204/222/341/205/241/341/206/270/341/204/200/341/205/241/341/204/213/341/205/265/341/204/203/341/205/263.md +572 -0
  199. aat_devqa-1.0.0/docs/AWT_Cost_Optimization_Plan.md +110 -0
  200. aat_devqa-1.0.0/docs/COMPARISON.md +102 -0
  201. aat_devqa-1.0.0/docs/FAQ.md +121 -0
  202. aat_devqa-1.0.0/docs/MAINTENANCE.md +65 -0
  203. aat_devqa-1.0.0/docs/QUICK_START.md +112 -0
  204. aat_devqa-1.0.0/docs/assets/demo.gif +0 -0
  205. aat_devqa-1.0.0/docs/assets/demo.mp4 +0 -0
  206. aat_devqa-1.0.0/docs/assets/logo-dark.png +0 -0
  207. aat_devqa-1.0.0/docs/assets/logo-light.png +0 -0
  208. aat_devqa-1.0.0/docs/check_sync.sh +141 -0
  209. aat_devqa-1.0.0/llms-full.txt +369 -0
  210. aat_devqa-1.0.0/llms.txt +25 -0
  211. aat_devqa-1.0.0/pyproject.toml +123 -0
  212. aat_devqa-1.0.0/render.yaml +30 -0
  213. aat_devqa-1.0.0/src/aat/__init__.py +3 -0
  214. aat_devqa-1.0.0/src/aat/adapters/__init__.py +24 -0
  215. aat_devqa-1.0.0/src/aat/adapters/base.py +84 -0
  216. aat_devqa-1.0.0/src/aat/adapters/claude.py +340 -0
  217. aat_devqa-1.0.0/src/aat/adapters/deepseek.py +61 -0
  218. aat_devqa-1.0.0/src/aat/adapters/gemini.py +72 -0
  219. aat_devqa-1.0.0/src/aat/adapters/ollama.py +337 -0
  220. aat_devqa-1.0.0/src/aat/adapters/openai_adapter.py +563 -0
  221. aat_devqa-1.0.0/src/aat/cli/__init__.py +0 -0
  222. aat_devqa-1.0.0/src/aat/cli/commands/__init__.py +0 -0
  223. aat_devqa-1.0.0/src/aat/cli/commands/analyze_cmd.py +132 -0
  224. aat_devqa-1.0.0/src/aat/cli/commands/config_cmd.py +76 -0
  225. aat_devqa-1.0.0/src/aat/cli/commands/cost_cmd.py +113 -0
  226. aat_devqa-1.0.0/src/aat/cli/commands/dashboard_cmd.py +47 -0
  227. aat_devqa-1.0.0/src/aat/cli/commands/doctor_cmd.py +273 -0
  228. aat_devqa-1.0.0/src/aat/cli/commands/generate_cmd.py +201 -0
  229. aat_devqa-1.0.0/src/aat/cli/commands/init_cmd.py +52 -0
  230. aat_devqa-1.0.0/src/aat/cli/commands/learn_cmd.py +141 -0
  231. aat_devqa-1.0.0/src/aat/cli/commands/learned_cmd.py +23 -0
  232. aat_devqa-1.0.0/src/aat/cli/commands/loop_cmd.py +418 -0
  233. aat_devqa-1.0.0/src/aat/cli/commands/report_cmd.py +25 -0
  234. aat_devqa-1.0.0/src/aat/cli/commands/run_cmd.py +363 -0
  235. aat_devqa-1.0.0/src/aat/cli/commands/serve_cmd.py +52 -0
  236. aat_devqa-1.0.0/src/aat/cli/commands/setup_cmd.py +145 -0
  237. aat_devqa-1.0.0/src/aat/cli/commands/start_cmd.py +442 -0
  238. aat_devqa-1.0.0/src/aat/cli/commands/validate_cmd.py +58 -0
  239. aat_devqa-1.0.0/src/aat/cli/main.py +68 -0
  240. aat_devqa-1.0.0/src/aat/core/__init__.py +0 -0
  241. aat_devqa-1.0.0/src/aat/core/config.py +143 -0
  242. aat_devqa-1.0.0/src/aat/core/connection.py +131 -0
  243. aat_devqa-1.0.0/src/aat/core/cost.py +231 -0
  244. aat_devqa-1.0.0/src/aat/core/events.py +207 -0
  245. aat_devqa-1.0.0/src/aat/core/exceptions.py +62 -0
  246. aat_devqa-1.0.0/src/aat/core/git_ops.py +146 -0
  247. aat_devqa-1.0.0/src/aat/core/loop.py +555 -0
  248. aat_devqa-1.0.0/src/aat/core/models.py +557 -0
  249. aat_devqa-1.0.0/src/aat/core/scenario_loader.py +166 -0
  250. aat_devqa-1.0.0/src/aat/dashboard/__init__.py +1 -0
  251. aat_devqa-1.0.0/src/aat/dashboard/app.py +1850 -0
  252. aat_devqa-1.0.0/src/aat/dashboard/events_ws.py +191 -0
  253. aat_devqa-1.0.0/src/aat/dashboard/static/index.html +2057 -0
  254. aat_devqa-1.0.0/src/aat/dashboard/subprocess_manager.py +186 -0
  255. aat_devqa-1.0.0/src/aat/engine/__init__.py +9 -0
  256. aat_devqa-1.0.0/src/aat/engine/base.py +104 -0
  257. aat_devqa-1.0.0/src/aat/engine/comparator.py +204 -0
  258. aat_devqa-1.0.0/src/aat/engine/desktop.py +363 -0
  259. aat_devqa-1.0.0/src/aat/engine/executor.py +684 -0
  260. aat_devqa-1.0.0/src/aat/engine/humanizer.py +209 -0
  261. aat_devqa-1.0.0/src/aat/engine/waiter.py +59 -0
  262. aat_devqa-1.0.0/src/aat/engine/web.py +350 -0
  263. aat_devqa-1.0.0/src/aat/learning/__init__.py +0 -0
  264. aat_devqa-1.0.0/src/aat/learning/matcher.py +65 -0
  265. aat_devqa-1.0.0/src/aat/learning/store.py +481 -0
  266. aat_devqa-1.0.0/src/aat/matchers/__init__.py +28 -0
  267. aat_devqa-1.0.0/src/aat/matchers/base.py +49 -0
  268. aat_devqa-1.0.0/src/aat/matchers/feature.py +190 -0
  269. aat_devqa-1.0.0/src/aat/matchers/hybrid.py +145 -0
  270. aat_devqa-1.0.0/src/aat/matchers/ocr.py +207 -0
  271. aat_devqa-1.0.0/src/aat/matchers/template.py +202 -0
  272. aat_devqa-1.0.0/src/aat/matchers/vision_ai.py +51 -0
  273. aat_devqa-1.0.0/src/aat/parsers/__init__.py +13 -0
  274. aat_devqa-1.0.0/src/aat/parsers/base.py +31 -0
  275. aat_devqa-1.0.0/src/aat/parsers/markdown_parser.py +61 -0
  276. aat_devqa-1.0.0/src/aat/reporters/__init__.py +9 -0
  277. aat_devqa-1.0.0/src/aat/reporters/base.py +40 -0
  278. aat_devqa-1.0.0/src/aat/reporters/markdown.py +207 -0
  279. aat_devqa-1.0.0/test-site/README.md +34 -0
  280. aat_devqa-1.0.0/test-site/app.py +78 -0
  281. aat_devqa-1.0.0/test-site/config.yaml +18 -0
  282. aat_devqa-1.0.0/test-site/docs/AWT_Demo_/341/204/200/341/205/265/341/204/222/341/205/254/341/206/250/341/204/211/341/205/245.md +77 -0
  283. aat_devqa-1.0.0/test-site/docs/AWT_Demo_/341/204/200/341/205/265/341/204/222/341/205/254/341/206/250/341/204/211/341/205/245_/341/204/200/341/205/241/341/206/253/341/204/205/341/205/243/341/206/250.md +15 -0
  284. aat_devqa-1.0.0/test-site/docs//352/270/260/355/232/215/354/204/234.md +85 -0
  285. aat_devqa-1.0.0/test-site/templates/base.html +217 -0
  286. aat_devqa-1.0.0/test-site/templates/index.html +15 -0
  287. aat_devqa-1.0.0/test-site/templates/login.html +22 -0
  288. aat_devqa-1.0.0/test-site/templates/main.html +15 -0
  289. aat_devqa-1.0.0/test-site/templates/register.html +26 -0
  290. aat_devqa-1.0.0/tests/__init__.py +0 -0
  291. aat_devqa-1.0.0/tests/conftest.py +1 -0
  292. aat_devqa-1.0.0/tests/integration/__init__.py +0 -0
  293. aat_devqa-1.0.0/tests/integration/test_loop_e2e.py +735 -0
  294. aat_devqa-1.0.0/tests/integration/test_matchers_real.py +466 -0
  295. aat_devqa-1.0.0/tests/test_abc_interfaces.py +183 -0
  296. aat_devqa-1.0.0/tests/test_adapters/__init__.py +0 -0
  297. aat_devqa-1.0.0/tests/test_adapters/test_claude.py +306 -0
  298. aat_devqa-1.0.0/tests/test_adapters/test_ollama.py +419 -0
  299. aat_devqa-1.0.0/tests/test_adapters/test_openai.py +447 -0
  300. aat_devqa-1.0.0/tests/test_cli/__init__.py +0 -0
  301. aat_devqa-1.0.0/tests/test_cli/test_analyze_cmd.py +131 -0
  302. aat_devqa-1.0.0/tests/test_cli/test_config_cmd.py +115 -0
  303. aat_devqa-1.0.0/tests/test_cli/test_generate_cmd.py +255 -0
  304. aat_devqa-1.0.0/tests/test_cli/test_init_cmd.py +160 -0
  305. aat_devqa-1.0.0/tests/test_cli/test_learn_cmd.py +168 -0
  306. aat_devqa-1.0.0/tests/test_cli/test_loop_cmd.py +52 -0
  307. aat_devqa-1.0.0/tests/test_cli/test_run_cmd.py +23 -0
  308. aat_devqa-1.0.0/tests/test_cli/test_serve_cmd.py +33 -0
  309. aat_devqa-1.0.0/tests/test_cli/test_start_cmd.py +32 -0
  310. aat_devqa-1.0.0/tests/test_cli/test_validate_cmd.py +107 -0
  311. aat_devqa-1.0.0/tests/test_config.py +224 -0
  312. aat_devqa-1.0.0/tests/test_core/__init__.py +0 -0
  313. aat_devqa-1.0.0/tests/test_core/test_connection.py +348 -0
  314. aat_devqa-1.0.0/tests/test_core/test_events.py +265 -0
  315. aat_devqa-1.0.0/tests/test_core/test_git_ops.py +193 -0
  316. aat_devqa-1.0.0/tests/test_dashboard/__init__.py +0 -0
  317. aat_devqa-1.0.0/tests/test_dashboard/test_app.py +556 -0
  318. aat_devqa-1.0.0/tests/test_dashboard/test_events_ws.py +146 -0
  319. aat_devqa-1.0.0/tests/test_dashboard/test_subprocess_manager.py +174 -0
  320. aat_devqa-1.0.0/tests/test_engine/__init__.py +0 -0
  321. aat_devqa-1.0.0/tests/test_engine/test_comparator.py +211 -0
  322. aat_devqa-1.0.0/tests/test_engine/test_desktop.py +418 -0
  323. aat_devqa-1.0.0/tests/test_engine/test_executor.py +715 -0
  324. aat_devqa-1.0.0/tests/test_engine/test_humanizer.py +129 -0
  325. aat_devqa-1.0.0/tests/test_engine/test_waiter.py +66 -0
  326. aat_devqa-1.0.0/tests/test_engine/test_web_engine.py +187 -0
  327. aat_devqa-1.0.0/tests/test_exceptions.py +61 -0
  328. aat_devqa-1.0.0/tests/test_learning/__init__.py +0 -0
  329. aat_devqa-1.0.0/tests/test_learning/test_matcher.py +120 -0
  330. aat_devqa-1.0.0/tests/test_learning/test_store.py +136 -0
  331. aat_devqa-1.0.0/tests/test_loop.py +478 -0
  332. aat_devqa-1.0.0/tests/test_matchers/__init__.py +0 -0
  333. aat_devqa-1.0.0/tests/test_matchers/test_feature.py +139 -0
  334. aat_devqa-1.0.0/tests/test_matchers/test_hybrid.py +256 -0
  335. aat_devqa-1.0.0/tests/test_matchers/test_ocr.py +223 -0
  336. aat_devqa-1.0.0/tests/test_matchers/test_template.py +172 -0
  337. aat_devqa-1.0.0/tests/test_matchers/test_vision_ai.py +25 -0
  338. aat_devqa-1.0.0/tests/test_models.py +742 -0
  339. aat_devqa-1.0.0/tests/test_parsers/__init__.py +0 -0
  340. aat_devqa-1.0.0/tests/test_parsers/test_markdown_parser.py +143 -0
  341. aat_devqa-1.0.0/tests/test_reporters/__init__.py +0 -0
  342. aat_devqa-1.0.0/tests/test_reporters/test_markdown.py +224 -0
  343. aat_devqa-1.0.0/tests/test_scenario_loader.py +266 -0
@@ -0,0 +1,19 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(TOKEN=\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXItMDAxIiwicm9sZSI6ImF1dGhlbnRpY2F0ZWQiLCJhdWQiOiJhdXRoZW50aWNhdGVkIiwiaWF0IjoxNzcxNzc1MTY2LCJleHAiOjE3NzE3Nzg3NjZ9.hqqiwgpS0gSexiMWixcsTrlaVMGhNJO-BBNSmRsoRkk\")",
5
+ "Bash(__NEW_LINE_235143f4d0a68954__ curl -s -X POST http://127.0.0.1:8000/api/scans -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" -d '{\"\"url\"\": \"\"https://errcode.co.kr\"\", \"\"max_pages\"\": 3}')",
6
+ "Bash(python3:*)",
7
+ "Bash(__NEW_LINE_d2d54d808ebacd0a__ curl -s -X POST http://127.0.0.1:8000/api/scan -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" -d '{\"\"url\"\": \"\"https://errcode.co.kr\"\", \"\"max_pages\"\": 3}')",
8
+ "Bash(__NEW_LINE_64300031d61389f5__ curl -s -X POST http://127.0.0.1:8000/api/scan -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" -d '{\"\"url\"\": \"\"https://errcode.co.kr\"\", \"\"max_pages\"\": 3}')",
9
+ "Bash(__NEW_LINE_f039b8502301214b__ curl -v -X POST http://127.0.0.1:8000/api/scan -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" -d '{\"\"url\"\": \"\"https://errcode.co.kr\"\", \"\"max_pages\"\": 3}')",
10
+ "Bash(source:*)",
11
+ "Bash(python -m uvicorn:*)",
12
+ "Bash(curl:*)",
13
+ "Bash(__NEW_LINE_a05475a8b0e3beb7__ curl -s -X POST http://127.0.0.1:8000/api/scan -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" -d '{\"\"url\"\": \"\"https://errcode.co.kr\"\", \"\"max_pages\"\": 3}')",
14
+ "Bash(__NEW_LINE_a439d22f4994d432__ curl -s -X POST http://127.0.0.1:8000/api/scan -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" -d '{\"\"target_url\"\": \"\"https://errcode.co.kr\"\", \"\"max_pages\"\": 3}')",
15
+ "Bash(git add:*)",
16
+ "Bash(sleep:*)"
17
+ ]
18
+ }
19
+ }
@@ -0,0 +1,15 @@
1
+ ## Changes
2
+
3
+ -
4
+
5
+ ## Documentation Checklist
6
+
7
+ - [ ] `README.md` updated (if features/install/usage changed)
8
+ - [ ] `docs/API_REFERENCE.md` updated (if endpoints changed)
9
+ - [ ] `docs/QUICK_START.md` updated (if setup/usage changed)
10
+ - [ ] `docs/FAQ.md` updated (if user-facing behavior changed)
11
+ - [ ] `cloud/docs/CI_CD_GUIDE.md` updated (if API auth/endpoints changed)
12
+ - [ ] `en.json` updated (if UI text added/changed)
13
+ - [ ] `ko.json` structure synced with `en.json`
14
+ - [ ] `cloud/BACKUP_RECOVERY.md` updated (if DB schema changed)
15
+ - [ ] No docs update needed (explain why):
@@ -0,0 +1,50 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ lint-and-test:
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ python-version: ["3.11", "3.12"]
20
+
21
+ steps:
22
+ - name: Checkout repository
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Install system dependencies
26
+ run: |
27
+ sudo apt-get update
28
+ sudo apt-get install -y tesseract-ocr
29
+
30
+ - name: Setup Python ${{ matrix.python-version }}
31
+ uses: actions/setup-python@v5
32
+ with:
33
+ python-version: ${{ matrix.python-version }}
34
+ cache: pip
35
+ cache-dependency-path: pyproject.toml
36
+
37
+ - name: Install dependencies
38
+ run: |
39
+ python -m pip install --upgrade pip
40
+ pip install -e ".[dev]"
41
+ playwright install --with-deps chromium
42
+
43
+ - name: Lint with Ruff
44
+ run: ruff check src/ tests/
45
+
46
+ - name: Type check with Mypy
47
+ run: mypy src/aat/
48
+
49
+ - name: Run tests with Pytest
50
+ run: pytest tests/ --tb=short -q
@@ -0,0 +1,64 @@
1
+ # PM documents (internal)
2
+ PM/
3
+
4
+ # Project config (may contain API keys)
5
+ aat.config.yaml
6
+
7
+ # Claude Code project guide (internal)
8
+ CLAUDE.md
9
+
10
+ # AAT runtime data (config, learned DB, screenshots, uploaded docs)
11
+ .aat/
12
+
13
+ # Reports (large files)
14
+ reports/
15
+
16
+ # Python
17
+ __pycache__/
18
+ *.pyc
19
+ *.pyo
20
+ .pytest_cache/
21
+ .mypy_cache/
22
+ .ruff_cache/
23
+ htmlcov/
24
+ dist/
25
+ build/
26
+ *.egg-info/
27
+
28
+ # IDE
29
+ .vscode/
30
+ .idea/
31
+
32
+ # OS
33
+ .DS_Store
34
+ Thumbs.db
35
+
36
+ # Environment
37
+ .env
38
+ .venv/
39
+ venv/
40
+
41
+ # Cloud backend local DB + screenshots
42
+ awt_cloud.db
43
+ cloud/screenshots/
44
+ cloud/cloud/
45
+ cloud/uploads/
46
+ cloud/sample_spec.md
47
+
48
+ # Frontend
49
+ cloud/frontend/node_modules/
50
+ cloud/frontend/.next/
51
+ cloud/frontend/.env.local
52
+ .next/
53
+
54
+ # Uploads (runtime)
55
+ uploads/
56
+
57
+ # Scenarios (local test files)
58
+ scenarios/
59
+
60
+ # AAT data
61
+ .aat/config.yaml
62
+ .aat/learned.db
63
+ .aat/screenshots/
64
+ reports/
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.4.0
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
@@ -0,0 +1,286 @@
1
+ # 기여 가이드
2
+
3
+ AAT 프로젝트에 기여해 주셔서 감사합니다. 이 문서는 개발 환경 설정부터 PR 제출까지의 과정을 설명합니다.
4
+
5
+ ---
6
+
7
+ ## 개발 환경 설정
8
+
9
+ ### 필수 조건
10
+
11
+ - Python 3.11 이상
12
+ - Tesseract OCR (`brew install tesseract` 또는 `apt-get install tesseract-ocr`)
13
+ - Git
14
+
15
+ ### 설치
16
+
17
+ ```bash
18
+ git clone <repo-url> && cd AI_Auto_Tester
19
+ make dev
20
+ ```
21
+
22
+ `make dev`는 다음을 수행한다:
23
+
24
+ ```makefile
25
+ dev:
26
+ pip install -e ".[dev]" # 패키지 + 개발 의존성 설치
27
+ playwright install chromium # Chromium 브라우저 설치
28
+ pre-commit install # pre-commit 훅 설치
29
+ ```
30
+
31
+ ### 가상 환경 (권장)
32
+
33
+ ```bash
34
+ python -m venv .venv
35
+ source .venv/bin/activate # macOS/Linux
36
+ make dev
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 코드 스타일
42
+
43
+ ### ruff (린터 + 포매터)
44
+
45
+ 프로젝트는 ruff를 린터와 포매터로 사용한다. 설정은 `pyproject.toml`에 정의되어 있다.
46
+
47
+ ```toml
48
+ [tool.ruff]
49
+ target-version = "py311"
50
+ line-length = 99
51
+ src = ["src"]
52
+
53
+ [tool.ruff.lint]
54
+ select = ["E", "F", "I", "N", "UP", "B", "SIM", "TCH"]
55
+ ```
56
+
57
+ 주요 규칙:
58
+
59
+ | 코드 | 설명 |
60
+ |------|------|
61
+ | `E`, `F` | pyflakes, pycodestyle 기본 규칙 |
62
+ | `I` | import 정렬 (isort) |
63
+ | `N` | 네이밍 컨벤션 |
64
+ | `UP` | Python 3.11+ 문법으로 업그레이드 |
65
+ | `B` | bugbear (잠재적 버그) |
66
+ | `SIM` | 코드 단순화 |
67
+ | `TCH` | TYPE_CHECKING 블록 사용 |
68
+
69
+ ```bash
70
+ # 린트 검사
71
+ make lint
72
+
73
+ # 자동 포맷 + 자동 수정
74
+ make format
75
+ ```
76
+
77
+ ### mypy (타입 검사)
78
+
79
+ strict 모드로 동작한다. 모든 함수에 타입 힌트를 작성해야 한다.
80
+
81
+ ```toml
82
+ [tool.mypy]
83
+ python_version = "3.11"
84
+ strict = true
85
+ warn_return_any = true
86
+ warn_unused_configs = true
87
+ ```
88
+
89
+ ```bash
90
+ make typecheck
91
+ ```
92
+
93
+ ### pre-commit
94
+
95
+ 커밋 시 ruff 린트와 포맷이 자동으로 실행된다. `.pre-commit-config.yaml`에 정의되어 있다.
96
+
97
+ ```bash
98
+ # 수동 실행 (전체 파일)
99
+ pre-commit run --all-files
100
+ ```
101
+
102
+ ---
103
+
104
+ ## 테스트
105
+
106
+ ### 테스트 실행
107
+
108
+ ```bash
109
+ # 전체 테스트
110
+ make test
111
+
112
+ # 커버리지 포함
113
+ make test-cov
114
+ ```
115
+
116
+ `make test-cov`는 터미널 리포트와 HTML 리포트(`htmlcov/`)를 모두 생성한다.
117
+
118
+ ### 테스트 설정
119
+
120
+ ```toml
121
+ [tool.pytest.ini_options]
122
+ testpaths = ["tests"]
123
+ asyncio_mode = "auto"
124
+ addopts = "-v --tb=short"
125
+ ```
126
+
127
+ - `asyncio_mode = "auto"` -- async 테스트 함수를 자동으로 감지한다. `@pytest.mark.asyncio` 데코레이터가 필요 없다.
128
+ - `addopts = "-v --tb=short"` -- 상세 출력, 짧은 트레이스백.
129
+
130
+ ### 테스트 구조
131
+
132
+ ```
133
+ tests/
134
+ ├── conftest.py # 공통 fixtures
135
+ ├── test_engine/ # engine 모듈 테스트
136
+ ├── test_matchers/ # matchers 모듈 테스트
137
+ ├── test_adapters/ # adapters 모듈 테스트
138
+ ├── test_learning/ # learning 모듈 테스트
139
+ └── integration/ # 통합 테스트
140
+ ```
141
+
142
+ ### 테스트 작성 규칙
143
+
144
+ - 파일명: `test_<모듈명>.py`
145
+ - 함수명: `test_<동작>_<조건>_<기대결과>` (예: `test_match_with_low_confidence_returns_none`)
146
+ - fixture 활용: 공통 setup은 `conftest.py`에 정의한다.
147
+ - 외부 의존성(API, 브라우저)은 mock으로 대체한다.
148
+
149
+ ---
150
+
151
+ ## PR 프로세스
152
+
153
+ ### 1. 브랜치 생성
154
+
155
+ ```bash
156
+ git checkout -b feat/<기능명> # 기능 추가
157
+ git checkout -b fix/<버그명> # 버그 수정
158
+ git checkout -b refactor/<대상> # 리팩토링
159
+ ```
160
+
161
+ ### 2. 개발 및 검증
162
+
163
+ ```bash
164
+ # 코드 작성 후
165
+ make format # 포맷 + 린트 자동 수정
166
+ make lint # 린트 검사
167
+ make typecheck # 타입 검사
168
+ make test # 테스트
169
+ ```
170
+
171
+ 네 가지 검사를 모두 통과해야 PR을 제출할 수 있다.
172
+
173
+ ### 3. 커밋
174
+
175
+ 커밋 메시지 형식:
176
+
177
+ ```
178
+ <type>(<scope>): <subject>
179
+
180
+ <body>
181
+ ```
182
+
183
+ | type | 설명 |
184
+ |------|------|
185
+ | `feat` | 새 기능 |
186
+ | `fix` | 버그 수정 |
187
+ | `refactor` | 리팩토링 (기능 변경 없음) |
188
+ | `test` | 테스트 추가/수정 |
189
+ | `docs` | 문서 변경 |
190
+ | `chore` | 빌드, CI, 의존성 등 |
191
+
192
+ 예시:
193
+
194
+ ```
195
+ feat(matchers): add FeatureMatcher with ORB descriptor
196
+
197
+ ORB 기반 특징점 매칭을 구현한다. 스케일/회전 변환에 강건한 매칭이 가능해진다.
198
+ ```
199
+
200
+ ### 4. PR 제출
201
+
202
+ - PR 제목은 커밋 메시지와 동일한 형식을 따른다.
203
+ - 변경 내용, 테스트 방법, 관련 이슈를 본문에 기술한다.
204
+ - 가능하면 스크린샷이나 로그를 첨부한다.
205
+
206
+ ---
207
+
208
+ ## 아키텍처 개요
209
+
210
+ AAT는 플러그인 기반 아키텍처를 따른다. 각 모듈은 ABC(추상 기본 클래스)를 상속받아 구현하며, Registry에 등록하여 사용한다.
211
+
212
+ ### 플러그인 구조
213
+
214
+ ```
215
+ BaseEngine (ABC) --> ENGINE_REGISTRY
216
+ ├── WebEngine (Playwright)
217
+ └── (향후) DesktopEngine
218
+
219
+ BaseMatcher (ABC) --> MATCHER_REGISTRY
220
+ ├── TemplateMatcher (cv2.matchTemplate)
221
+ ├── OCRMatcher (pytesseract)
222
+ ├── FeatureMatcher (ORB/SIFT)
223
+ └── HybridMatcher (체인 오케스트레이터)
224
+
225
+ AIAdapter (ABC) --> ADAPTER_REGISTRY
226
+ └── ClaudeAdapter (anthropic SDK)
227
+
228
+ BaseParser (ABC) --> PARSER_REGISTRY
229
+ └── MarkdownParser
230
+
231
+ BaseReporter (ABC) --> REPORTER_REGISTRY
232
+ └── MarkdownReporter (Jinja2)
233
+ ```
234
+
235
+ ### 새 플러그인 추가 방법
236
+
237
+ 1. 해당 모듈의 ABC를 상속받는 클래스를 작성한다.
238
+ 2. 모듈의 `__init__.py`에 정의된 Registry에 등록한다.
239
+ 3. 테스트를 작성한다.
240
+
241
+ 예시 -- 새 Matcher 추가:
242
+
243
+ ```python
244
+ # src/aat/matchers/my_matcher.py
245
+ from aat.matchers.base import BaseMatcher, MatchResult
246
+
247
+ class MyMatcher(BaseMatcher):
248
+ name = "my_matcher"
249
+
250
+ async def match(self, screenshot: bytes, target: MatchTarget) -> MatchResult | None:
251
+ # 구현
252
+ ...
253
+ ```
254
+
255
+ ```python
256
+ # src/aat/matchers/__init__.py
257
+ from aat.matchers.my_matcher import MyMatcher
258
+
259
+ MATCHER_REGISTRY["my_matcher"] = MyMatcher
260
+ ```
261
+
262
+ ### 핵심 흐름
263
+
264
+ 1. **CLI** -- Typer가 사용자 명령을 파싱한다.
265
+ 2. **ScenarioLoader** -- YAML 파일을 Pydantic 모델(`Scenario`)로 변환한다.
266
+ 3. **StepExecutor** -- 시나리오의 각 스텝을 순서대로 실행한다.
267
+ 4. **Engine** -- 브라우저를 제어한다 (navigate, click, type 등).
268
+ 5. **Matcher** -- 스크린샷에서 대상 UI 요소의 좌표를 찾는다.
269
+ 6. **Comparator** -- 기대 결과와 실제 결과를 비교하여 Pass/Fail을 판정한다.
270
+ 7. **DevQA Loop** -- 실패 시 AI Adapter를 호출하여 수정안을 받고 재실행한다.
271
+ 8. **Reporter** -- 실행 결과를 Markdown 리포트로 생성한다.
272
+
273
+ ---
274
+
275
+ ## Make 명령어 요약
276
+
277
+ | 명령어 | 설명 |
278
+ |--------|------|
279
+ | `make install` | 런타임 의존성만 설치 |
280
+ | `make dev` | 개발 환경 전체 설정 |
281
+ | `make lint` | ruff 린트 검사 |
282
+ | `make format` | ruff 포맷 + 자동 수정 |
283
+ | `make typecheck` | mypy strict 타입 검사 |
284
+ | `make test` | pytest 전체 실행 |
285
+ | `make test-cov` | pytest + 커버리지 리포트 |
286
+ | `make clean` | 캐시, 빌드 산출물 정리 |
@@ -0,0 +1,225 @@
1
+ # Contributing to AWT
2
+
3
+ Thank you for your interest in contributing! This guide covers everything you need to get started.
4
+
5
+ ---
6
+
7
+ ## Development Setup
8
+
9
+ ### Prerequisites
10
+
11
+ - Python 3.11+
12
+ - [Tesseract OCR](https://github.com/tesseract-ocr/tesseract) (`brew install tesseract` / `apt install tesseract-ocr`)
13
+ - Git
14
+
15
+ ### Installation
16
+
17
+ ```bash
18
+ git clone https://github.com/ksgisang/AI-Watch-Tester.git
19
+ cd AI-Watch-Tester
20
+ python -m venv .venv && source .venv/bin/activate
21
+ make dev
22
+ ```
23
+
24
+ `make dev` will:
25
+
26
+ 1. Install the package in editable mode with dev dependencies
27
+ 2. Install Playwright Chromium browser
28
+ 3. Set up pre-commit hooks
29
+
30
+ ---
31
+
32
+ ## Code Style
33
+
34
+ ### ruff (Linter + Formatter)
35
+
36
+ ```bash
37
+ make lint # Check for issues
38
+ make format # Auto-format + auto-fix
39
+ ```
40
+
41
+ Key rules enforced: pyflakes, pycodestyle, import sorting, naming conventions, Python 3.11+ syntax, bugbear, and code simplification.
42
+
43
+ Configuration is in `pyproject.toml`:
44
+
45
+ ```toml
46
+ [tool.ruff]
47
+ target-version = "py311"
48
+ line-length = 99
49
+
50
+ [tool.ruff.lint]
51
+ select = ["E", "F", "I", "N", "UP", "B", "SIM", "TCH"]
52
+ ```
53
+
54
+ ### mypy (Type Checking)
55
+
56
+ Runs in **strict mode**. All functions must have type annotations.
57
+
58
+ ```bash
59
+ make typecheck
60
+ ```
61
+
62
+ ### pre-commit
63
+
64
+ Ruff lint and format run automatically on every commit via `.pre-commit-config.yaml`.
65
+
66
+ ```bash
67
+ # Run manually on all files
68
+ pre-commit run --all-files
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Running Tests
74
+
75
+ ```bash
76
+ # Regular tests (free, no AI calls)
77
+ pytest tests/
78
+ pytest cloud/tests/
79
+
80
+ # E2E tests (AI API calls, costs money)
81
+ pytest cloud/tests/ -m e2e
82
+ ```
83
+
84
+ > **Warning**
85
+ > E2E tests call the OpenAI API and may incur costs (~$1-2 per run).
86
+ > Regular tests do not require an API key and are always free to run.
87
+ > Please run regular tests before submitting a PR.
88
+ > E2E tests are run automatically in CI after PR review.
89
+
90
+ ### Test Writing Rules
91
+
92
+ - File name: `test_<module>.py`
93
+ - Function name: `test_<action>_<condition>_<expected>`
94
+ - Use fixtures from `conftest.py` for common setup
95
+ - Mock external dependencies (APIs, browsers)
96
+ - `asyncio_mode = "auto"` — no `@pytest.mark.asyncio` decorator needed
97
+
98
+ ### Test Structure
99
+
100
+ ```
101
+ tests/
102
+ ├── conftest.py # Shared fixtures
103
+ ├── test_engine/ # Engine module tests
104
+ ├── test_matchers/ # Matchers module tests
105
+ ├── test_adapters/ # Adapters module tests
106
+ ├── test_learning/ # Learning module tests
107
+ └── integration/ # Integration tests
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Pull Request Process
113
+
114
+ ### 1. Create a Branch
115
+
116
+ ```bash
117
+ git checkout -b feat/<feature> # New feature
118
+ git checkout -b fix/<bug> # Bug fix
119
+ git checkout -b refactor/<target> # Refactoring
120
+ ```
121
+
122
+ ### 2. Verify Before Submitting
123
+
124
+ All four checks must pass:
125
+
126
+ ```bash
127
+ make format # Format + auto-fix
128
+ make lint # Lint check
129
+ make typecheck # Type check
130
+ make test # Tests
131
+ ```
132
+
133
+ ### 3. Commit Message Format
134
+
135
+ ```
136
+ <type>(<scope>): <subject>
137
+ ```
138
+
139
+ | Type | Description |
140
+ |------|-------------|
141
+ | `feat` | New feature |
142
+ | `fix` | Bug fix |
143
+ | `refactor` | Refactoring (no behavior change) |
144
+ | `test` | Add/modify tests |
145
+ | `docs` | Documentation changes |
146
+ | `chore` | Build, CI, dependencies |
147
+
148
+ Example:
149
+
150
+ ```
151
+ feat(matchers): add FeatureMatcher with ORB descriptor
152
+ ```
153
+
154
+ ### 4. Submit PR
155
+
156
+ - Keep the title short and descriptive
157
+ - Describe what changed and why in the body
158
+ - Attach screenshots or logs when relevant
159
+
160
+ ---
161
+
162
+ ## Architecture Overview
163
+
164
+ AWT uses a plugin-based architecture. Each module extends an ABC and is registered in a dictionary-based registry.
165
+
166
+ ```
167
+ BaseEngine (ABC) → ENGINE_REGISTRY
168
+ ├── WebEngine (Playwright)
169
+ └── DesktopEngine (PyAutoGUI + Playwright)
170
+
171
+ BaseMatcher (ABC) → MATCHER_REGISTRY
172
+ ├── TemplateMatcher (cv2.matchTemplate)
173
+ ├── OCRMatcher (pytesseract)
174
+ ├── FeatureMatcher (ORB/SIFT)
175
+ └── HybridMatcher (chain orchestrator)
176
+
177
+ AIAdapter (ABC) → ADAPTER_REGISTRY
178
+ ├── ClaudeAdapter (anthropic SDK)
179
+ ├── OpenAIAdapter (openai SDK)
180
+ └── OllamaAdapter (httpx)
181
+
182
+ BaseParser (ABC) → PARSER_REGISTRY
183
+ └── MarkdownParser
184
+
185
+ BaseReporter (ABC) → REPORTER_REGISTRY
186
+ └── MarkdownReporter (Jinja2)
187
+ ```
188
+
189
+ ### Adding a New Plugin
190
+
191
+ 1. Create a class extending the module's ABC
192
+ 2. Register it in the module's `__init__.py` registry
193
+ 3. Write tests
194
+
195
+ ```python
196
+ # src/aat/matchers/my_matcher.py
197
+ from aat.matchers.base import BaseMatcher, MatchResult
198
+
199
+ class MyMatcher(BaseMatcher):
200
+ name = "my_matcher"
201
+
202
+ async def match(self, screenshot: bytes, target: MatchTarget) -> MatchResult | None:
203
+ ...
204
+ ```
205
+
206
+ ```python
207
+ # src/aat/matchers/__init__.py
208
+ from aat.matchers.my_matcher import MyMatcher
209
+
210
+ MATCHER_REGISTRY["my_matcher"] = MyMatcher
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Make Commands
216
+
217
+ | Command | Description |
218
+ |---------|-------------|
219
+ | `make dev` | Full development environment setup |
220
+ | `make lint` | ruff lint check |
221
+ | `make format` | ruff format + auto-fix |
222
+ | `make typecheck` | mypy strict type check |
223
+ | `make test` | Run all pytest tests |
224
+ | `make test-cov` | pytest + coverage report |
225
+ | `make clean` | Clean caches and build artifacts |
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 AWT Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.