bps-kit 1.0.1 → 1.0.2

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 (368) hide show
  1. package/package.json +1 -1
  2. package/templates/.agents/agents/backend-specialist.md +263 -0
  3. package/templates/.agents/agents/code-archaeologist.md +106 -0
  4. package/templates/.agents/agents/database-architect.md +226 -0
  5. package/templates/.agents/agents/debugger.md +225 -0
  6. package/templates/.agents/agents/devops-engineer.md +242 -0
  7. package/templates/.agents/agents/documentation-writer.md +104 -0
  8. package/templates/.agents/agents/explorer-agent.md +73 -0
  9. package/templates/.agents/agents/frontend-specialist.md +593 -0
  10. package/templates/.agents/agents/game-developer.md +162 -0
  11. package/templates/.agents/agents/mobile-developer.md +377 -0
  12. package/templates/.agents/agents/orchestrator.md +416 -0
  13. package/templates/.agents/agents/penetration-tester.md +188 -0
  14. package/templates/.agents/agents/performance-optimizer.md +187 -0
  15. package/templates/.agents/agents/product-manager.md +112 -0
  16. package/templates/.agents/agents/product-owner.md +95 -0
  17. package/templates/.agents/agents/project-planner.md +406 -0
  18. package/templates/.agents/agents/qa-automation-engineer.md +103 -0
  19. package/templates/.agents/agents/security-auditor.md +170 -0
  20. package/templates/.agents/agents/seo-specialist.md +111 -0
  21. package/templates/.agents/agents/test-engineer.md +158 -0
  22. package/templates/.agents/rules/GEMINI.md +219 -0
  23. package/templates/.agents/scripts/auto_preview.py +148 -0
  24. package/templates/.agents/scripts/checklist.py +217 -0
  25. package/templates/.agents/scripts/session_manager.py +120 -0
  26. package/templates/.agents/scripts/verify_all.py +327 -0
  27. package/templates/.agents/workflows/brainstorm.md +113 -0
  28. package/templates/.agents/workflows/create.md +59 -0
  29. package/templates/.agents/workflows/debug.md +103 -0
  30. package/templates/.agents/workflows/deploy.md +176 -0
  31. package/templates/.agents/workflows/enhance.md +63 -0
  32. package/templates/.agents/workflows/orchestrate.md +237 -0
  33. package/templates/.agents/workflows/plan.md +89 -0
  34. package/templates/.agents/workflows/preview.md +81 -0
  35. package/templates/.agents/workflows/setup-brain.md +39 -0
  36. package/templates/.agents/workflows/status.md +86 -0
  37. package/templates/.agents/workflows/test.md +144 -0
  38. package/templates/.agents/workflows/ui-ux-pro-max.md +296 -0
  39. package/templates/skills_normal/api-patterns/scripts/api_validator.py +211 -0
  40. package/templates/skills_normal/database-design/scripts/schema_validator.py +172 -0
  41. package/templates/skills_normal/frontend-design/scripts/accessibility_checker.py +183 -0
  42. package/templates/skills_normal/frontend-design/scripts/ux_audit.py +722 -0
  43. package/templates/skills_normal/git-pushing/scripts/smart_commit.sh +19 -0
  44. package/templates/skills_normal/lint-and-validate/scripts/lint_runner.py +184 -0
  45. package/templates/skills_normal/lint-and-validate/scripts/type_coverage.py +173 -0
  46. package/templates/skills_normal/performance-profiling/scripts/lighthouse_audit.py +76 -0
  47. package/templates/skills_normal/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
  48. package/templates/skills_normal/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
  49. package/templates/skills_normal/senior-fullstack/scripts/project_scaffolder.py +114 -0
  50. package/templates/skills_normal/seo-fundamentals/scripts/seo_checker.py +219 -0
  51. package/templates/skills_normal/testing-patterns/scripts/test_runner.py +219 -0
  52. package/templates/skills_normal/vulnerability-scanner/scripts/security_scan.py +458 -0
  53. package/templates/vault/007/scripts/config.py +472 -0
  54. package/templates/vault/007/scripts/full_audit.py +1306 -0
  55. package/templates/vault/007/scripts/quick_scan.py +481 -0
  56. package/templates/vault/007/scripts/requirements.txt +26 -0
  57. package/templates/vault/007/scripts/scanners/__init__.py +0 -0
  58. package/templates/vault/007/scripts/scanners/dependency_scanner.py +1305 -0
  59. package/templates/vault/007/scripts/scanners/injection_scanner.py +1104 -0
  60. package/templates/vault/007/scripts/scanners/secrets_scanner.py +1008 -0
  61. package/templates/vault/007/scripts/score_calculator.py +693 -0
  62. package/templates/vault/agent-orchestrator/scripts/match_skills.py +329 -0
  63. package/templates/vault/agent-orchestrator/scripts/orchestrate.py +304 -0
  64. package/templates/vault/agent-orchestrator/scripts/requirements.txt +1 -0
  65. package/templates/vault/agent-orchestrator/scripts/scan_registry.py +508 -0
  66. package/templates/vault/ai-studio-image/scripts/config.py +613 -0
  67. package/templates/vault/ai-studio-image/scripts/generate.py +630 -0
  68. package/templates/vault/ai-studio-image/scripts/prompt_engine.py +424 -0
  69. package/templates/vault/ai-studio-image/scripts/requirements.txt +4 -0
  70. package/templates/vault/ai-studio-image/scripts/templates.py +349 -0
  71. package/templates/vault/android_ui_verification/scripts/verify_ui.sh +32 -0
  72. package/templates/vault/apify-audience-analysis/reference/scripts/run_actor.js +363 -0
  73. package/templates/vault/apify-brand-reputation-monitoring/reference/scripts/run_actor.js +363 -0
  74. package/templates/vault/apify-competitor-intelligence/reference/scripts/run_actor.js +363 -0
  75. package/templates/vault/apify-content-analytics/reference/scripts/run_actor.js +363 -0
  76. package/templates/vault/apify-ecommerce/reference/scripts/package.json +3 -0
  77. package/templates/vault/apify-ecommerce/reference/scripts/run_actor.js +369 -0
  78. package/templates/vault/apify-influencer-discovery/reference/scripts/run_actor.js +363 -0
  79. package/templates/vault/apify-lead-generation/reference/scripts/run_actor.js +363 -0
  80. package/templates/vault/apify-market-research/reference/scripts/run_actor.js +363 -0
  81. package/templates/vault/apify-trend-analysis/reference/scripts/run_actor.js +363 -0
  82. package/templates/vault/apify-ultimate-scraper/reference/scripts/run_actor.js +363 -0
  83. package/templates/vault/audio-transcriber/scripts/install-requirements.sh +190 -0
  84. package/templates/vault/audio-transcriber/scripts/transcribe.py +486 -0
  85. package/templates/vault/claude-monitor/scripts/api_bench.py +240 -0
  86. package/templates/vault/claude-monitor/scripts/config.py +69 -0
  87. package/templates/vault/claude-monitor/scripts/health_check.py +362 -0
  88. package/templates/vault/claude-monitor/scripts/monitor.py +296 -0
  89. package/templates/vault/content-creator/scripts/brand_voice_analyzer.py +185 -0
  90. package/templates/vault/content-creator/scripts/seo_optimizer.py +419 -0
  91. package/templates/vault/context-agent/scripts/active_context.py +227 -0
  92. package/templates/vault/context-agent/scripts/compressor.py +149 -0
  93. package/templates/vault/context-agent/scripts/config.py +69 -0
  94. package/templates/vault/context-agent/scripts/context_loader.py +155 -0
  95. package/templates/vault/context-agent/scripts/context_manager.py +302 -0
  96. package/templates/vault/context-agent/scripts/models.py +103 -0
  97. package/templates/vault/context-agent/scripts/project_registry.py +132 -0
  98. package/templates/vault/context-agent/scripts/requirements.txt +6 -0
  99. package/templates/vault/context-agent/scripts/search.py +115 -0
  100. package/templates/vault/context-agent/scripts/session_parser.py +206 -0
  101. package/templates/vault/context-agent/scripts/session_summary.py +319 -0
  102. package/templates/vault/context-guardian/scripts/context_snapshot.py +229 -0
  103. package/templates/vault/docx/ooxml/scripts/pack.py +159 -0
  104. package/templates/vault/docx/ooxml/scripts/unpack.py +29 -0
  105. package/templates/vault/docx/ooxml/scripts/validate.py +69 -0
  106. package/templates/vault/docx/ooxml/scripts/validation/__init__.py +15 -0
  107. package/templates/vault/docx/ooxml/scripts/validation/base.py +951 -0
  108. package/templates/vault/docx/ooxml/scripts/validation/docx.py +274 -0
  109. package/templates/vault/docx/ooxml/scripts/validation/pptx.py +315 -0
  110. package/templates/vault/docx/ooxml/scripts/validation/redlining.py +279 -0
  111. package/templates/vault/docx/scripts/__init__.py +1 -0
  112. package/templates/vault/docx/scripts/document.py +1276 -0
  113. package/templates/vault/docx/scripts/templates/comments.xml +3 -0
  114. package/templates/vault/docx/scripts/templates/commentsExtended.xml +3 -0
  115. package/templates/vault/docx/scripts/templates/commentsExtensible.xml +3 -0
  116. package/templates/vault/docx/scripts/templates/commentsIds.xml +3 -0
  117. package/templates/vault/docx/scripts/templates/people.xml +3 -0
  118. package/templates/vault/docx/scripts/utilities.py +374 -0
  119. package/templates/vault/docx-official/ooxml/scripts/pack.py +159 -0
  120. package/templates/vault/docx-official/ooxml/scripts/unpack.py +29 -0
  121. package/templates/vault/docx-official/ooxml/scripts/validate.py +69 -0
  122. package/templates/vault/docx-official/ooxml/scripts/validation/__init__.py +15 -0
  123. package/templates/vault/docx-official/ooxml/scripts/validation/base.py +951 -0
  124. package/templates/vault/docx-official/ooxml/scripts/validation/docx.py +274 -0
  125. package/templates/vault/docx-official/ooxml/scripts/validation/pptx.py +315 -0
  126. package/templates/vault/docx-official/ooxml/scripts/validation/redlining.py +279 -0
  127. package/templates/vault/docx-official/scripts/__init__.py +1 -0
  128. package/templates/vault/docx-official/scripts/document.py +1276 -0
  129. package/templates/vault/docx-official/scripts/templates/comments.xml +3 -0
  130. package/templates/vault/docx-official/scripts/templates/commentsExtended.xml +3 -0
  131. package/templates/vault/docx-official/scripts/templates/commentsExtensible.xml +3 -0
  132. package/templates/vault/docx-official/scripts/templates/commentsIds.xml +3 -0
  133. package/templates/vault/docx-official/scripts/templates/people.xml +3 -0
  134. package/templates/vault/docx-official/scripts/utilities.py +374 -0
  135. package/templates/vault/geo-fundamentals/scripts/geo_checker.py +289 -0
  136. package/templates/vault/helm-chart-scaffolding/scripts/validate-chart.sh +244 -0
  137. package/templates/vault/i18n-localization/scripts/i18n_checker.py +241 -0
  138. package/templates/vault/instagram/scripts/account_setup.py +233 -0
  139. package/templates/vault/instagram/scripts/analyze.py +221 -0
  140. package/templates/vault/instagram/scripts/api_client.py +444 -0
  141. package/templates/vault/instagram/scripts/auth.py +411 -0
  142. package/templates/vault/instagram/scripts/comments.py +160 -0
  143. package/templates/vault/instagram/scripts/config.py +111 -0
  144. package/templates/vault/instagram/scripts/db.py +467 -0
  145. package/templates/vault/instagram/scripts/export.py +138 -0
  146. package/templates/vault/instagram/scripts/governance.py +233 -0
  147. package/templates/vault/instagram/scripts/hashtags.py +114 -0
  148. package/templates/vault/instagram/scripts/insights.py +170 -0
  149. package/templates/vault/instagram/scripts/media.py +65 -0
  150. package/templates/vault/instagram/scripts/messages.py +103 -0
  151. package/templates/vault/instagram/scripts/profile.py +58 -0
  152. package/templates/vault/instagram/scripts/publish.py +449 -0
  153. package/templates/vault/instagram/scripts/requirements.txt +5 -0
  154. package/templates/vault/instagram/scripts/run_all.py +189 -0
  155. package/templates/vault/instagram/scripts/schedule.py +189 -0
  156. package/templates/vault/instagram/scripts/serve_api.py +234 -0
  157. package/templates/vault/instagram/scripts/templates.py +155 -0
  158. package/templates/vault/junta-leiloeiros/scripts/db.py +216 -0
  159. package/templates/vault/junta-leiloeiros/scripts/export.py +137 -0
  160. package/templates/vault/junta-leiloeiros/scripts/requirements.txt +15 -0
  161. package/templates/vault/junta-leiloeiros/scripts/run_all.py +190 -0
  162. package/templates/vault/junta-leiloeiros/scripts/scraper/__init__.py +4 -0
  163. package/templates/vault/junta-leiloeiros/scripts/scraper/base_scraper.py +209 -0
  164. package/templates/vault/junta-leiloeiros/scripts/scraper/generic_scraper.py +110 -0
  165. package/templates/vault/junta-leiloeiros/scripts/scraper/jucap.py +110 -0
  166. package/templates/vault/junta-leiloeiros/scripts/scraper/juceac.py +72 -0
  167. package/templates/vault/junta-leiloeiros/scripts/scraper/juceal.py +72 -0
  168. package/templates/vault/junta-leiloeiros/scripts/scraper/juceb.py +68 -0
  169. package/templates/vault/junta-leiloeiros/scripts/scraper/jucec.py +63 -0
  170. package/templates/vault/junta-leiloeiros/scripts/scraper/jucema.py +211 -0
  171. package/templates/vault/junta-leiloeiros/scripts/scraper/jucemg.py +218 -0
  172. package/templates/vault/junta-leiloeiros/scripts/scraper/jucep.py +70 -0
  173. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepa.py +74 -0
  174. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepar.py +80 -0
  175. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepe.py +78 -0
  176. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepi.py +69 -0
  177. package/templates/vault/junta-leiloeiros/scripts/scraper/jucer.py +256 -0
  178. package/templates/vault/junta-leiloeiros/scripts/scraper/jucerja.py +170 -0
  179. package/templates/vault/junta-leiloeiros/scripts/scraper/jucern.py +71 -0
  180. package/templates/vault/junta-leiloeiros/scripts/scraper/jucesc.py +89 -0
  181. package/templates/vault/junta-leiloeiros/scripts/scraper/jucesp.py +233 -0
  182. package/templates/vault/junta-leiloeiros/scripts/scraper/jucetins.py +134 -0
  183. package/templates/vault/junta-leiloeiros/scripts/scraper/jucis_df.py +63 -0
  184. package/templates/vault/junta-leiloeiros/scripts/scraper/jucisrs.py +299 -0
  185. package/templates/vault/junta-leiloeiros/scripts/scraper/states.py +99 -0
  186. package/templates/vault/junta-leiloeiros/scripts/serve_api.py +164 -0
  187. package/templates/vault/junta-leiloeiros/scripts/web_scraper_fallback.py +233 -0
  188. package/templates/vault/last30days/scripts/last30days.py +521 -0
  189. package/templates/vault/last30days/scripts/lib/__init__.py +1 -0
  190. package/templates/vault/last30days/scripts/lib/cache.py +152 -0
  191. package/templates/vault/last30days/scripts/lib/dates.py +124 -0
  192. package/templates/vault/last30days/scripts/lib/dedupe.py +120 -0
  193. package/templates/vault/last30days/scripts/lib/env.py +149 -0
  194. package/templates/vault/last30days/scripts/lib/http.py +152 -0
  195. package/templates/vault/last30days/scripts/lib/models.py +175 -0
  196. package/templates/vault/last30days/scripts/lib/normalize.py +160 -0
  197. package/templates/vault/last30days/scripts/lib/openai_reddit.py +230 -0
  198. package/templates/vault/last30days/scripts/lib/reddit_enrich.py +232 -0
  199. package/templates/vault/last30days/scripts/lib/render.py +383 -0
  200. package/templates/vault/last30days/scripts/lib/schema.py +336 -0
  201. package/templates/vault/last30days/scripts/lib/score.py +311 -0
  202. package/templates/vault/last30days/scripts/lib/ui.py +324 -0
  203. package/templates/vault/last30days/scripts/lib/websearch.py +401 -0
  204. package/templates/vault/last30days/scripts/lib/xai_x.py +217 -0
  205. package/templates/vault/leiloeiro-avaliacao/scripts/governance.py +106 -0
  206. package/templates/vault/leiloeiro-avaliacao/scripts/requirements.txt +1 -0
  207. package/templates/vault/leiloeiro-edital/scripts/governance.py +106 -0
  208. package/templates/vault/leiloeiro-edital/scripts/requirements.txt +1 -0
  209. package/templates/vault/leiloeiro-ia/scripts/governance.py +106 -0
  210. package/templates/vault/leiloeiro-ia/scripts/requirements.txt +1 -0
  211. package/templates/vault/leiloeiro-juridico/scripts/governance.py +106 -0
  212. package/templates/vault/leiloeiro-juridico/scripts/requirements.txt +1 -0
  213. package/templates/vault/leiloeiro-mercado/scripts/governance.py +106 -0
  214. package/templates/vault/leiloeiro-mercado/scripts/requirements.txt +1 -0
  215. package/templates/vault/leiloeiro-risco/scripts/governance.py +106 -0
  216. package/templates/vault/leiloeiro-risco/scripts/requirements.txt +1 -0
  217. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/database.ts +24 -0
  218. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/db.ts +35 -0
  219. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/index.ts +2 -0
  220. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/migrations.ts +31 -0
  221. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/schema.sql +8 -0
  222. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/index.ts +44 -0
  223. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/routes/todos.ts +155 -0
  224. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/types/index.ts +35 -0
  225. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.css +384 -0
  226. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.tsx +81 -0
  227. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/api/todos.ts +57 -0
  228. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/ConfirmDialog.tsx +26 -0
  229. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/EmptyState.tsx +8 -0
  230. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoForm.tsx +43 -0
  231. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoItem.tsx +36 -0
  232. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoList.tsx +27 -0
  233. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/hooks/useTodos.ts +81 -0
  234. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/index.css +48 -0
  235. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/main.tsx +10 -0
  236. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/vite-env.d.ts +1 -0
  237. package/templates/vault/loki-mode/scripts/export-to-vibe-kanban.sh +178 -0
  238. package/templates/vault/loki-mode/scripts/loki-wrapper.sh +281 -0
  239. package/templates/vault/loki-mode/scripts/take-screenshots.js +55 -0
  240. package/templates/vault/matematico-tao/scripts/complexity_analyzer.py +544 -0
  241. package/templates/vault/matematico-tao/scripts/dependency_graph.py +538 -0
  242. package/templates/vault/mcp-builder/scripts/connections.py +151 -0
  243. package/templates/vault/mcp-builder/scripts/evaluation.py +373 -0
  244. package/templates/vault/mcp-builder/scripts/example_evaluation.xml +22 -0
  245. package/templates/vault/mcp-builder/scripts/requirements.txt +2 -0
  246. package/templates/vault/mobile-design/scripts/mobile_audit.py +670 -0
  247. package/templates/vault/notebooklm/scripts/__init__.py +81 -0
  248. package/templates/vault/notebooklm/scripts/ask_question.py +256 -0
  249. package/templates/vault/notebooklm/scripts/auth_manager.py +358 -0
  250. package/templates/vault/notebooklm/scripts/browser_session.py +255 -0
  251. package/templates/vault/notebooklm/scripts/browser_utils.py +107 -0
  252. package/templates/vault/notebooklm/scripts/cleanup_manager.py +302 -0
  253. package/templates/vault/notebooklm/scripts/config.py +44 -0
  254. package/templates/vault/notebooklm/scripts/notebook_manager.py +410 -0
  255. package/templates/vault/notebooklm/scripts/run.py +102 -0
  256. package/templates/vault/notebooklm/scripts/setup_environment.py +204 -0
  257. package/templates/vault/pdf/scripts/check_bounding_boxes.py +70 -0
  258. package/templates/vault/pdf/scripts/check_bounding_boxes_test.py +226 -0
  259. package/templates/vault/pdf/scripts/check_fillable_fields.py +12 -0
  260. package/templates/vault/pdf/scripts/convert_pdf_to_images.py +35 -0
  261. package/templates/vault/pdf/scripts/create_validation_image.py +41 -0
  262. package/templates/vault/pdf/scripts/extract_form_field_info.py +152 -0
  263. package/templates/vault/pdf/scripts/fill_fillable_fields.py +114 -0
  264. package/templates/vault/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  265. package/templates/vault/pdf-official/scripts/check_bounding_boxes.py +70 -0
  266. package/templates/vault/pdf-official/scripts/check_bounding_boxes_test.py +226 -0
  267. package/templates/vault/pdf-official/scripts/check_fillable_fields.py +12 -0
  268. package/templates/vault/pdf-official/scripts/convert_pdf_to_images.py +35 -0
  269. package/templates/vault/pdf-official/scripts/create_validation_image.py +41 -0
  270. package/templates/vault/pdf-official/scripts/extract_form_field_info.py +152 -0
  271. package/templates/vault/pdf-official/scripts/fill_fillable_fields.py +114 -0
  272. package/templates/vault/pdf-official/scripts/fill_pdf_form_with_annotations.py +108 -0
  273. package/templates/vault/planning-with-files/scripts/check-complete.sh +44 -0
  274. package/templates/vault/planning-with-files/scripts/init-session.sh +120 -0
  275. package/templates/vault/pptx/ooxml/scripts/pack.py +159 -0
  276. package/templates/vault/pptx/ooxml/scripts/unpack.py +29 -0
  277. package/templates/vault/pptx/ooxml/scripts/validate.py +69 -0
  278. package/templates/vault/pptx/ooxml/scripts/validation/__init__.py +15 -0
  279. package/templates/vault/pptx/ooxml/scripts/validation/base.py +951 -0
  280. package/templates/vault/pptx/ooxml/scripts/validation/docx.py +274 -0
  281. package/templates/vault/pptx/ooxml/scripts/validation/pptx.py +315 -0
  282. package/templates/vault/pptx/ooxml/scripts/validation/redlining.py +279 -0
  283. package/templates/vault/pptx/scripts/html2pptx.js +979 -0
  284. package/templates/vault/pptx/scripts/inventory.py +1020 -0
  285. package/templates/vault/pptx/scripts/rearrange.py +231 -0
  286. package/templates/vault/pptx/scripts/replace.py +385 -0
  287. package/templates/vault/pptx/scripts/thumbnail.py +450 -0
  288. package/templates/vault/pptx-official/ooxml/scripts/pack.py +159 -0
  289. package/templates/vault/pptx-official/ooxml/scripts/unpack.py +29 -0
  290. package/templates/vault/pptx-official/ooxml/scripts/validate.py +69 -0
  291. package/templates/vault/pptx-official/ooxml/scripts/validation/__init__.py +15 -0
  292. package/templates/vault/pptx-official/ooxml/scripts/validation/base.py +951 -0
  293. package/templates/vault/pptx-official/ooxml/scripts/validation/docx.py +274 -0
  294. package/templates/vault/pptx-official/ooxml/scripts/validation/pptx.py +315 -0
  295. package/templates/vault/pptx-official/ooxml/scripts/validation/redlining.py +279 -0
  296. package/templates/vault/pptx-official/scripts/html2pptx.js +979 -0
  297. package/templates/vault/pptx-official/scripts/inventory.py +1020 -0
  298. package/templates/vault/pptx-official/scripts/rearrange.py +231 -0
  299. package/templates/vault/pptx-official/scripts/replace.py +385 -0
  300. package/templates/vault/pptx-official/scripts/thumbnail.py +450 -0
  301. package/templates/vault/product-manager-toolkit/scripts/customer_interview_analyzer.py +441 -0
  302. package/templates/vault/product-manager-toolkit/scripts/rice_prioritizer.py +296 -0
  303. package/templates/vault/prompt-engineering-patterns/scripts/optimize-prompt.py +279 -0
  304. package/templates/vault/scripts/.skill_cache.json +7538 -0
  305. package/templates/vault/scripts/skill_search.py +228 -0
  306. package/templates/vault/senior-architect/scripts/architecture_diagram_generator.py +114 -0
  307. package/templates/vault/senior-architect/scripts/dependency_analyzer.py +114 -0
  308. package/templates/vault/senior-architect/scripts/project_architect.py +114 -0
  309. package/templates/vault/shopify-development/scripts/requirements.txt +19 -0
  310. package/templates/vault/shopify-development/scripts/shopify_graphql.py +428 -0
  311. package/templates/vault/shopify-development/scripts/shopify_init.py +441 -0
  312. package/templates/vault/shopify-development/scripts/tests/test_shopify_init.py +379 -0
  313. package/templates/vault/skill-creator/scripts/init_skill.py +303 -0
  314. package/templates/vault/skill-creator/scripts/package_skill.py +110 -0
  315. package/templates/vault/skill-creator/scripts/quick_validate.py +95 -0
  316. package/templates/vault/skill-installer/scripts/detect_skills.py +318 -0
  317. package/templates/vault/skill-installer/scripts/install_skill.py +1708 -0
  318. package/templates/vault/skill-installer/scripts/package_skill.py +417 -0
  319. package/templates/vault/skill-installer/scripts/requirements.txt +1 -0
  320. package/templates/vault/skill-installer/scripts/validate_skill.py +430 -0
  321. package/templates/vault/skill-sentinel/scripts/analyzers/__init__.py +13 -0
  322. package/templates/vault/skill-sentinel/scripts/analyzers/code_quality.py +247 -0
  323. package/templates/vault/skill-sentinel/scripts/analyzers/cross_skill.py +134 -0
  324. package/templates/vault/skill-sentinel/scripts/analyzers/dependencies.py +121 -0
  325. package/templates/vault/skill-sentinel/scripts/analyzers/documentation.py +189 -0
  326. package/templates/vault/skill-sentinel/scripts/analyzers/governance_audit.py +153 -0
  327. package/templates/vault/skill-sentinel/scripts/analyzers/performance.py +164 -0
  328. package/templates/vault/skill-sentinel/scripts/analyzers/security.py +189 -0
  329. package/templates/vault/skill-sentinel/scripts/config.py +158 -0
  330. package/templates/vault/skill-sentinel/scripts/cost_optimizer.py +146 -0
  331. package/templates/vault/skill-sentinel/scripts/db.py +354 -0
  332. package/templates/vault/skill-sentinel/scripts/governance.py +58 -0
  333. package/templates/vault/skill-sentinel/scripts/recommender.py +228 -0
  334. package/templates/vault/skill-sentinel/scripts/report_generator.py +224 -0
  335. package/templates/vault/skill-sentinel/scripts/requirements.txt +1 -0
  336. package/templates/vault/skill-sentinel/scripts/run_audit.py +290 -0
  337. package/templates/vault/skill-sentinel/scripts/scanner.py +271 -0
  338. package/templates/vault/stability-ai/scripts/config.py +266 -0
  339. package/templates/vault/stability-ai/scripts/generate.py +687 -0
  340. package/templates/vault/stability-ai/scripts/requirements.txt +4 -0
  341. package/templates/vault/stability-ai/scripts/styles.py +174 -0
  342. package/templates/vault/telegram/assets/boilerplate/nodejs/src/bot-client.ts +86 -0
  343. package/templates/vault/telegram/assets/boilerplate/nodejs/src/handlers.ts +79 -0
  344. package/templates/vault/telegram/assets/boilerplate/nodejs/src/index.ts +32 -0
  345. package/templates/vault/telegram/scripts/send_message.py +143 -0
  346. package/templates/vault/telegram/scripts/setup_project.py +103 -0
  347. package/templates/vault/telegram/scripts/test_bot.py +144 -0
  348. package/templates/vault/typescript-expert/scripts/ts_diagnostic.py +203 -0
  349. package/templates/vault/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
  350. package/templates/vault/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
  351. package/templates/vault/ui-ux-pro-max/scripts/core.py +257 -0
  352. package/templates/vault/ui-ux-pro-max/scripts/design_system.py +487 -0
  353. package/templates/vault/ui-ux-pro-max/scripts/search.py +76 -0
  354. package/templates/vault/videodb/scripts/ws_listener.py +204 -0
  355. package/templates/vault/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
  356. package/templates/vault/web-artifacts-builder/scripts/init-artifact.sh +322 -0
  357. package/templates/vault/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  358. package/templates/vault/webapp-testing/scripts/with_server.py +106 -0
  359. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/index.ts +125 -0
  360. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/template-manager.ts +67 -0
  361. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/types.ts +216 -0
  362. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/webhook-handler.ts +173 -0
  363. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/whatsapp-client.ts +193 -0
  364. package/templates/vault/whatsapp-cloud-api/scripts/send_test_message.py +137 -0
  365. package/templates/vault/whatsapp-cloud-api/scripts/setup_project.py +118 -0
  366. package/templates/vault/whatsapp-cloud-api/scripts/validate_config.py +190 -0
  367. package/templates/vault/youtube-summarizer/scripts/extract-transcript.py +65 -0
  368. package/templates/vault/youtube-summarizer/scripts/install-dependencies.sh +28 -0
@@ -0,0 +1,218 @@
1
+ """
2
+ Scraper JUCEMG — Junta Comercial do Estado de Minas Gerais
3
+ URLs descobertas em 2026-02-25:
4
+ - /pagina/139 = menu principal (links para sub-paginas)
5
+ - /pagina/140 = lista alfabetica com contatos completos (USAR ESTA)
6
+ - /pagina/141 = lista por antiguidade com tabela (apenas nome + matricula)
7
+ - /pagina/142 = matriculas canceladas
8
+ Metodo: httpx + BeautifulSoup
9
+ Pagina /pagina/140 contem paragrafos com nome + matricula + endereco + telefone + email
10
+ Total: 218 leiloeiros ativos (alguns com status inline: Suspenso, Licenciado)
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import logging
15
+ import re
16
+ from typing import List
17
+
18
+ from .base_scraper import AbstractJuntaScraper, Leiloeiro
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+ RE_MATRICULA_MG = re.compile(r"[Mm]atr[íi]cula:?\s*(\d+)\s+de\s+(\d{2}/\d{2}/\d{4})|[Mm]atr[íi]cula:?\s*n[º°]?\s*(\d+)", re.IGNORECASE)
23
+ RE_PREPOSTO = re.compile(r"[Pp]reposto:?\s*(.+)")
24
+ RE_TELEFONE = re.compile(r"[Tt]elefones?:?\s*(.+)")
25
+ RE_EMAIL = re.compile(r"(?:e-mail|email):?\s*(.+)", re.IGNORECASE)
26
+ RE_SITE = re.compile(r"(?:site|www\.)(.+)", re.IGNORECASE)
27
+ RE_STATUS_INLINE = re.compile(r"\((Suspen|Licencia|Cancel|Irregular)[^)]*\)", re.IGNORECASE)
28
+
29
+
30
+ class JucemgScraper(AbstractJuntaScraper):
31
+ estado = "MG"
32
+ junta = "JUCEMG"
33
+ url = "https://jucemg.mg.gov.br/pagina/139/leiloeiros-oficiais"
34
+ # URL da lista alfabetica com contatos completos
35
+ _URL_ALFA = "https://jucemg.mg.gov.br/pagina/140/leiloeiros-ordem-alfabetica"
36
+ # URL da lista por antiguidade com tabela (nome + matricula)
37
+ _URL_ANT = "https://jucemg.mg.gov.br/pagina/141/leiloeiros-antiguidade"
38
+
39
+ def _parse_alfabetica(self, soup) -> List[dict]:
40
+ """
41
+ Parseia a pagina /pagina/140 (ordem alfabetica).
42
+ Cada leiloeiro e um bloco <p>:
43
+ <p><strong>NOME COMPLETO</strong><br>
44
+ Matricula: N de DD/MM/AAAA<br>
45
+ Preposto: ...<br>
46
+ Endereco, Bairro, Cidade - MG, CEP<br>
47
+ Telefones: ...<br>
48
+ email<br>
49
+ site</p>
50
+ """
51
+ records = []
52
+ content = soup.select_one(
53
+ ".conteudo-pagina, .page-content, .conteudo, article .content, main .content, "
54
+ ".entry-content, #conteudo, .corpo-pagina"
55
+ )
56
+ if not content:
57
+ content = soup.body or soup
58
+
59
+ for p in content.find_all("p"):
60
+ strong = p.find("strong")
61
+ if not strong:
62
+ continue
63
+ nome_raw = self.clean(strong.get_text())
64
+ if not nome_raw or len(nome_raw) < 3:
65
+ continue
66
+
67
+ # Verificar status inline no nome (ex: "NOME (Suspenso)")
68
+ status_match = RE_STATUS_INLINE.search(nome_raw)
69
+ situacao = None
70
+ if status_match:
71
+ situacao = status_match.group(0).strip("()")
72
+ nome_raw = RE_STATUS_INLINE.sub("", nome_raw).strip()
73
+
74
+ # Coletar linhas do paragrafo (apos o <strong>)
75
+ lines = []
76
+ for el in p.children:
77
+ if el == strong:
78
+ continue
79
+ if hasattr(el, "get_text"):
80
+ line = self.clean(el.get_text())
81
+ elif isinstance(el, str):
82
+ line = self.clean(str(el))
83
+ else:
84
+ continue
85
+ if line and line != nome_raw:
86
+ lines.append(line)
87
+
88
+ record = {
89
+ "nome": nome_raw,
90
+ "municipio": "Belo Horizonte",
91
+ "situacao": situacao,
92
+ }
93
+
94
+ for line in lines:
95
+ m = RE_MATRICULA_MG.search(line)
96
+ if m:
97
+ record["matricula"] = m.group(1) or m.group(3)
98
+ if m.group(2):
99
+ record["data_registro"] = m.group(2)
100
+ continue
101
+ m = RE_TELEFONE.search(line)
102
+ if m:
103
+ record["telefone"] = self.clean(m.group(1))
104
+ continue
105
+ m = RE_EMAIL.search(line)
106
+ if m:
107
+ record["email"] = self.clean(m.group(1))
108
+ continue
109
+ # Linha de endereco: contem cidade/MG ou CEP
110
+ if (re.search(r"/\s*MG\b|\bMG\s*,?\s*CEP|CEP\s*\d", line) or
111
+ (len(line) > 10 and not RE_PREPOSTO.match(line) and
112
+ not RE_SITE.match(line) and
113
+ not record.get("endereco"))):
114
+ m_cidade = re.search(r"([A-ZÁÉÍÓÚÀÃÕÇ][A-Za-záéíóúàãõç\s]+)\s*-?\s*MG", line)
115
+ if m_cidade:
116
+ record["municipio"] = m_cidade.group(1).strip()
117
+ if not record.get("endereco"):
118
+ record["endereco"] = line
119
+
120
+ records.append(record)
121
+
122
+ return records
123
+
124
+ def _parse_antiguidade(self, soup) -> List[dict]:
125
+ """
126
+ Parseia tabela /pagina/141 (antiguidade).
127
+ Tabela com 2 colunas: "Ordem de antiguidade e nome" + "No de matricula"
128
+ Alguns nomes tem notas de status inline.
129
+ """
130
+ records = []
131
+ for table in soup.find_all("table"):
132
+ rows = table.find_all("tr")
133
+ if len(rows) < 2:
134
+ continue
135
+ for row in rows[1:]:
136
+ cells = row.find_all(["td", "th"])
137
+ if len(cells) < 2:
138
+ continue
139
+ nome_raw = self.clean(cells[0].get_text())
140
+ matricula = self.clean(cells[1].get_text()) if len(cells) > 1 else None
141
+ if not nome_raw or len(nome_raw) < 3:
142
+ continue
143
+
144
+ # Extrair status inline
145
+ status_match = RE_STATUS_INLINE.search(nome_raw)
146
+ situacao = None
147
+ if status_match:
148
+ situacao = status_match.group(0).strip("()")
149
+ nome_raw = RE_STATUS_INLINE.sub("", nome_raw).strip()
150
+
151
+ records.append({
152
+ "nome": nome_raw,
153
+ "matricula": matricula,
154
+ "situacao": situacao,
155
+ "municipio": "Belo Horizonte",
156
+ })
157
+ if records:
158
+ break
159
+ return records
160
+
161
+ async def parse_leiloeiros(self) -> List[Leiloeiro]:
162
+ # Estrategia 1: Pagina alfabetica (tem contatos completos)
163
+ soup = await self.fetch_page(url=self._URL_ALFA)
164
+ if soup:
165
+ records = self._parse_alfabetica(soup)
166
+ if records:
167
+ logger.info("[MG] Pagina alfabetica: %d registros", len(records))
168
+ return [self.make_leiloeiro(**r) for r in records]
169
+
170
+ # Estrategia 2: Tabela de antiguidade (pelo menos nome + matricula)
171
+ soup = await self.fetch_page(url=self._URL_ANT)
172
+ if soup:
173
+ records = self._parse_antiguidade(soup)
174
+ if records:
175
+ logger.info("[MG] Tabela antiguidade: %d registros", len(records))
176
+ return [self.make_leiloeiro(**r) for r in records]
177
+
178
+ # Estrategia 3: Pagina principal de leiloeiros
179
+ soup = await self.fetch_page(url=self.url)
180
+ if not soup:
181
+ soup = await self.fetch_page_js(url=self.url, wait_ms=3000)
182
+ if not soup:
183
+ return []
184
+
185
+ results: List[Leiloeiro] = []
186
+
187
+ # Tenta tabela
188
+ for table in soup.find_all("table"):
189
+ rows = table.find_all("tr")
190
+ if len(rows) < 2:
191
+ continue
192
+ headers = [self.clean(th.get_text()) for th in rows[0].find_all(["th", "td"])]
193
+ col = {(h or "").lower(): i for i, h in enumerate(headers)}
194
+
195
+ def gcol(cells, frags):
196
+ for k, i in col.items():
197
+ if any(f in k for f in frags) and i < len(cells):
198
+ return self.clean(cells[i].get_text())
199
+ return None
200
+
201
+ for row in rows[1:]:
202
+ cells = row.find_all(["td", "th"])
203
+ if not cells:
204
+ continue
205
+ nome = gcol(cells, ["nome"]) or self.clean(cells[0].get_text())
206
+ if not nome or len(nome) < 3:
207
+ continue
208
+ results.append(self.make_leiloeiro(
209
+ nome=nome,
210
+ matricula=gcol(cells, ["matr", "registro"]),
211
+ situacao=gcol(cells, ["situ", "status"]),
212
+ municipio="Belo Horizonte",
213
+ telefone=gcol(cells, ["tel", "fone"]),
214
+ email=gcol(cells, ["email"]),
215
+ ))
216
+
217
+ logger.info("[MG] Total: %d registros", len(results))
218
+ return results
@@ -0,0 +1,70 @@
1
+ """
2
+ Scraper JUCEP — Junta Comercial do Estado da Paraíba
3
+ URL: https://jucep.pb.gov.br/contatos/leiloeiros
4
+ Método: httpx + BeautifulSoup
5
+ Nota: Domínio antigo jucepb.pb.gov.br não existe mais.
6
+ Junta renomeada/migrada para JUCEP em jucep.pb.gov.br.
7
+ Lista 57 leiloeiros com matrícula, data, endereço, contato, situação (Regular/Irregular).
8
+ Atualizada até 2025.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ from typing import List
13
+
14
+ from .base_scraper import AbstractJuntaScraper, Leiloeiro
15
+
16
+
17
+ class JucepScraper(AbstractJuntaScraper):
18
+ estado = "PB"
19
+ junta = "JUCEP"
20
+ url = "https://jucep.pb.gov.br/contatos/leiloeiros"
21
+
22
+ async def parse_leiloeiros(self) -> List[Leiloeiro]:
23
+ soup = await self.fetch_page()
24
+ if not soup:
25
+ soup = await self.fetch_page_js(wait_ms=3000)
26
+ if not soup:
27
+ return []
28
+
29
+ results: List[Leiloeiro] = []
30
+
31
+ for table in soup.find_all("table"):
32
+ rows = table.find_all("tr")
33
+ if len(rows) < 2:
34
+ continue
35
+ headers = [self.clean(th.get_text()) for th in rows[0].find_all(["th", "td"])]
36
+ col = {(h or "").lower(): i for i, h in enumerate(headers)}
37
+
38
+ def gcol(cells, frags):
39
+ for k, i in col.items():
40
+ if any(f in k for f in frags) and i < len(cells):
41
+ return self.clean(cells[i].get_text())
42
+ return None
43
+
44
+ for row in rows[1:]:
45
+ cells = row.find_all(["td", "th"])
46
+ if not cells:
47
+ continue
48
+ nome = gcol(cells, ["nome", "leiloeiro"]) or self.clean(cells[0].get_text())
49
+ if not nome or len(nome) < 3:
50
+ continue
51
+ results.append(self.make_leiloeiro(
52
+ nome=nome,
53
+ matricula=gcol(cells, ["matr", "registro", "nº"]),
54
+ situacao=gcol(cells, ["situ", "status"]),
55
+ municipio=gcol(cells, ["munic", "cidade"]) or "João Pessoa",
56
+ telefone=gcol(cells, ["tel", "fone", "contato"]),
57
+ email=gcol(cells, ["email", "site"]),
58
+ endereco=gcol(cells, ["ender", "logr"]),
59
+ data_registro=gcol(cells, ["data", "posse", "registro"]),
60
+ ))
61
+ if results:
62
+ break
63
+
64
+ if not results:
65
+ for el in soup.select("li, p, .item"):
66
+ text = self.clean(el.get_text(" | "))
67
+ if text and len(text) > 10:
68
+ results.append(self.make_leiloeiro(nome=text, municipio="João Pessoa"))
69
+
70
+ return results
@@ -0,0 +1,74 @@
1
+ """
2
+ Scraper JUCEPA — Junta Comercial do Estado do Pará
3
+ URL: https://www.jucepa.pa.gov.br/node/171
4
+ Método: httpx + BeautifulSoup (Drupal CMS, node ID fixo)
5
+ Nota: URL /index.php/leiloeiros retornava 404. Node 171 = Leiloeiros Ativos.
6
+ Lista inclui registros desde 1985 até 2026.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import re
11
+ from typing import List
12
+
13
+ from .base_scraper import AbstractJuntaScraper, Leiloeiro
14
+
15
+
16
+ class JucepaScraper(AbstractJuntaScraper):
17
+ estado = "PA"
18
+ junta = "JUCEPA"
19
+ url = "https://www.jucepa.pa.gov.br/node/171"
20
+
21
+ async def parse_leiloeiros(self) -> List[Leiloeiro]:
22
+ soup = await self.fetch_page()
23
+ if not soup:
24
+ soup = await self.fetch_page_js(wait_ms=3000)
25
+ if not soup:
26
+ return []
27
+
28
+ results: List[Leiloeiro] = []
29
+
30
+ # Tabela HTML (formato Drupal)
31
+ for table in soup.find_all("table"):
32
+ rows = table.find_all("tr")
33
+ if len(rows) < 2:
34
+ continue
35
+ headers = [self.clean(th.get_text()) for th in rows[0].find_all(["th", "td"])]
36
+ col = {(h or "").lower(): i for i, h in enumerate(headers)}
37
+
38
+ def gcol(cells, frags):
39
+ for k, i in col.items():
40
+ if any(f in k for f in frags) and i < len(cells):
41
+ return self.clean(cells[i].get_text())
42
+ return None
43
+
44
+ for row in rows[1:]:
45
+ cells = row.find_all(["td", "th"])
46
+ if not cells:
47
+ continue
48
+ nome = gcol(cells, ["nome", "leiloeiro"]) or self.clean(cells[0].get_text())
49
+ if not nome or len(nome) < 3:
50
+ continue
51
+ results.append(self.make_leiloeiro(
52
+ nome=nome,
53
+ matricula=gcol(cells, ["matr", "registro", "nº", "numero"]),
54
+ cpf_cnpj=gcol(cells, ["cpf", "cnpj"]),
55
+ situacao=gcol(cells, ["situ", "status"]),
56
+ municipio=gcol(cells, ["munic", "cidade"]) or "Belém",
57
+ telefone=gcol(cells, ["tel", "fone"]),
58
+ email=gcol(cells, ["email"]),
59
+ endereco=gcol(cells, ["ender", "logr"]),
60
+ data_registro=gcol(cells, ["data", "posse", "registro"]),
61
+ ))
62
+ if results:
63
+ break
64
+
65
+ # Fallback: conteúdo em texto com padrão nome + matrícula
66
+ if not results:
67
+ body = soup.select_one(".field-body, .node-content, article, main")
68
+ if body:
69
+ for el in body.find_all(["p", "li", "div", "tr"]):
70
+ text = self.clean(el.get_text())
71
+ if text and len(text) > 5 and re.search(r"[A-ZÁÉÍÓÚÀÃÕÇ]{3,}", text):
72
+ results.append(self.make_leiloeiro(nome=text, municipio="Belém"))
73
+
74
+ return results
@@ -0,0 +1,80 @@
1
+ """
2
+ Scraper JUCEPAR — Junta Comercial do Paraná
3
+ URL: https://www.juntacomercial.pr.gov.br/Pagina/LEILOEIROS-OFICIAIS
4
+ Método: httpx + BeautifulSoup (tabela HTML ou PDF link)
5
+ Nota: Site migrou de jucepar.pr.gov.br para juntacomercial.pr.gov.br
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import re
10
+ from typing import List
11
+
12
+ from .base_scraper import AbstractJuntaScraper, Leiloeiro
13
+
14
+
15
+ class JuceparScraper(AbstractJuntaScraper):
16
+ estado = "PR"
17
+ junta = "JUCEPAR"
18
+ url = "https://www.juntacomercial.pr.gov.br/Pagina/LEILOEIROS-OFICIAIS"
19
+
20
+ async def parse_leiloeiros(self) -> List[Leiloeiro]:
21
+ soup = await self.fetch_page()
22
+ if not soup:
23
+ # Tenta Playwright se httpx falhar
24
+ soup = await self.fetch_page_js(wait_ms=3000)
25
+ if not soup:
26
+ return []
27
+
28
+ results: List[Leiloeiro] = []
29
+
30
+ # Tentativa 1: tabela HTML
31
+ for table in soup.find_all("table"):
32
+ rows = table.find_all("tr")
33
+ if len(rows) < 2:
34
+ continue
35
+ headers = [self.clean(th.get_text()) for th in rows[0].find_all(["th", "td"])]
36
+ col = {(h or "").lower(): i for i, h in enumerate(headers)}
37
+
38
+ has_relevant = any(
39
+ any(f in (h or "").lower() for f in ["nome", "leiloeiro", "matr"])
40
+ for h in headers
41
+ )
42
+ if not has_relevant:
43
+ continue
44
+
45
+ def gcol(cells, frags):
46
+ for k, i in col.items():
47
+ if any(f in k for f in frags) and i < len(cells):
48
+ return self.clean(cells[i].get_text())
49
+ return None
50
+
51
+ for row in rows[1:]:
52
+ cells = row.find_all(["td", "th"])
53
+ if not cells:
54
+ continue
55
+ nome = gcol(cells, ["nome", "leiloeiro"]) or self.clean(cells[0].get_text())
56
+ if not nome or len(nome) < 3:
57
+ continue
58
+ results.append(self.make_leiloeiro(
59
+ nome=nome,
60
+ matricula=gcol(cells, ["matr", "registro", "nº"]),
61
+ situacao=gcol(cells, ["situ", "status"]),
62
+ municipio=gcol(cells, ["munic", "cidade"]) or "Curitiba",
63
+ telefone=gcol(cells, ["tel", "fone"]),
64
+ email=gcol(cells, ["email"]),
65
+ endereco=gcol(cells, ["ender", "logr"]),
66
+ data_registro=gcol(cells, ["data", "posse", "portaria"]),
67
+ ))
68
+ if results:
69
+ break
70
+
71
+ # Tentativa 2: conteúdo textual com nomes em maiúsculas
72
+ if not results:
73
+ content = soup.select_one("main, article, .conteudo, .page-content, #content")
74
+ if content:
75
+ for p in content.find_all(["p", "li", "div"]):
76
+ text = self.clean(p.get_text())
77
+ if text and len(text) > 5 and re.search(r"[A-ZÁÉÍÓÚÀÃÕÇ]{3,}", text):
78
+ results.append(self.make_leiloeiro(nome=text, municipio="Curitiba"))
79
+
80
+ return results
@@ -0,0 +1,78 @@
1
+ """
2
+ Scraper JUCEPE — Junta Comercial do Estado de Pernambuco
3
+ URL: https://portal.jucepe.pe.gov.br/leiloeiros (SPA em JS)
4
+ PDF: https://portal.jucepe.pe.gov.br/storage/content/leiloeiros.pdf
5
+ Método: Playwright (SPA) com fallback para PDF via httpx
6
+ Nota: Migrou de www.jucepe.pe.gov.br para portal.jucepe.pe.gov.br
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import re
11
+ from typing import List
12
+
13
+ from .base_scraper import AbstractJuntaScraper, Leiloeiro
14
+
15
+
16
+ class JucepeScraper(AbstractJuntaScraper):
17
+ estado = "PE"
18
+ junta = "JUCEPE"
19
+ url = "https://portal.jucepe.pe.gov.br/leiloeiros"
20
+ url_pdf = "https://portal.jucepe.pe.gov.br/storage/content/leiloeiros.pdf"
21
+
22
+ async def parse_leiloeiros(self) -> List[Leiloeiro]:
23
+ # Tenta SPA via Playwright primeiro
24
+ soup = await self.fetch_page_js(
25
+ wait_selector="table, tr td, .leiloeiro",
26
+ wait_ms=6000,
27
+ )
28
+ if not soup:
29
+ # Fallback: página legada (pode ter dados em HTML estático)
30
+ soup = await self.fetch_page(url="https://portal.jucepe.pe.gov.br/leiloeiros")
31
+ if not soup:
32
+ return []
33
+
34
+ results: List[Leiloeiro] = []
35
+
36
+ for table in soup.find_all("table"):
37
+ rows = table.find_all("tr")
38
+ if len(rows) < 2:
39
+ continue
40
+ headers = [self.clean(th.get_text()) for th in rows[0].find_all(["th", "td"])]
41
+ col = {(h or "").lower(): i for i, h in enumerate(headers)}
42
+
43
+ def gcol(cells, frags):
44
+ for k, i in col.items():
45
+ if any(f in k for f in frags) and i < len(cells):
46
+ return self.clean(cells[i].get_text())
47
+ return None
48
+
49
+ for row in rows[1:]:
50
+ cells = row.find_all(["td", "th"])
51
+ if not cells:
52
+ continue
53
+ nome = gcol(cells, ["nome", "leiloeiro"]) or self.clean(cells[0].get_text())
54
+ if not nome or len(nome) < 3:
55
+ continue
56
+ results.append(self.make_leiloeiro(
57
+ nome=nome,
58
+ matricula=gcol(cells, ["matr", "registro", "nº"]),
59
+ cpf_cnpj=gcol(cells, ["cpf", "cnpj"]),
60
+ situacao=gcol(cells, ["situ", "status"]),
61
+ municipio=gcol(cells, ["munic", "cidade"]) or "Recife",
62
+ telefone=gcol(cells, ["tel", "fone"]),
63
+ email=gcol(cells, ["email"]),
64
+ endereco=gcol(cells, ["ender", "logr"]),
65
+ data_registro=gcol(cells, ["data", "posse"]),
66
+ ))
67
+ if results:
68
+ break
69
+
70
+ if not results:
71
+ content = soup.select_one("main, #app, #root, .content, article")
72
+ if content:
73
+ for el in content.find_all(["li", "p", "div"]):
74
+ text = self.clean(el.get_text())
75
+ if text and len(text) > 10 and re.search(r"[A-ZÁÉÍÓÚ]{3,}", text):
76
+ results.append(self.make_leiloeiro(nome=text, municipio="Recife"))
77
+
78
+ return results
@@ -0,0 +1,69 @@
1
+ """
2
+ Scraper JUCEPI — Junta Comercial do Estado do Piauí
3
+ URL: https://portal.pi.gov.br/jucepi/leiloeiro-oficial/
4
+ Método: httpx + BeautifulSoup
5
+ Nota: Site migrou para portal estadual integrado (portal.pi.gov.br/jucepi).
6
+ Lista inclui matrícula, data, endereço, telefone, email, situação (regular/irregular/cancelado).
7
+ Portarias de 2025 confirmadas.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ from typing import List
12
+
13
+ from .base_scraper import AbstractJuntaScraper, Leiloeiro
14
+
15
+
16
+ class JucepiScraper(AbstractJuntaScraper):
17
+ estado = "PI"
18
+ junta = "JUCEPI"
19
+ url = "https://portal.pi.gov.br/jucepi/leiloeiro-oficial/"
20
+
21
+ async def parse_leiloeiros(self) -> List[Leiloeiro]:
22
+ soup = await self.fetch_page()
23
+ if not soup:
24
+ soup = await self.fetch_page_js(wait_ms=3000)
25
+ if not soup:
26
+ return []
27
+
28
+ results: List[Leiloeiro] = []
29
+
30
+ for table in soup.find_all("table"):
31
+ rows = table.find_all("tr")
32
+ if len(rows) < 2:
33
+ continue
34
+ headers = [self.clean(th.get_text()) for th in rows[0].find_all(["th", "td"])]
35
+ col = {(h or "").lower(): i for i, h in enumerate(headers)}
36
+
37
+ def gcol(cells, frags):
38
+ for k, i in col.items():
39
+ if any(f in k for f in frags) and i < len(cells):
40
+ return self.clean(cells[i].get_text())
41
+ return None
42
+
43
+ for row in rows[1:]:
44
+ cells = row.find_all(["td", "th"])
45
+ if not cells:
46
+ continue
47
+ nome = gcol(cells, ["nome", "leiloeiro"]) or self.clean(cells[0].get_text())
48
+ if not nome or len(nome) < 3:
49
+ continue
50
+ results.append(self.make_leiloeiro(
51
+ nome=nome,
52
+ matricula=gcol(cells, ["matr", "registro", "nº"]),
53
+ situacao=gcol(cells, ["situ", "status"]),
54
+ municipio=gcol(cells, ["munic", "cidade"]) or "Teresina",
55
+ telefone=gcol(cells, ["tel", "fone"]),
56
+ email=gcol(cells, ["email"]),
57
+ endereco=gcol(cells, ["ender", "logr", "endere"]),
58
+ data_registro=gcol(cells, ["data", "posse", "registro"]),
59
+ ))
60
+ if results:
61
+ break
62
+
63
+ if not results:
64
+ for el in soup.select(".entry-content li, .conteudo li, article li, p"):
65
+ text = self.clean(el.get_text(" | "))
66
+ if text and len(text) > 10:
67
+ results.append(self.make_leiloeiro(nome=text, municipio="Teresina"))
68
+
69
+ return results