antigravity-ide 4.2.1 → 4.3.3

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 (359) hide show
  1. package/.agent/.shared/{design-philosophy → core/design-philosophy}/README.md +12 -1
  2. package/.agent/.shared/{ai-master → technical/ai-master}/README.md +12 -1
  3. package/.agent/.shared/{api-standards → technical/api-standards}/README.md +12 -1
  4. package/.agent/.shared/{database-master → technical/database-master}/README.md +12 -2
  5. package/.agent/.shared/{seo-master → technical/seo-master}/README.md +12 -1
  6. package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/README.md +12 -1
  7. package/.agent/ARCHITECTURE.md +16 -10
  8. package/.agent/ARCHITECTURE.vi.md +8 -8
  9. package/{GEMINI.md → .agent/GEMINI.md} +4 -5
  10. package/.agent/RESOURCES.md +6 -1
  11. package/.agent/agents/backend-specialist.md +154 -19
  12. package/.agent/agents/browser-subagent.md +45 -0
  13. package/.agent/agents/cloud-architect.md +108 -189
  14. package/.agent/agents/debugger.md +83 -182
  15. package/.agent/agents/documentation-writer.md +125 -72
  16. package/.agent/agents/frontend-specialist.md +40 -7
  17. package/.agent/agents/game-developer.md +111 -116
  18. package/.agent/agents/mobile-developer.md +108 -321
  19. package/.agent/agents/orchestrator.md +106 -366
  20. package/.agent/agents/performance-optimizer.md +105 -136
  21. package/.agent/agents/project-planner.md +132 -39
  22. package/.agent/agents/quality-inspector.md +136 -32
  23. package/.agent/agents/security-auditor.md +138 -15
  24. package/.agent/agents/seo-specialist.md +118 -72
  25. package/.agent/agents/test-engineer.md +142 -11
  26. package/.agent/brain/task.md +16 -0
  27. package/.agent/rules/GEMINI.md +63 -31
  28. package/.agent/rules/code-quality.md +34 -3
  29. package/.agent/rules/frontend.md +3 -3
  30. package/.agent/rules/strict-protocol.md +44 -3
  31. package/.agent/rules/system-update.md +56 -3
  32. package/.agent/skills/agent-backend-patterns/SKILL.md +16 -3
  33. package/.agent/skills/ai-engineer/SKILL.md +29 -16
  34. package/.agent/skills/api-documenter/SKILL.md +4 -4
  35. package/.agent/skills/app-builder/SKILL.md +1 -1
  36. package/.agent/skills/app-builder/tech-stack.md +2 -2
  37. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +39 -79
  38. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +53 -75
  39. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +56 -119
  40. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +61 -94
  41. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +56 -82
  42. package/.agent/skills/brand-guidelines-anthropic/LICENSE.txt +202 -0
  43. package/.agent/skills/brand-guidelines-anthropic/SKILL.md +26 -0
  44. package/.agent/skills/brand-guidelines-anthropic/sub-skills/color-application.md +5 -0
  45. package/.agent/skills/brand-guidelines-anthropic/sub-skills/colors.md +14 -0
  46. package/.agent/skills/brand-guidelines-anthropic/sub-skills/font-management.md +6 -0
  47. package/.agent/skills/brand-guidelines-anthropic/sub-skills/shape-and-accent-colors.md +7 -0
  48. package/.agent/skills/brand-guidelines-anthropic/sub-skills/smart-font-application.md +6 -0
  49. package/.agent/skills/brand-guidelines-anthropic/sub-skills/text-styling.md +6 -0
  50. package/.agent/skills/brand-guidelines-anthropic/sub-skills/typography.md +7 -0
  51. package/.agent/skills/cloud-architect-master/SKILL.md +9 -4
  52. package/.agent/skills/cro-expert-kit/SKILL.md +9 -4
  53. package/.agent/skills/database-migration/SKILL.md +9 -3
  54. package/.agent/skills/deployment-engineer/SKILL.md +9 -3
  55. package/.agent/skills/frontend-design/ux-psychology.md +10 -585
  56. package/.agent/skills/full-stack-scaffold/SKILL.md +4 -4
  57. package/.agent/skills/game-development/2d-games/SKILL.md +4 -2
  58. package/.agent/skills/game-development/3d-games/SKILL.md +4 -2
  59. package/.agent/skills/game-development/SKILL.md +18 -149
  60. package/.agent/skills/game-development/game-art/SKILL.md +4 -2
  61. package/.agent/skills/game-development/game-audio/SKILL.md +4 -2
  62. package/.agent/skills/game-development/game-design/SKILL.md +4 -2
  63. package/.agent/skills/game-development/mobile-games/SKILL.md +4 -2
  64. package/.agent/skills/game-development/multiplayer/SKILL.md +4 -2
  65. package/.agent/skills/game-development/pc-games/SKILL.md +4 -2
  66. package/.agent/skills/game-development/vr-ar/SKILL.md +4 -2
  67. package/.agent/skills/game-development/web-games/SKILL.md +4 -2
  68. package/.agent/skills/geo-fundamentals/SKILL.md +9 -136
  69. package/.agent/skills/git-collaboration-master/SKILL.md +9 -4
  70. package/.agent/skills/i18n-localization/SKILL.md +10 -118
  71. package/.agent/skills/incident-responder/SKILL.md +9 -6
  72. package/.agent/skills/internal-comms-anthropic/LICENSE.txt +202 -0
  73. package/.agent/skills/internal-comms-anthropic/SKILL.md +33 -0
  74. package/.agent/skills/internal-comms-anthropic/examples/3p-updates.md +47 -0
  75. package/.agent/skills/internal-comms-anthropic/examples/company-newsletter.md +65 -0
  76. package/.agent/skills/internal-comms-anthropic/examples/faq-answers.md +30 -0
  77. package/.agent/skills/internal-comms-anthropic/examples/general-comms.md +16 -0
  78. package/.agent/skills/last30days/tests/__init__.py +1 -0
  79. package/.agent/skills/last30days/tests/test_cache.py +59 -0
  80. package/.agent/skills/last30days/tests/test_dates.py +114 -0
  81. package/.agent/skills/last30days/tests/test_dedupe.py +111 -0
  82. package/.agent/skills/last30days/tests/test_models.py +135 -0
  83. package/.agent/skills/last30days/tests/test_normalize.py +138 -0
  84. package/.agent/skills/last30days/tests/test_render.py +116 -0
  85. package/.agent/skills/last30days/tests/test_score.py +168 -0
  86. package/.agent/skills/legacy-modernizer/SKILL.md +9 -4
  87. package/.agent/skills/lint-and-validate/scripts/lint_runner.py +2 -14
  88. package/.agent/skills/loki-mode/.github/workflows/claude-code-review.yml +57 -0
  89. package/.agent/skills/loki-mode/.github/workflows/claude.yml +50 -0
  90. package/.agent/skills/loki-mode/.github/workflows/release.yml +128 -0
  91. package/.agent/skills/loki-mode/tests/run-all-tests.sh +78 -0
  92. package/.agent/skills/loki-mode/tests/test-agent-timeout.sh +348 -0
  93. package/.agent/skills/loki-mode/tests/test-bootstrap.sh +196 -0
  94. package/.agent/skills/loki-mode/tests/test-circuit-breaker.sh +389 -0
  95. package/.agent/skills/loki-mode/tests/test-state-recovery.sh +393 -0
  96. package/.agent/skills/loki-mode/tests/test-task-queue.sh +396 -0
  97. package/.agent/skills/loki-mode/tests/test-wrapper.sh +314 -0
  98. package/.agent/skills/mcp-builder/SKILL.md +21 -164
  99. package/.agent/skills/mobile-design/SKILL.md +21 -369
  100. package/.agent/skills/mobile-design/mobile-performance.md +1 -1
  101. package/.agent/skills/modern-web-architect/SKILL.md +12 -6
  102. package/.agent/skills/nextjs-react-expert/scripts/convert_rules.py +1 -1
  103. package/.agent/skills/penetration-tester-master/SKILL.md +9 -4
  104. package/.agent/skills/performance-engineer/SKILL.md +4 -5
  105. package/.agent/skills/production-code-audit/SKILL.md +6 -0
  106. package/.agent/skills/rust-pro/SKILL.md +0 -177
  107. package/.agent/skills/security-auditor/SKILL.md +35 -27
  108. package/.agent/skills/seo-expert-kit/SKILL.md +9 -4
  109. package/.agent/skills/shopify-development/scripts/tests/test_shopify_init.py +379 -0
  110. package/.agent/skills/tdd-master-workflow/SKILL.md +9 -3
  111. package/.agent/workflows/audit.md +30 -16
  112. package/.agent/workflows/brainstorm.md +33 -96
  113. package/.agent/workflows/create.md +37 -45
  114. package/.agent/workflows/debug.md +45 -84
  115. package/.agent/workflows/deploy.md +33 -158
  116. package/.agent/workflows/document.md +38 -15
  117. package/.agent/workflows/enhance.md +33 -48
  118. package/.agent/workflows/monitor.md +35 -14
  119. package/.agent/workflows/orchestrate.md +33 -218
  120. package/.agent/workflows/plan.md +39 -70
  121. package/.agent/workflows/security.md +35 -14
  122. package/.agent/workflows/seo.md +39 -16
  123. package/.agent/workflows/status.md +33 -72
  124. package/.agent/workflows/test.md +30 -127
  125. package/.agent/workflows/ui-ux-pro-max.md +24 -283
  126. package/LICENSE +22 -8
  127. package/README.md +105 -72
  128. package/README.vi.md +93 -110
  129. package/cli/create.js +275 -413
  130. package/cli/index.js +36 -24
  131. package/cli/lib/auto-update.js +14 -21
  132. package/cli/logic/product-skills.js +58 -0
  133. package/cli/logic/skill-definitions.js +0 -39
  134. package/cli/prompts.js +151 -145
  135. package/cli/skills/browser-subagent-core/SKILL.md +22 -0
  136. package/cli/tools/browser.js +75 -0
  137. package/cli/ui/dashboard.js +48 -0
  138. package/docs/AGENTS_GUIDE.vi.md +39 -45
  139. package/docs/CONTRIBUTING.vi.md +12 -3
  140. package/docs/{GEMINI_GUIDE.md → GEMINI_USAGE.md} +6 -6
  141. package/docs/GLOSSARY.vi.md +49 -30
  142. package/docs/HOW_ANTIGRAVITY_THINKS.vi.md +1 -1
  143. package/docs/OPERATIONAL_FLOW.vi.md +15 -0
  144. package/docs/{PUBLISHING.md → PUBLISHING_GUIDE.md} +31 -3
  145. package/docs/RULES_GUIDE.vi.md +67 -31
  146. package/docs/SHARED_LIBRARY_GUIDE.vi.md +18 -22
  147. package/docs/SKILLS_GUIDE.vi.md +119 -32
  148. package/docs/TROUBLESHOOTING.vi.md +10 -2
  149. package/docs/WORKFLOW_GUIDE.vi.md +57 -9
  150. package/package.json +32 -8
  151. package/setup.js +147 -114
  152. package/.agent/.shared/compliance/README.md +0 -19
  153. package/.agent/.shared/design-system/README.md +0 -18
  154. package/.agent/.shared/domain-blueprints/README.md +0 -18
  155. package/.agent/.shared/dx-toolkit/README.md +0 -19
  156. package/.agent/.shared/i18n-master/README.md +0 -18
  157. package/.agent/.shared/infra-blueprints/README.md +0 -18
  158. package/.agent/.shared/metrics/README.md +0 -17
  159. package/.agent/.shared/resilience-patterns/README.md +0 -19
  160. package/.agent/.shared/security-armor/README.md +0 -25
  161. package/.agent/.shared/testing-master/README.md +0 -20
  162. package/.agent/.shared/vitals-templates/README.md +0 -18
  163. package/.agent/agents/accessibility-expert.md +0 -22
  164. package/.agent/agents/api-architect.md +0 -22
  165. package/.agent/agents/backend-specialist.eco.md +0 -19
  166. package/.agent/agents/backend-specialist.instant.md +0 -19
  167. package/.agent/agents/codebase-expert.md +0 -23
  168. package/.agent/agents/compliance-expert.md +0 -22
  169. package/.agent/agents/data-scientist.md +0 -22
  170. package/.agent/agents/debugger.eco.md +0 -20
  171. package/.agent/agents/debugger.instant.md +0 -20
  172. package/.agent/agents/deep-thinker.ultra.md +0 -23
  173. package/.agent/agents/devex-optimizer.md +0 -22
  174. package/.agent/agents/devops-architect.md +0 -22
  175. package/.agent/agents/frontend-specialist.eco.md +0 -19
  176. package/.agent/agents/frontend-specialist.instant.md +0 -19
  177. package/.agent/agents/growth-engineer.md +0 -22
  178. package/.agent/agents/i18n-specialist.md +0 -21
  179. package/.agent/agents/legacy-modernizer.md +0 -22
  180. package/.agent/agents/microservices-specialist.md +0 -22
  181. package/.agent/agents/motion-designer.md +0 -22
  182. package/.agent/agents/orchestrator.creative.md +0 -28
  183. package/.agent/agents/orchestrator.eco.md +0 -29
  184. package/.agent/agents/orchestrator.instant.md +0 -29
  185. package/.agent/agents/orchestrator.ultra.md +0 -28
  186. package/.agent/agents/performance-benchmarker.md +0 -22
  187. package/.agent/agents/project-planner.eco.md +0 -19
  188. package/.agent/agents/project-planner.instant.md +0 -19
  189. package/.agent/agents/security-pentester.md +0 -22
  190. package/.agent/agents/serverless-expert.md +0 -22
  191. package/.agent/fastcode_index.json +0 -1038
  192. package/.agent/mcp_config.json +0 -24
  193. package/.agent/rules/GEMINI.eco.md +0 -37
  194. package/.agent/rules/GEMINI.instant.md +0 -37
  195. package/.agent/rules/api-spec.md +0 -28
  196. package/.agent/rules/database.md +0 -24
  197. package/.agent/rules/devops.md +0 -23
  198. package/.agent/rules/growth-strategy.md +0 -22
  199. package/.agent/rules/logging-monitoring.md +0 -22
  200. package/.agent/rules/quality-assurance.md +0 -22
  201. package/.agent/rules/system-reasoning.md +0 -20
  202. package/.agent/rules/ui-design.md +0 -23
  203. package/.agent/rules/ux-patterns.md +0 -23
  204. package/.agent/scripts/auto_preview.py +0 -148
  205. package/.agent/scripts/checklist.py +0 -252
  206. package/.agent/scripts/session_manager.py +0 -120
  207. package/.agent/scripts/simulation_install.js +0 -59
  208. package/.agent/scripts/sync_to_global.py +0 -78
  209. package/.agent/scripts/translate_workflows.py +0 -53
  210. package/.agent/scripts/verify_all.py +0 -327
  211. package/.agent/scripts/verify_shared_modules.js +0 -126
  212. package/.agent/skills/fastcode-search/SKILL.md +0 -46
  213. package/.agent/skills/fastcode-search/fastcode_config.example.json +0 -17
  214. package/.agent/skills/frontend-trends-2026/SKILL.md +0 -78
  215. package/.agent/skills/frontend-trends-2026/formulas/BentoGrid.tsx +0 -42
  216. package/.agent/skills/frontend-trends-2026/formulas/LiquidCard.tsx +0 -32
  217. package/.agent/skills/frontend-trends-2026/formulas/NeoButton.tsx +0 -27
  218. package/.agent/workflows/deep-security-audit.md +0 -9
  219. package/.agent/workflows/growth-max.md +0 -9
  220. package/.agent/workflows/performance-max.md +0 -9
  221. package/.editorconfig +0 -21
  222. package/.gitattributes +0 -7
  223. package/CHANGELOG.md +0 -32
  224. package/ERRORS.md +0 -67
  225. package/action.yml +0 -32
  226. package/antigravity-ide-logo.png +0 -0
  227. package/antigravity-ide-logo.svg +0 -24
  228. package/assets/skills-bundle.json +0 -1
  229. package/cli/manifest.js +0 -524
  230. package/cli/skills/fastcode.js +0 -181
  231. package/docs/AGENT_FLOW.md +0 -608
  232. package/docs/CONTRIBUTING.md +0 -46
  233. package/docs/COPYRIGHT.md +0 -57
  234. package/docs/DEPLOYMENT.md +0 -77
  235. package/docs/GLOSSARY.md +0 -109
  236. package/docs/MASTER_GUIDE.md +0 -103
  237. package/docs/OPERATIONAL_FLOW.md +0 -147
  238. package/docs/PLAN-upgrade-core-architecture.md +0 -71
  239. package/docs/SKILLS.md +0 -610
  240. package/docs/TROUBLESHOOTING.md +0 -43
  241. package/jest.config.js +0 -8
  242. package/scripts/bump.js +0 -93
  243. package/scripts/bundle-skills.js +0 -59
  244. package/scripts/internal/automation/auto-release.js +0 -177
  245. package/scripts/internal/fractalize-skills.js +0 -89
  246. package/scripts/internal/generate-skill-definitions.js +0 -134
  247. package/scripts/internal/internal/update-docs.js +0 -115
  248. package/scripts/internal/refactor-skill-content.js +0 -127
  249. package/scripts/internal/rename-skills.js +0 -96
  250. package/scripts/internal/sync-skills.js +0 -112
  251. package/scripts/internal/update-frontmatter-names.js +0 -99
  252. package/scripts/internal/verification/audit-dna.js +0 -56
  253. package/scripts/internal/verification/audit-skills.js +0 -65
  254. package/web/src/app/docs/guide/examples/brainstorm/page.mdx +0 -91
  255. package/web/src/app/docs/guide/examples/create/page.mdx +0 -84
  256. package/web/src/app/docs/guide/examples/debugging/page.mdx +0 -83
  257. package/web/src/app/docs/guide/examples/deployment/page.mdx +0 -93
  258. package/web/src/app/docs/guide/examples/new-feature/page.mdx +0 -102
  259. package/web/src/app/docs/guide/examples/orchestration/page.mdx +0 -99
  260. package/web/src/app/docs/guide/examples/plan/page.mdx +0 -76
  261. package/web/src/app/docs/guide/examples/preview/page.mdx +0 -77
  262. package/web/src/app/docs/guide/examples/status/page.mdx +0 -78
  263. package/web/src/app/docs/guide/examples/test/page.mdx +0 -80
  264. package/web/src/app/docs/guide/examples/ui-design/page.mdx +0 -90
  265. package/web/src/components/mdx/Callout.tsx +0 -60
  266. package/web/src/components/mdx/FeatureGrid.tsx +0 -38
  267. package/web/src/components/mdx/ProTips.tsx +0 -29
  268. package/web/src/components/mdx/StepList.tsx +0 -33
  269. package/web/src/components/mdx/Terminal.tsx +0 -58
  270. package/web/src/components/mdx/index.ts +0 -5
  271. package/web/src/mdx-components.tsx +0 -98
  272. /package/.agent/.shared/{design-philosophy → core/design-philosophy}/MANIFESTO.md +0 -0
  273. /package/.agent/.shared/{design-philosophy → core/design-philosophy}/checklists/tactile_audit.md +0 -0
  274. /package/.agent/.shared/{design-philosophy → core/design-philosophy}/checklists/visual_audit.md +0 -0
  275. /package/.agent/.shared/{design-philosophy → core/design-philosophy}/presets/linear_glow.json +0 -0
  276. /package/.agent/.shared/{dx-toolkit → core/dx-toolkit}/checklists/code_review.md +0 -0
  277. /package/.agent/.shared/{dx-toolkit → core/dx-toolkit}/presets/vscode_settings.json +0 -0
  278. /package/.agent/.shared/{metrics → core/metrics}/benchmarks.json +0 -0
  279. /package/.agent/.shared/{vitals-templates → core/vitals-templates}/audit_report.md +0 -0
  280. /package/.agent/.shared/{vitals-templates → core/vitals-templates}/plan_prd.md +0 -0
  281. /package/.agent/.shared/{ai-master → technical/ai-master}/best_patterns.md +0 -0
  282. /package/.agent/.shared/{ai-master → technical/ai-master}/checklists/prompt_audit.md +0 -0
  283. /package/.agent/.shared/{ai-master → technical/ai-master}/presets/model_configs.json +0 -0
  284. /package/.agent/.shared/{api-standards → technical/api-standards}/data +0 -0
  285. /package/.agent/.shared/{api-standards → technical/api-standards}/endpoints_naming.md +0 -0
  286. /package/.agent/.shared/{api-standards → technical/api-standards}/error_codes.csv +0 -0
  287. /package/.agent/.shared/{api-standards → technical/api-standards}/pagination_sorting.md +0 -0
  288. /package/.agent/.shared/{api-standards → technical/api-standards}/response_format.json +0 -0
  289. /package/.agent/.shared/{database-master → technical/database-master}/schemas/auth_rbac.sql +0 -0
  290. /package/.agent/.shared/{database-master → technical/database-master}/schemas/cms.sql +0 -0
  291. /package/.agent/.shared/{database-master → technical/database-master}/schemas/ecommerce.sql +0 -0
  292. /package/.agent/.shared/{design-system → technical/design-system}/brand_presets.json +0 -0
  293. /package/.agent/.shared/{design-system → technical/design-system}/micro_interactions.md +0 -0
  294. /package/.agent/.shared/{i18n-master → technical/i18n-master}/vi_tech_dictionary.csv +0 -0
  295. /package/.agent/.shared/{i18n-master → technical/i18n-master}/workflows.json +0 -0
  296. /package/.agent/.shared/{resilience-patterns → technical/resilience-patterns}/checklists/chaos_engineering.md +0 -0
  297. /package/.agent/.shared/{resilience-patterns → technical/resilience-patterns}/presets/circuit_breaker.json +0 -0
  298. /package/.agent/.shared/{security-armor → technical/security-armor}/checklists/vuln_scan.md +0 -0
  299. /package/.agent/.shared/{security-armor → technical/security-armor}/hardening.md +0 -0
  300. /package/.agent/.shared/{security-armor → technical/security-armor}/presets/helmet_config.json +0 -0
  301. /package/.agent/.shared/{seo-master → technical/seo-master}/checklists/technical_seo.md +0 -0
  302. /package/.agent/.shared/{seo-master → technical/seo-master}/presets/json_ld_schema.json +0 -0
  303. /package/.agent/.shared/{testing-master → technical/testing-master}/checklists/pre_release.md +0 -0
  304. /package/.agent/.shared/{testing-master → technical/testing-master}/scenarios.md +0 -0
  305. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/colors.csv +0 -0
  306. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/icons.csv +0 -0
  307. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/landing.csv +0 -0
  308. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/products.csv +0 -0
  309. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/react-performance.csv +0 -0
  310. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/flutter.csv +0 -0
  311. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/html-tailwind.csv +0 -0
  312. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/jetpack-compose.csv +0 -0
  313. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/nextjs.csv +0 -0
  314. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/nuxt-ui.csv +0 -0
  315. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/nuxtjs.csv +0 -0
  316. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/react-native.csv +0 -0
  317. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/react.csv +0 -0
  318. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/shadcn.csv +0 -0
  319. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/svelte.csv +0 -0
  320. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/swiftui.csv +0 -0
  321. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/vue.csv +0 -0
  322. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/ux-guidelines.csv +0 -0
  323. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/web-interface.csv +0 -0
  324. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/scripts/__pycache__/core.cpython-313.pyc +0 -0
  325. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  326. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/scripts/core.py +0 -0
  327. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/scripts/design_system.py +0 -0
  328. /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/scripts/search.py +0 -0
  329. /package/.agent/.shared/{compliance → verticals/compliance}/legal_templates.md +0 -0
  330. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/edtech.md +0 -0
  331. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/fintech.md +0 -0
  332. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/fnb_restaurant.md +0 -0
  333. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/freelance_marketplace.md +0 -0
  334. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/healthcare.md +0 -0
  335. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/hospitality_tourism.md +0 -0
  336. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/logistics.md +0 -0
  337. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/marketing_automation.md +0 -0
  338. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/personal_branding.md +0 -0
  339. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/real_estate.md +0 -0
  340. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/retail_ecommerce.md +0 -0
  341. /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/standard-pro-agents.md +0 -0
  342. /package/.agent/.shared/{infra-blueprints → verticals/infra-blueprints}/deployment_specs.md +0 -0
  343. /package/.agent/skills/ai-engineer/{resources → sub-skills}/ai_infra_stack.md +0 -0
  344. /package/.agent/skills/cloud-architect-master/{resources → sub-skills}/cost_optimization_checklist.md +0 -0
  345. /package/.agent/skills/cro-expert-kit/{resources → sub-skills}/psychological_triggers.md +0 -0
  346. /package/.agent/skills/database-migration/{resources → sub-skills}/zero_downtime_strategy.md +0 -0
  347. /package/.agent/skills/deployment-engineer/{resources → sub-skills}/k8s_best_practices.md +0 -0
  348. /package/.agent/skills/git-collaboration-master/{resources → sub-skills}/pr_template.md +0 -0
  349. /package/.agent/skills/incident-responder/{resources → sub-skills}/incident_severity_levels.md +0 -0
  350. /package/.agent/skills/legacy-modernizer/{resources → sub-skills}/strangler_fig_pattern.md +0 -0
  351. /package/.agent/skills/penetration-tester-master/{resources → sub-skills}/owasp_top_10_2025.md +0 -0
  352. /package/.agent/skills/production-code-audit/{resources → sub-skills}/solid_principles_cheat_sheet.md +0 -0
  353. /package/.agent/skills/seo-expert-kit/{resources → sub-skills}/technical_seo_checklist.md +0 -0
  354. /package/.agent/skills/tdd-master-workflow/{resources → sub-skills}/unit_test_naming_convention.md +0 -0
  355. /package/.agent/{.shared → skills}/ui-ux-pro-max/data/charts.csv +0 -0
  356. /package/.agent/{.shared → skills}/ui-ux-pro-max/data/prompts.csv +0 -0
  357. /package/.agent/{.shared → skills}/ui-ux-pro-max/data/styles.csv +0 -0
  358. /package/.agent/{.shared → skills}/ui-ux-pro-max/data/typography.csv +0 -0
  359. /package/.agent/{.shared → skills}/ui-ux-pro-max/data/ui-reasoning.csv +0 -0
@@ -0,0 +1,111 @@
1
+ """Tests for dedupe module."""
2
+
3
+ import sys
4
+ import unittest
5
+ from pathlib import Path
6
+
7
+ # Add lib to path
8
+ sys.path.insert(0, str(Path(__file__).parent.parent / "scripts"))
9
+
10
+ from lib import dedupe, schema
11
+
12
+
13
+ class TestNormalizeText(unittest.TestCase):
14
+ def test_lowercase(self):
15
+ result = dedupe.normalize_text("HELLO World")
16
+ self.assertEqual(result, "hello world")
17
+
18
+ def test_removes_punctuation(self):
19
+ result = dedupe.normalize_text("Hello, World!")
20
+ # Punctuation replaced with space, then whitespace collapsed
21
+ self.assertEqual(result, "hello world")
22
+
23
+ def test_collapses_whitespace(self):
24
+ result = dedupe.normalize_text("hello world")
25
+ self.assertEqual(result, "hello world")
26
+
27
+
28
+ class TestGetNgrams(unittest.TestCase):
29
+ def test_short_text(self):
30
+ result = dedupe.get_ngrams("ab", n=3)
31
+ self.assertEqual(result, {"ab"})
32
+
33
+ def test_normal_text(self):
34
+ result = dedupe.get_ngrams("hello", n=3)
35
+ self.assertIn("hel", result)
36
+ self.assertIn("ell", result)
37
+ self.assertIn("llo", result)
38
+
39
+
40
+ class TestJaccardSimilarity(unittest.TestCase):
41
+ def test_identical_sets(self):
42
+ set1 = {"a", "b", "c"}
43
+ result = dedupe.jaccard_similarity(set1, set1)
44
+ self.assertEqual(result, 1.0)
45
+
46
+ def test_disjoint_sets(self):
47
+ set1 = {"a", "b", "c"}
48
+ set2 = {"d", "e", "f"}
49
+ result = dedupe.jaccard_similarity(set1, set2)
50
+ self.assertEqual(result, 0.0)
51
+
52
+ def test_partial_overlap(self):
53
+ set1 = {"a", "b", "c"}
54
+ set2 = {"b", "c", "d"}
55
+ result = dedupe.jaccard_similarity(set1, set2)
56
+ self.assertEqual(result, 0.5) # 2 overlap / 4 union
57
+
58
+ def test_empty_sets(self):
59
+ result = dedupe.jaccard_similarity(set(), set())
60
+ self.assertEqual(result, 0.0)
61
+
62
+
63
+ class TestFindDuplicates(unittest.TestCase):
64
+ def test_no_duplicates(self):
65
+ items = [
66
+ schema.RedditItem(id="R1", title="Completely different topic A", url="", subreddit=""),
67
+ schema.RedditItem(id="R2", title="Another unrelated subject B", url="", subreddit=""),
68
+ ]
69
+ result = dedupe.find_duplicates(items)
70
+ self.assertEqual(result, [])
71
+
72
+ def test_finds_duplicates(self):
73
+ items = [
74
+ schema.RedditItem(id="R1", title="Best practices for Claude Code skills", url="", subreddit=""),
75
+ schema.RedditItem(id="R2", title="Best practices for Claude Code skills guide", url="", subreddit=""),
76
+ ]
77
+ result = dedupe.find_duplicates(items, threshold=0.7)
78
+ self.assertEqual(len(result), 1)
79
+ self.assertEqual(result[0], (0, 1))
80
+
81
+
82
+ class TestDedupeItems(unittest.TestCase):
83
+ def test_keeps_higher_scored(self):
84
+ items = [
85
+ schema.RedditItem(id="R1", title="Best practices for skills", url="", subreddit="", score=90),
86
+ schema.RedditItem(id="R2", title="Best practices for skills guide", url="", subreddit="", score=50),
87
+ ]
88
+ result = dedupe.dedupe_items(items, threshold=0.6)
89
+ self.assertEqual(len(result), 1)
90
+ self.assertEqual(result[0].id, "R1")
91
+
92
+ def test_keeps_all_unique(self):
93
+ items = [
94
+ schema.RedditItem(id="R1", title="Topic about apples", url="", subreddit="", score=90),
95
+ schema.RedditItem(id="R2", title="Discussion of oranges", url="", subreddit="", score=50),
96
+ ]
97
+ result = dedupe.dedupe_items(items)
98
+ self.assertEqual(len(result), 2)
99
+
100
+ def test_empty_list(self):
101
+ result = dedupe.dedupe_items([])
102
+ self.assertEqual(result, [])
103
+
104
+ def test_single_item(self):
105
+ items = [schema.RedditItem(id="R1", title="Test", url="", subreddit="")]
106
+ result = dedupe.dedupe_items(items)
107
+ self.assertEqual(len(result), 1)
108
+
109
+
110
+ if __name__ == "__main__":
111
+ unittest.main()
@@ -0,0 +1,135 @@
1
+ """Tests for models module."""
2
+
3
+ import sys
4
+ import unittest
5
+ from pathlib import Path
6
+
7
+ # Add lib to path
8
+ sys.path.insert(0, str(Path(__file__).parent.parent / "scripts"))
9
+
10
+ from lib import models
11
+
12
+
13
+ class TestParseVersion(unittest.TestCase):
14
+ def test_simple_version(self):
15
+ result = models.parse_version("gpt-5")
16
+ self.assertEqual(result, (5,))
17
+
18
+ def test_minor_version(self):
19
+ result = models.parse_version("gpt-5.2")
20
+ self.assertEqual(result, (5, 2))
21
+
22
+ def test_patch_version(self):
23
+ result = models.parse_version("gpt-5.2.1")
24
+ self.assertEqual(result, (5, 2, 1))
25
+
26
+ def test_no_version(self):
27
+ result = models.parse_version("custom-model")
28
+ self.assertIsNone(result)
29
+
30
+
31
+ class TestIsMainlineOpenAIModel(unittest.TestCase):
32
+ def test_gpt5_is_mainline(self):
33
+ self.assertTrue(models.is_mainline_openai_model("gpt-5"))
34
+
35
+ def test_gpt52_is_mainline(self):
36
+ self.assertTrue(models.is_mainline_openai_model("gpt-5.2"))
37
+
38
+ def test_gpt5_mini_is_not_mainline(self):
39
+ self.assertFalse(models.is_mainline_openai_model("gpt-5-mini"))
40
+
41
+ def test_gpt4_is_not_mainline(self):
42
+ self.assertFalse(models.is_mainline_openai_model("gpt-4"))
43
+
44
+
45
+ class TestSelectOpenAIModel(unittest.TestCase):
46
+ def test_pinned_policy(self):
47
+ result = models.select_openai_model(
48
+ "fake-key",
49
+ policy="pinned",
50
+ pin="gpt-5.1"
51
+ )
52
+ self.assertEqual(result, "gpt-5.1")
53
+
54
+ def test_auto_with_mock_models(self):
55
+ mock_models = [
56
+ {"id": "gpt-5.2", "created": 1704067200},
57
+ {"id": "gpt-5.1", "created": 1701388800},
58
+ {"id": "gpt-5", "created": 1698710400},
59
+ ]
60
+ result = models.select_openai_model(
61
+ "fake-key",
62
+ policy="auto",
63
+ mock_models=mock_models
64
+ )
65
+ self.assertEqual(result, "gpt-5.2")
66
+
67
+ def test_auto_filters_variants(self):
68
+ mock_models = [
69
+ {"id": "gpt-5.2", "created": 1704067200},
70
+ {"id": "gpt-5-mini", "created": 1704067200},
71
+ {"id": "gpt-5.1", "created": 1701388800},
72
+ ]
73
+ result = models.select_openai_model(
74
+ "fake-key",
75
+ policy="auto",
76
+ mock_models=mock_models
77
+ )
78
+ self.assertEqual(result, "gpt-5.2")
79
+
80
+
81
+ class TestSelectXAIModel(unittest.TestCase):
82
+ def test_latest_policy(self):
83
+ result = models.select_xai_model(
84
+ "fake-key",
85
+ policy="latest"
86
+ )
87
+ self.assertEqual(result, "grok-4-latest")
88
+
89
+ def test_stable_policy(self):
90
+ # Clear cache first to avoid interference
91
+ from lib import cache
92
+ cache.MODEL_CACHE_FILE.unlink(missing_ok=True)
93
+ result = models.select_xai_model(
94
+ "fake-key",
95
+ policy="stable"
96
+ )
97
+ self.assertEqual(result, "grok-4")
98
+
99
+ def test_pinned_policy(self):
100
+ result = models.select_xai_model(
101
+ "fake-key",
102
+ policy="pinned",
103
+ pin="grok-3"
104
+ )
105
+ self.assertEqual(result, "grok-3")
106
+
107
+
108
+ class TestGetModels(unittest.TestCase):
109
+ def test_no_keys_returns_none(self):
110
+ config = {}
111
+ result = models.get_models(config)
112
+ self.assertIsNone(result["openai"])
113
+ self.assertIsNone(result["xai"])
114
+
115
+ def test_openai_key_only(self):
116
+ config = {"OPENAI_API_KEY": "sk-test"}
117
+ mock_models = [{"id": "gpt-5.2", "created": 1704067200}]
118
+ result = models.get_models(config, mock_openai_models=mock_models)
119
+ self.assertEqual(result["openai"], "gpt-5.2")
120
+ self.assertIsNone(result["xai"])
121
+
122
+ def test_both_keys(self):
123
+ config = {
124
+ "OPENAI_API_KEY": "sk-test",
125
+ "XAI_API_KEY": "xai-test",
126
+ }
127
+ mock_openai = [{"id": "gpt-5.2", "created": 1704067200}]
128
+ mock_xai = [{"id": "grok-4-latest", "created": 1704067200}]
129
+ result = models.get_models(config, mock_openai, mock_xai)
130
+ self.assertEqual(result["openai"], "gpt-5.2")
131
+ self.assertEqual(result["xai"], "grok-4-latest")
132
+
133
+
134
+ if __name__ == "__main__":
135
+ unittest.main()
@@ -0,0 +1,138 @@
1
+ """Tests for normalize module."""
2
+
3
+ import sys
4
+ import unittest
5
+ from pathlib import Path
6
+
7
+ # Add lib to path
8
+ sys.path.insert(0, str(Path(__file__).parent.parent / "scripts"))
9
+
10
+ from lib import normalize, schema
11
+
12
+
13
+ class TestNormalizeRedditItems(unittest.TestCase):
14
+ def test_normalizes_basic_item(self):
15
+ items = [
16
+ {
17
+ "id": "R1",
18
+ "title": "Test Thread",
19
+ "url": "https://reddit.com/r/test/1",
20
+ "subreddit": "test",
21
+ "date": "2026-01-15",
22
+ "why_relevant": "Relevant because...",
23
+ "relevance": 0.85,
24
+ }
25
+ ]
26
+
27
+ result = normalize.normalize_reddit_items(items, "2026-01-01", "2026-01-31")
28
+
29
+ self.assertEqual(len(result), 1)
30
+ self.assertIsInstance(result[0], schema.RedditItem)
31
+ self.assertEqual(result[0].id, "R1")
32
+ self.assertEqual(result[0].title, "Test Thread")
33
+ self.assertEqual(result[0].date_confidence, "high")
34
+
35
+ def test_sets_low_confidence_for_old_date(self):
36
+ items = [
37
+ {
38
+ "id": "R1",
39
+ "title": "Old Thread",
40
+ "url": "https://reddit.com/r/test/1",
41
+ "subreddit": "test",
42
+ "date": "2025-12-01", # Before range
43
+ "relevance": 0.5,
44
+ }
45
+ ]
46
+
47
+ result = normalize.normalize_reddit_items(items, "2026-01-01", "2026-01-31")
48
+
49
+ self.assertEqual(result[0].date_confidence, "low")
50
+
51
+ def test_handles_engagement(self):
52
+ items = [
53
+ {
54
+ "id": "R1",
55
+ "title": "Thread with engagement",
56
+ "url": "https://reddit.com/r/test/1",
57
+ "subreddit": "test",
58
+ "engagement": {
59
+ "score": 100,
60
+ "num_comments": 50,
61
+ "upvote_ratio": 0.9,
62
+ },
63
+ "relevance": 0.5,
64
+ }
65
+ ]
66
+
67
+ result = normalize.normalize_reddit_items(items, "2026-01-01", "2026-01-31")
68
+
69
+ self.assertIsNotNone(result[0].engagement)
70
+ self.assertEqual(result[0].engagement.score, 100)
71
+ self.assertEqual(result[0].engagement.num_comments, 50)
72
+
73
+
74
+ class TestNormalizeXItems(unittest.TestCase):
75
+ def test_normalizes_basic_item(self):
76
+ items = [
77
+ {
78
+ "id": "X1",
79
+ "text": "Test post content",
80
+ "url": "https://x.com/user/status/123",
81
+ "author_handle": "testuser",
82
+ "date": "2026-01-15",
83
+ "why_relevant": "Relevant because...",
84
+ "relevance": 0.9,
85
+ }
86
+ ]
87
+
88
+ result = normalize.normalize_x_items(items, "2026-01-01", "2026-01-31")
89
+
90
+ self.assertEqual(len(result), 1)
91
+ self.assertIsInstance(result[0], schema.XItem)
92
+ self.assertEqual(result[0].id, "X1")
93
+ self.assertEqual(result[0].author_handle, "testuser")
94
+
95
+ def test_handles_x_engagement(self):
96
+ items = [
97
+ {
98
+ "id": "X1",
99
+ "text": "Post with engagement",
100
+ "url": "https://x.com/user/status/123",
101
+ "author_handle": "user",
102
+ "engagement": {
103
+ "likes": 100,
104
+ "reposts": 25,
105
+ "replies": 15,
106
+ "quotes": 5,
107
+ },
108
+ "relevance": 0.5,
109
+ }
110
+ ]
111
+
112
+ result = normalize.normalize_x_items(items, "2026-01-01", "2026-01-31")
113
+
114
+ self.assertIsNotNone(result[0].engagement)
115
+ self.assertEqual(result[0].engagement.likes, 100)
116
+ self.assertEqual(result[0].engagement.reposts, 25)
117
+
118
+
119
+ class TestItemsToDicts(unittest.TestCase):
120
+ def test_converts_items(self):
121
+ items = [
122
+ schema.RedditItem(
123
+ id="R1",
124
+ title="Test",
125
+ url="https://reddit.com/r/test/1",
126
+ subreddit="test",
127
+ )
128
+ ]
129
+
130
+ result = normalize.items_to_dicts(items)
131
+
132
+ self.assertEqual(len(result), 1)
133
+ self.assertIsInstance(result[0], dict)
134
+ self.assertEqual(result[0]["id"], "R1")
135
+
136
+
137
+ if __name__ == "__main__":
138
+ unittest.main()
@@ -0,0 +1,116 @@
1
+ """Tests for render module."""
2
+
3
+ import sys
4
+ import unittest
5
+ from pathlib import Path
6
+
7
+ # Add lib to path
8
+ sys.path.insert(0, str(Path(__file__).parent.parent / "scripts"))
9
+
10
+ from lib import render, schema
11
+
12
+
13
+ class TestRenderCompact(unittest.TestCase):
14
+ def test_renders_basic_report(self):
15
+ report = schema.Report(
16
+ topic="test topic",
17
+ range_from="2026-01-01",
18
+ range_to="2026-01-31",
19
+ generated_at="2026-01-31T12:00:00Z",
20
+ mode="both",
21
+ openai_model_used="gpt-5.2",
22
+ xai_model_used="grok-4-latest",
23
+ )
24
+
25
+ result = render.render_compact(report)
26
+
27
+ self.assertIn("test topic", result)
28
+ self.assertIn("2026-01-01", result)
29
+ self.assertIn("both", result)
30
+ self.assertIn("gpt-5.2", result)
31
+
32
+ def test_renders_reddit_items(self):
33
+ report = schema.Report(
34
+ topic="test",
35
+ range_from="2026-01-01",
36
+ range_to="2026-01-31",
37
+ generated_at="2026-01-31T12:00:00Z",
38
+ mode="reddit-only",
39
+ reddit=[
40
+ schema.RedditItem(
41
+ id="R1",
42
+ title="Test Thread",
43
+ url="https://reddit.com/r/test/1",
44
+ subreddit="test",
45
+ date="2026-01-15",
46
+ date_confidence="high",
47
+ score=85,
48
+ why_relevant="Very relevant",
49
+ )
50
+ ],
51
+ )
52
+
53
+ result = render.render_compact(report)
54
+
55
+ self.assertIn("R1", result)
56
+ self.assertIn("Test Thread", result)
57
+ self.assertIn("r/test", result)
58
+
59
+ def test_shows_coverage_tip_for_reddit_only(self):
60
+ report = schema.Report(
61
+ topic="test",
62
+ range_from="2026-01-01",
63
+ range_to="2026-01-31",
64
+ generated_at="2026-01-31T12:00:00Z",
65
+ mode="reddit-only",
66
+ )
67
+
68
+ result = render.render_compact(report)
69
+
70
+ self.assertIn("xAI key", result)
71
+
72
+
73
+ class TestRenderContextSnippet(unittest.TestCase):
74
+ def test_renders_snippet(self):
75
+ report = schema.Report(
76
+ topic="Claude Code Skills",
77
+ range_from="2026-01-01",
78
+ range_to="2026-01-31",
79
+ generated_at="2026-01-31T12:00:00Z",
80
+ mode="both",
81
+ )
82
+
83
+ result = render.render_context_snippet(report)
84
+
85
+ self.assertIn("Claude Code Skills", result)
86
+ self.assertIn("Last 30 Days", result)
87
+
88
+
89
+ class TestRenderFullReport(unittest.TestCase):
90
+ def test_renders_full_report(self):
91
+ report = schema.Report(
92
+ topic="test topic",
93
+ range_from="2026-01-01",
94
+ range_to="2026-01-31",
95
+ generated_at="2026-01-31T12:00:00Z",
96
+ mode="both",
97
+ openai_model_used="gpt-5.2",
98
+ xai_model_used="grok-4-latest",
99
+ )
100
+
101
+ result = render.render_full_report(report)
102
+
103
+ self.assertIn("# test topic", result)
104
+ self.assertIn("## Models Used", result)
105
+ self.assertIn("gpt-5.2", result)
106
+
107
+
108
+ class TestGetContextPath(unittest.TestCase):
109
+ def test_returns_path_string(self):
110
+ result = render.get_context_path()
111
+ self.assertIsInstance(result, str)
112
+ self.assertIn("last30days.context.md", result)
113
+
114
+
115
+ if __name__ == "__main__":
116
+ unittest.main()
@@ -0,0 +1,168 @@
1
+ """Tests for score module."""
2
+
3
+ import sys
4
+ import unittest
5
+ from datetime import datetime, timezone
6
+ from pathlib import Path
7
+
8
+ # Add lib to path
9
+ sys.path.insert(0, str(Path(__file__).parent.parent / "scripts"))
10
+
11
+ from lib import schema, score
12
+
13
+
14
+ class TestLog1pSafe(unittest.TestCase):
15
+ def test_positive_value(self):
16
+ result = score.log1p_safe(100)
17
+ self.assertGreater(result, 0)
18
+
19
+ def test_zero(self):
20
+ result = score.log1p_safe(0)
21
+ self.assertEqual(result, 0)
22
+
23
+ def test_none(self):
24
+ result = score.log1p_safe(None)
25
+ self.assertEqual(result, 0)
26
+
27
+ def test_negative(self):
28
+ result = score.log1p_safe(-5)
29
+ self.assertEqual(result, 0)
30
+
31
+
32
+ class TestComputeRedditEngagementRaw(unittest.TestCase):
33
+ def test_with_engagement(self):
34
+ eng = schema.Engagement(score=100, num_comments=50, upvote_ratio=0.9)
35
+ result = score.compute_reddit_engagement_raw(eng)
36
+ self.assertIsNotNone(result)
37
+ self.assertGreater(result, 0)
38
+
39
+ def test_without_engagement(self):
40
+ result = score.compute_reddit_engagement_raw(None)
41
+ self.assertIsNone(result)
42
+
43
+ def test_empty_engagement(self):
44
+ eng = schema.Engagement()
45
+ result = score.compute_reddit_engagement_raw(eng)
46
+ self.assertIsNone(result)
47
+
48
+
49
+ class TestComputeXEngagementRaw(unittest.TestCase):
50
+ def test_with_engagement(self):
51
+ eng = schema.Engagement(likes=100, reposts=25, replies=15, quotes=5)
52
+ result = score.compute_x_engagement_raw(eng)
53
+ self.assertIsNotNone(result)
54
+ self.assertGreater(result, 0)
55
+
56
+ def test_without_engagement(self):
57
+ result = score.compute_x_engagement_raw(None)
58
+ self.assertIsNone(result)
59
+
60
+
61
+ class TestNormalizeTo100(unittest.TestCase):
62
+ def test_normalizes_values(self):
63
+ values = [0, 50, 100]
64
+ result = score.normalize_to_100(values)
65
+ self.assertEqual(result[0], 0)
66
+ self.assertEqual(result[1], 50)
67
+ self.assertEqual(result[2], 100)
68
+
69
+ def test_handles_none(self):
70
+ values = [0, None, 100]
71
+ result = score.normalize_to_100(values)
72
+ self.assertIsNone(result[1])
73
+
74
+ def test_single_value(self):
75
+ values = [50]
76
+ result = score.normalize_to_100(values)
77
+ self.assertEqual(result[0], 50)
78
+
79
+
80
+ class TestScoreRedditItems(unittest.TestCase):
81
+ def test_scores_items(self):
82
+ today = datetime.now(timezone.utc).date().isoformat()
83
+ items = [
84
+ schema.RedditItem(
85
+ id="R1",
86
+ title="Test",
87
+ url="https://reddit.com/r/test/1",
88
+ subreddit="test",
89
+ date=today,
90
+ date_confidence="high",
91
+ engagement=schema.Engagement(score=100, num_comments=50, upvote_ratio=0.9),
92
+ relevance=0.9,
93
+ ),
94
+ schema.RedditItem(
95
+ id="R2",
96
+ title="Test 2",
97
+ url="https://reddit.com/r/test/2",
98
+ subreddit="test",
99
+ date=today,
100
+ date_confidence="high",
101
+ engagement=schema.Engagement(score=10, num_comments=5, upvote_ratio=0.8),
102
+ relevance=0.5,
103
+ ),
104
+ ]
105
+
106
+ result = score.score_reddit_items(items)
107
+
108
+ self.assertEqual(len(result), 2)
109
+ self.assertGreater(result[0].score, 0)
110
+ self.assertGreater(result[1].score, 0)
111
+ # Higher relevance and engagement should score higher
112
+ self.assertGreater(result[0].score, result[1].score)
113
+
114
+ def test_empty_list(self):
115
+ result = score.score_reddit_items([])
116
+ self.assertEqual(result, [])
117
+
118
+
119
+ class TestScoreXItems(unittest.TestCase):
120
+ def test_scores_items(self):
121
+ today = datetime.now(timezone.utc).date().isoformat()
122
+ items = [
123
+ schema.XItem(
124
+ id="X1",
125
+ text="Test post",
126
+ url="https://x.com/user/1",
127
+ author_handle="user1",
128
+ date=today,
129
+ date_confidence="high",
130
+ engagement=schema.Engagement(likes=100, reposts=25, replies=15, quotes=5),
131
+ relevance=0.9,
132
+ ),
133
+ ]
134
+
135
+ result = score.score_x_items(items)
136
+
137
+ self.assertEqual(len(result), 1)
138
+ self.assertGreater(result[0].score, 0)
139
+
140
+
141
+ class TestSortItems(unittest.TestCase):
142
+ def test_sorts_by_score_descending(self):
143
+ items = [
144
+ schema.RedditItem(id="R1", title="Low", url="", subreddit="", score=30),
145
+ schema.RedditItem(id="R2", title="High", url="", subreddit="", score=90),
146
+ schema.RedditItem(id="R3", title="Mid", url="", subreddit="", score=60),
147
+ ]
148
+
149
+ result = score.sort_items(items)
150
+
151
+ self.assertEqual(result[0].id, "R2")
152
+ self.assertEqual(result[1].id, "R3")
153
+ self.assertEqual(result[2].id, "R1")
154
+
155
+ def test_stable_sort(self):
156
+ items = [
157
+ schema.RedditItem(id="R1", title="A", url="", subreddit="", score=50),
158
+ schema.RedditItem(id="R2", title="B", url="", subreddit="", score=50),
159
+ ]
160
+
161
+ result = score.sort_items(items)
162
+
163
+ # Both have same score, should maintain order by title
164
+ self.assertEqual(len(result), 2)
165
+
166
+
167
+ if __name__ == "__main__":
168
+ unittest.main()
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: legacy-modernizer
3
- description: >
4
- Refactor legacy codebases, migrate outdated frameworks, and implement gradual
5
- modernization. Handles technical debt, dependency updates, and backward compatibility.
6
- Uses the Strangler Fig pattern for safe transitions.
3
+ description: Refactor legacy codebases, migrate outdated frameworks, and implement gradual modernization.
4
+ category: development
5
+ version: 4.1.0-fractal
6
+ layer: master-skill
7
7
  ---
8
8
 
9
9
  # 🏛️ Legacy Modernizer Master Kit
@@ -66,3 +66,8 @@ You are a **Principal Modernization Engineer and Software Strategist**. You tran
66
66
 
67
67
  ---
68
68
  *Merged and optimized from 5 legacy modernization and migration skills.*
69
+
70
+
71
+ ## 🧠 Knowledge Modules (Fractal Skills)
72
+
73
+ ### 1. [strangler_fig_pattern](./sub-skills/strangler_fig_pattern.md)