mega-brain-ai 1.3.0

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 (510) hide show
  1. package/.antigravity/README.md +46 -0
  2. package/.antigravity/rules/.gitkeep +0 -0
  3. package/.antigravity/rules/mega-brain.md +39 -0
  4. package/.claude/CLAUDE.md +172 -0
  5. package/.claude/agents.yaml +44 -0
  6. package/.claude/commands/agents.md +161 -0
  7. package/.claude/commands/ask.md +117 -0
  8. package/.claude/commands/benchmark.md +224 -0
  9. package/.claude/commands/chat.md +343 -0
  10. package/.claude/commands/compare.md +116 -0
  11. package/.claude/commands/conclave.md +196 -0
  12. package/.claude/commands/config.md +133 -0
  13. package/.claude/commands/create-agent.md +467 -0
  14. package/.claude/commands/debate.md +159 -0
  15. package/.claude/commands/documentation/create-architecture-documentation.md +175 -0
  16. package/.claude/commands/dossiers.md +180 -0
  17. package/.claude/commands/evolve.md +223 -0
  18. package/.claude/commands/extract-dna.md +172 -0
  19. package/.claude/commands/extract-knowledge.md +507 -0
  20. package/.claude/commands/gsd/add-phase.md +43 -0
  21. package/.claude/commands/gsd/add-tests.md +41 -0
  22. package/.claude/commands/gsd/add-todo.md +47 -0
  23. package/.claude/commands/gsd/audit-milestone.md +36 -0
  24. package/.claude/commands/gsd/check-todos.md +45 -0
  25. package/.claude/commands/gsd/cleanup.md +18 -0
  26. package/.claude/commands/gsd/complete-milestone.md +136 -0
  27. package/.claude/commands/gsd/debug.md +167 -0
  28. package/.claude/commands/gsd/discuss-phase.md +83 -0
  29. package/.claude/commands/gsd/execute-phase.md +41 -0
  30. package/.claude/commands/gsd/health.md +22 -0
  31. package/.claude/commands/gsd/help.md +22 -0
  32. package/.claude/commands/gsd/insert-phase.md +32 -0
  33. package/.claude/commands/gsd/join-discord.md +18 -0
  34. package/.claude/commands/gsd/list-phase-assumptions.md +46 -0
  35. package/.claude/commands/gsd/map-codebase.md +71 -0
  36. package/.claude/commands/gsd/new-milestone.md +44 -0
  37. package/.claude/commands/gsd/new-project.md +42 -0
  38. package/.claude/commands/gsd/pause-work.md +38 -0
  39. package/.claude/commands/gsd/plan-milestone-gaps.md +34 -0
  40. package/.claude/commands/gsd/plan-phase.md +45 -0
  41. package/.claude/commands/gsd/progress.md +24 -0
  42. package/.claude/commands/gsd/quick.md +41 -0
  43. package/.claude/commands/gsd/reapply-patches.md +110 -0
  44. package/.claude/commands/gsd/remove-phase.md +31 -0
  45. package/.claude/commands/gsd/research-phase.md +189 -0
  46. package/.claude/commands/gsd/resume-work.md +40 -0
  47. package/.claude/commands/gsd/set-profile.md +34 -0
  48. package/.claude/commands/gsd/settings.md +36 -0
  49. package/.claude/commands/gsd/update.md +37 -0
  50. package/.claude/commands/gsd/verify-work.md +38 -0
  51. package/.claude/commands/inbox.md +296 -0
  52. package/.claude/commands/ingest-empresa.md +191 -0
  53. package/.claude/commands/ingest.md +183 -0
  54. package/.claude/commands/jarvis-briefing.md +67 -0
  55. package/.claude/commands/jarvis-control.md +169 -0
  56. package/.claude/commands/jarvis-full.md +182 -0
  57. package/.claude/commands/jarvis.md +212 -0
  58. package/.claude/commands/ler-drive.md +212 -0
  59. package/.claude/commands/log.md +158 -0
  60. package/.claude/commands/loop.md +133 -0
  61. package/.claude/commands/loops.md +73 -0
  62. package/.claude/commands/mission-autopilot.md +538 -0
  63. package/.claude/commands/mission.md +353 -0
  64. package/.claude/commands/process-inbox.md +148 -0
  65. package/.claude/commands/process-jarvis.md +3036 -0
  66. package/.claude/commands/process-video.md +131 -0
  67. package/.claude/commands/rag-search.md +78 -0
  68. package/.claude/commands/resume.md +33 -0
  69. package/.claude/commands/save.md +38 -0
  70. package/.claude/commands/scan-inbox.md +125 -0
  71. package/.claude/commands/setup.md +99 -0
  72. package/.claude/commands/system-digest.md +243 -0
  73. package/.claude/commands/verify.md +182 -0
  74. package/.claude/commands/view-dna.md +169 -0
  75. package/.claude/get-shit-done/VERSION +1 -0
  76. package/.claude/get-shit-done/bin/gsd-tools.cjs +588 -0
  77. package/.claude/get-shit-done/bin/lib/commands.cjs +553 -0
  78. package/.claude/get-shit-done/bin/lib/config.cjs +162 -0
  79. package/.claude/get-shit-done/bin/lib/core.cjs +411 -0
  80. package/.claude/get-shit-done/bin/lib/frontmatter.cjs +299 -0
  81. package/.claude/get-shit-done/bin/lib/init.cjs +710 -0
  82. package/.claude/get-shit-done/bin/lib/milestone.cjs +216 -0
  83. package/.claude/get-shit-done/bin/lib/phase.cjs +871 -0
  84. package/.claude/get-shit-done/bin/lib/roadmap.cjs +298 -0
  85. package/.claude/get-shit-done/bin/lib/state.cjs +679 -0
  86. package/.claude/get-shit-done/bin/lib/template.cjs +222 -0
  87. package/.claude/get-shit-done/bin/lib/verify.cjs +773 -0
  88. package/.claude/get-shit-done/references/checkpoints.md +776 -0
  89. package/.claude/get-shit-done/references/continuation-format.md +249 -0
  90. package/.claude/get-shit-done/references/decimal-phase-calculation.md +65 -0
  91. package/.claude/get-shit-done/references/git-integration.md +248 -0
  92. package/.claude/get-shit-done/references/git-planning-commit.md +38 -0
  93. package/.claude/get-shit-done/references/model-profile-resolution.md +34 -0
  94. package/.claude/get-shit-done/references/model-profiles.md +92 -0
  95. package/.claude/get-shit-done/references/phase-argument-parsing.md +61 -0
  96. package/.claude/get-shit-done/references/planning-config.md +196 -0
  97. package/.claude/get-shit-done/references/questioning.md +145 -0
  98. package/.claude/get-shit-done/references/tdd.md +263 -0
  99. package/.claude/get-shit-done/references/ui-brand.md +160 -0
  100. package/.claude/get-shit-done/references/verification-patterns.md +612 -0
  101. package/.claude/get-shit-done/templates/DEBUG.md +164 -0
  102. package/.claude/get-shit-done/templates/UAT.md +247 -0
  103. package/.claude/get-shit-done/templates/VALIDATION.md +76 -0
  104. package/.claude/get-shit-done/templates/codebase/architecture.md +255 -0
  105. package/.claude/get-shit-done/templates/codebase/concerns.md +310 -0
  106. package/.claude/get-shit-done/templates/codebase/conventions.md +307 -0
  107. package/.claude/get-shit-done/templates/codebase/integrations.md +280 -0
  108. package/.claude/get-shit-done/templates/codebase/stack.md +186 -0
  109. package/.claude/get-shit-done/templates/codebase/structure.md +285 -0
  110. package/.claude/get-shit-done/templates/codebase/testing.md +480 -0
  111. package/.claude/get-shit-done/templates/config.json +37 -0
  112. package/.claude/get-shit-done/templates/context.md +283 -0
  113. package/.claude/get-shit-done/templates/continue-here.md +78 -0
  114. package/.claude/get-shit-done/templates/debug-subagent-prompt.md +91 -0
  115. package/.claude/get-shit-done/templates/discovery.md +146 -0
  116. package/.claude/get-shit-done/templates/milestone-archive.md +123 -0
  117. package/.claude/get-shit-done/templates/milestone.md +115 -0
  118. package/.claude/get-shit-done/templates/phase-prompt.md +569 -0
  119. package/.claude/get-shit-done/templates/planner-subagent-prompt.md +117 -0
  120. package/.claude/get-shit-done/templates/project.md +184 -0
  121. package/.claude/get-shit-done/templates/requirements.md +231 -0
  122. package/.claude/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
  123. package/.claude/get-shit-done/templates/research-project/FEATURES.md +147 -0
  124. package/.claude/get-shit-done/templates/research-project/PITFALLS.md +200 -0
  125. package/.claude/get-shit-done/templates/research-project/STACK.md +120 -0
  126. package/.claude/get-shit-done/templates/research-project/SUMMARY.md +170 -0
  127. package/.claude/get-shit-done/templates/research.md +552 -0
  128. package/.claude/get-shit-done/templates/retrospective.md +54 -0
  129. package/.claude/get-shit-done/templates/roadmap.md +202 -0
  130. package/.claude/get-shit-done/templates/state.md +176 -0
  131. package/.claude/get-shit-done/templates/summary-complex.md +59 -0
  132. package/.claude/get-shit-done/templates/summary-minimal.md +41 -0
  133. package/.claude/get-shit-done/templates/summary-standard.md +48 -0
  134. package/.claude/get-shit-done/templates/summary.md +248 -0
  135. package/.claude/get-shit-done/templates/user-setup.md +311 -0
  136. package/.claude/get-shit-done/templates/verification-report.md +322 -0
  137. package/.claude/get-shit-done/workflows/add-phase.md +111 -0
  138. package/.claude/get-shit-done/workflows/add-tests.md +350 -0
  139. package/.claude/get-shit-done/workflows/add-todo.md +157 -0
  140. package/.claude/get-shit-done/workflows/audit-milestone.md +297 -0
  141. package/.claude/get-shit-done/workflows/check-todos.md +176 -0
  142. package/.claude/get-shit-done/workflows/cleanup.md +152 -0
  143. package/.claude/get-shit-done/workflows/complete-milestone.md +763 -0
  144. package/.claude/get-shit-done/workflows/diagnose-issues.md +219 -0
  145. package/.claude/get-shit-done/workflows/discovery-phase.md +289 -0
  146. package/.claude/get-shit-done/workflows/discuss-phase.md +542 -0
  147. package/.claude/get-shit-done/workflows/execute-phase.md +449 -0
  148. package/.claude/get-shit-done/workflows/execute-plan.md +448 -0
  149. package/.claude/get-shit-done/workflows/health.md +156 -0
  150. package/.claude/get-shit-done/workflows/help.md +489 -0
  151. package/.claude/get-shit-done/workflows/insert-phase.md +129 -0
  152. package/.claude/get-shit-done/workflows/list-phase-assumptions.md +178 -0
  153. package/.claude/get-shit-done/workflows/map-codebase.md +315 -0
  154. package/.claude/get-shit-done/workflows/new-milestone.md +382 -0
  155. package/.claude/get-shit-done/workflows/new-project.md +1116 -0
  156. package/.claude/get-shit-done/workflows/pause-work.md +122 -0
  157. package/.claude/get-shit-done/workflows/plan-milestone-gaps.md +274 -0
  158. package/.claude/get-shit-done/workflows/plan-phase.md +569 -0
  159. package/.claude/get-shit-done/workflows/progress.md +381 -0
  160. package/.claude/get-shit-done/workflows/quick.md +453 -0
  161. package/.claude/get-shit-done/workflows/remove-phase.md +154 -0
  162. package/.claude/get-shit-done/workflows/research-phase.md +73 -0
  163. package/.claude/get-shit-done/workflows/resume-project.md +306 -0
  164. package/.claude/get-shit-done/workflows/set-profile.md +80 -0
  165. package/.claude/get-shit-done/workflows/settings.md +213 -0
  166. package/.claude/get-shit-done/workflows/transition.md +544 -0
  167. package/.claude/get-shit-done/workflows/update.md +219 -0
  168. package/.claude/get-shit-done/workflows/verify-phase.md +242 -0
  169. package/.claude/get-shit-done/workflows/verify-work.md +569 -0
  170. package/.claude/gsd-file-manifest.json +144 -0
  171. package/.claude/hooks/agent_creation_trigger.py +168 -0
  172. package/.claude/hooks/agent_index_updater.py +255 -0
  173. package/.claude/hooks/agent_memory_persister.py +203 -0
  174. package/.claude/hooks/claude_md_agent_sync.py +162 -0
  175. package/.claude/hooks/claude_md_guard.py +154 -0
  176. package/.claude/hooks/continuous_save.py +414 -0
  177. package/.claude/hooks/creation_validator.py +360 -0
  178. package/.claude/hooks/enforce_dual_location.py +501 -0
  179. package/.claude/hooks/enforce_plan_mode.py +220 -0
  180. package/.claude/hooks/gsd-check-update.js +62 -0
  181. package/.claude/hooks/gsd-context-monitor.js +122 -0
  182. package/.claude/hooks/gsd-statusline.js +108 -0
  183. package/.claude/hooks/inbox_age_alert.py +367 -0
  184. package/.claude/hooks/ledger_updater.py +303 -0
  185. package/.claude/hooks/memory_hints_injector.py +251 -0
  186. package/.claude/hooks/memory_updater.py +202 -0
  187. package/.claude/hooks/notification_system.py +115 -0
  188. package/.claude/hooks/pending_tracker.py +188 -0
  189. package/.claude/hooks/pipeline_checkpoint.py +583 -0
  190. package/.claude/hooks/post_batch_cascading.py +1740 -0
  191. package/.claude/hooks/post_tool_use.py +120 -0
  192. package/.claude/hooks/quality_watchdog.py +394 -0
  193. package/.claude/hooks/ralph_wiggum.py +286 -0
  194. package/.claude/hooks/session-source-sync.py +223 -0
  195. package/.claude/hooks/session_autosave_v2.py +1135 -0
  196. package/.claude/hooks/session_end.py +203 -0
  197. package/.claude/hooks/session_start.py +939 -0
  198. package/.claude/hooks/skill_indexer.py +48 -0
  199. package/.claude/hooks/skill_router.py +358 -0
  200. package/.claude/hooks/stop_hook_completeness.py +187 -0
  201. package/.claude/hooks/user_prompt_submit.py +125 -0
  202. package/.claude/package.json +1 -0
  203. package/.claude/rules/ANTHROPIC-STANDARDS.md +384 -0
  204. package/.claude/rules/CLAUDE-LITE.md +201 -0
  205. package/.claude/rules/RULE-GROUP-1.md +320 -0
  206. package/.claude/rules/RULE-GROUP-2.md +307 -0
  207. package/.claude/rules/RULE-GROUP-3.md +248 -0
  208. package/.claude/rules/RULE-GROUP-4.md +427 -0
  209. package/.claude/rules/RULE-GROUP-5.md +388 -0
  210. package/.claude/rules/RULE-GROUP-6.md +387 -0
  211. package/.claude/rules/RULE-GSD-MANDATORY.md +106 -0
  212. package/.claude/rules/agent-cognition.md +779 -0
  213. package/.claude/rules/agent-integrity.md +692 -0
  214. package/.claude/rules/epistemic-standards.md +333 -0
  215. package/.claude/rules/logging.md +53 -0
  216. package/.claude/rules/mcp-governance.md +128 -0
  217. package/.claude/rules/pipeline.md +60 -0
  218. package/.claude/rules/state-management.md +93 -0
  219. package/.claude/scripts/apply-tags.py +77 -0
  220. package/.claude/scripts/batch-extract-transcriptions.py +132 -0
  221. package/.claude/scripts/build-complete-index.py +250 -0
  222. package/.claude/scripts/build-planilha-index.py +170 -0
  223. package/.claude/scripts/complete-tag-matching.py +250 -0
  224. package/.claude/scripts/deduplicate-inbox.py +139 -0
  225. package/.claude/scripts/docx-xml-extractor.py +141 -0
  226. package/.claude/scripts/extract-docx-text.py +58 -0
  227. package/.claude/scripts/extract-single-transcription.py +74 -0
  228. package/.claude/scripts/extract_docx_from_gdrive.py +77 -0
  229. package/.claude/scripts/jarvis_orchestrator.py +5 -0
  230. package/.claude/scripts/organized-downloader.py +246 -0
  231. package/.claude/scripts/planilha-tagger.py +187 -0
  232. package/.claude/scripts/revert-tags.py +70 -0
  233. package/.claude/scripts/source-sync.py +265 -0
  234. package/.claude/scripts/tag-inbox-files.py +276 -0
  235. package/.claude/scripts/tag-inbox-v2.py +253 -0
  236. package/.claude/scripts/test-extraction.py +35 -0
  237. package/.claude/scripts/test-full-extraction.py +74 -0
  238. package/.claude/scripts/validate_cascading_integrity.py +409 -0
  239. package/.claude/settings.json +215 -0
  240. package/.claude/skills/DETECTION-PROTOCOL.md +217 -0
  241. package/.claude/skills/README.md +240 -0
  242. package/.claude/skills/SKILL-REGISTRY.md +283 -0
  243. package/.claude/skills/SKILL-SUGGESTIONS.md +114 -0
  244. package/.claude/skills/_TEMPLATES/SKILL-WRITER-GUIDE.md +385 -0
  245. package/.claude/skills/agent-creation/SKILL.md +374 -0
  246. package/.claude/skills/ask-company/SKILL.md +198 -0
  247. package/.claude/skills/brainstorming/SKILL.md +72 -0
  248. package/.claude/skills/chronicler/SKILL.md +146 -0
  249. package/.claude/skills/chronicler/chronicler_core.py +468 -0
  250. package/.claude/skills/code-review/SKILL.md +160 -0
  251. package/.claude/skills/convert-to-company-docs/SKILL.md +68 -0
  252. package/.claude/skills/convert-to-company-docs/convert.py +532 -0
  253. package/.claude/skills/dispatching-parallel-agents/SKILL.md +193 -0
  254. package/.claude/skills/docs-megabrain/SKILL.md +251 -0
  255. package/.claude/skills/executing-plans/SKILL.md +114 -0
  256. package/.claude/skills/executor/SKILL.md +161 -0
  257. package/.claude/skills/fase-2-5-tagging/SKILL.md +182 -0
  258. package/.claude/skills/feature-dev/SKILL.md +154 -0
  259. package/.claude/skills/frontend-design/SKILL.md +165 -0
  260. package/.claude/skills/gdrive-transcription-downloader/SKILL.md +249 -0
  261. package/.claude/skills/gemini-fallback/SKILL.md +67 -0
  262. package/.claude/skills/gemini-fallback/gemini_fetch.py +0 -0
  263. package/.claude/skills/gha/SKILL.md +96 -0
  264. package/.claude/skills/gha/gha_diagnostic.py +227 -0
  265. package/.claude/skills/github-workflow/SKILL.md +190 -0
  266. package/.claude/skills/hookify/SKILL.md +134 -0
  267. package/.claude/skills/hybrid-source-reading/SKILL.md +265 -0
  268. package/.claude/skills/jarvis/SKILL.md +546 -0
  269. package/.claude/skills/jarvis-briefing/SKILL.md +340 -0
  270. package/.claude/skills/knowledge-extraction/SKILL.md +318 -0
  271. package/.claude/skills/ler-planilha/SKILL.md +281 -0
  272. package/.claude/skills/pipeline-jarvis/SKILL.md +430 -0
  273. package/.claude/skills/plugin-dev/SKILL.md +176 -0
  274. package/.claude/skills/pr-review-toolkit/SKILL.md +178 -0
  275. package/.claude/skills/process-company-inbox/SKILL.md +183 -0
  276. package/.claude/skills/python-megabrain/SKILL.md +323 -0
  277. package/.claude/skills/resume/SKILL.md +61 -0
  278. package/.claude/skills/save/SKILL.md +87 -0
  279. package/.claude/skills/skill-creator-internal/SKILL.md +186 -0
  280. package/.claude/skills/skill-writer/SKILL.md +153 -0
  281. package/.claude/skills/skill-writer/examples.md +191 -0
  282. package/.claude/skills/skill-writer/troubleshooting.md +205 -0
  283. package/.claude/skills/smart-download-tagger/SKILL.md +148 -0
  284. package/.claude/skills/source-sync/SKILL.md +240 -0
  285. package/.claude/skills/sync-docs/SKILL.md +193 -0
  286. package/.claude/skills/sync-docs/config.json +37 -0
  287. package/.claude/skills/sync-docs/gdrive_sync.py +358 -0
  288. package/.claude/skills/sync-docs/reauth.py +71 -0
  289. package/.claude/skills/using-superpowers/SKILL.md +105 -0
  290. package/.claude/skills/verification-before-completion/SKILL.md +130 -0
  291. package/.claude/skills/verify/SKILL.md +154 -0
  292. package/.claude/skills/verify/verify_runner.py +0 -0
  293. package/.claude/skills/verify-6-levels/SKILL.md +234 -0
  294. package/.claude/skills/writing-plans/SKILL.md +184 -0
  295. package/.claude/templates/BATCH-LOG-TEMPLATE.md +221 -0
  296. package/.claudeignore +9 -0
  297. package/.cursor/agents.yaml +44 -0
  298. package/.cursor/rules/mega-brain.md +39 -0
  299. package/.gitattributes +19 -0
  300. package/.github/CODEOWNERS +8 -0
  301. package/.github/ISSUE_TEMPLATE/agent.md +96 -0
  302. package/.github/ISSUE_TEMPLATE/bug.md +67 -0
  303. package/.github/ISSUE_TEMPLATE/feature.md +56 -0
  304. package/.github/ISSUE_TEMPLATE/pipeline.md +70 -0
  305. package/.github/PULL_REQUEST_TEMPLATE.md +30 -0
  306. package/.github/assets/banner.svg +152 -0
  307. package/.github/assets/logo-dark.svg +79 -0
  308. package/.github/assets/social-preview.png +0 -0
  309. package/.github/layer1-allowlist.txt +196 -0
  310. package/.github/layer2-manifest.txt +42 -0
  311. package/.github/layer3-manifest.txt +94 -0
  312. package/.github/workflows/claude-code-pr.yml +198 -0
  313. package/.github/workflows/claude-code-review.yml +57 -0
  314. package/.github/workflows/claude.yml +76 -0
  315. package/.github/workflows/publish-pro.yml +72 -0
  316. package/.github/workflows/publish.yml +86 -0
  317. package/.github/workflows/verification.yml +251 -0
  318. package/.gitignore +244 -0
  319. package/.gitleaks.toml +118 -0
  320. package/.windsurf/agents.yaml +44 -0
  321. package/.windsurf/rules/mega-brain.md +39 -0
  322. package/CONTRIBUTING.md +62 -0
  323. package/QUICK-START.md +231 -0
  324. package/README.md +168 -0
  325. package/agents/AGENT-INDEX.yaml +107 -0
  326. package/agents/MASTER-AGENT.md +612 -0
  327. package/agents/README.md +48 -0
  328. package/agents/_templates/INDEX.md +741 -0
  329. package/agents/_templates/TEMPLATE-AGENT-MD-ULTRA-ROBUSTO-V3.md +2399 -0
  330. package/agents/boardroom/CHECKLIST-MASTER.md +281 -0
  331. package/agents/boardroom/INTEGRATION-GUIDE.md +406 -0
  332. package/agents/boardroom/README.md +238 -0
  333. package/agents/boardroom/config/BOARDROOM-CONFIG.md +186 -0
  334. package/agents/boardroom/config/TTS-INTEGRATION.md +258 -0
  335. package/agents/boardroom/config/VOICE-PROFILES.md +624 -0
  336. package/agents/boardroom/scripts/audio_generator.py +375 -0
  337. package/agents/boardroom/scripts/audio_generator_edge.py +353 -0
  338. package/agents/boardroom/scripts/jarvis_boardroom_hook.py +415 -0
  339. package/agents/boardroom/scripts/notebooklm_generator.py +578 -0
  340. package/agents/boardroom/templates/EPISODE-TEMPLATE.md +367 -0
  341. package/agents/boardroom/templates/scene-templates/SCENE-AGENT-DEBATE.md +252 -0
  342. package/agents/boardroom/templates/scene-templates/SCENE-COUNCIL.md +270 -0
  343. package/agents/boardroom/templates/scene-templates/SCENE-DNA-CONSULTATION.md +126 -0
  344. package/agents/boardroom/templates/scene-templates/SCENE-QUESTION.md +174 -0
  345. package/agents/boardroom/workflows/WORKFLOW-AUDIO-GENERATION.md +421 -0
  346. package/agents/conclave/CRITIC.md +197 -0
  347. package/agents/conclave/DEVILS-ADVOCATE.md +274 -0
  348. package/agents/conclave/README.md +35 -0
  349. package/agents/conclave/SYNTHESIZER.md +293 -0
  350. package/agents/conclave/advogado-do-diabo/AGENT.md +502 -0
  351. package/agents/conclave/advogado-do-diabo/SOUL.md +100 -0
  352. package/agents/conclave/critico-metodologico/AGENT.md +683 -0
  353. package/agents/conclave/critico-metodologico/SOUL.md +107 -0
  354. package/agents/conclave/sintetizador/AGENT.md +571 -0
  355. package/agents/conclave/sintetizador/SOUL.md +94 -0
  356. package/agents/constitution/BASE-CONSTITUTION.md +254 -0
  357. package/agents/persona-registry.yaml +300 -0
  358. package/agents/sua-empresa/.gitkeep +0 -0
  359. package/agents/sua-empresa/README.md +44 -0
  360. package/agents/sua-empresa/_example/jds/EXAMPLE-JD.md +42 -0
  361. package/agents/sua-empresa/_example/org/EXAMPLE-ORG.md +32 -0
  362. package/agents/sua-empresa/_example/roles/EXAMPLE-ROLE.md +38 -0
  363. package/artifacts/README.md +11 -0
  364. package/artifacts/canonical/.gitkeep +0 -0
  365. package/artifacts/chunks/.gitkeep +0 -0
  366. package/artifacts/insights/.gitkeep +0 -0
  367. package/artifacts/narratives/.gitkeep +0 -0
  368. package/bin/cli.js +2 -0
  369. package/bin/lib/ascii-art.js +202 -0
  370. package/bin/lib/feature-gate.js +46 -0
  371. package/bin/lib/installer.js +593 -0
  372. package/bin/lib/license.js +59 -0
  373. package/bin/lib/pro-commands.js +75 -0
  374. package/bin/lib/setup-wizard.js +547 -0
  375. package/bin/lib/validate-email.js +113 -0
  376. package/bin/mega-brain.js +136 -0
  377. package/bin/pre-publish-gate.js +229 -0
  378. package/bin/push.js +1056 -0
  379. package/bin/templates/env.example +27 -0
  380. package/bin/utils/pro-detector.js +50 -0
  381. package/bin/validate-package.js +190 -0
  382. package/core/__init__.py +2 -0
  383. package/core/glossary/INDEX.md +63 -0
  384. package/core/glossary/digital.md +243 -0
  385. package/core/glossary/finance.md +49 -0
  386. package/core/glossary/marketing.md +69 -0
  387. package/core/glossary/operations.md +50 -0
  388. package/core/glossary/sales.md +690 -0
  389. package/core/intelligence/__init__.py +41 -0
  390. package/core/intelligence/agent_trigger.py +468 -0
  391. package/core/intelligence/audit_layers.py +491 -0
  392. package/core/intelligence/autonomous_processor.py +796 -0
  393. package/core/intelligence/bootstrap_registry.py +550 -0
  394. package/core/intelligence/business_model_detector.py +476 -0
  395. package/core/intelligence/dossier_trigger.py +336 -0
  396. package/core/intelligence/entity_normalizer.py +565 -0
  397. package/core/intelligence/org_chain_detector.py +411 -0
  398. package/core/intelligence/review_dashboard.py +338 -0
  399. package/core/intelligence/role_detector.py +855 -0
  400. package/core/intelligence/session_autosave.py +46 -0
  401. package/core/intelligence/skill_generator.py +601 -0
  402. package/core/intelligence/sow_generator.py +711 -0
  403. package/core/intelligence/sync_package_files.py +504 -0
  404. package/core/intelligence/task_orchestrator.py +780 -0
  405. package/core/intelligence/theme_analyzer.py +562 -0
  406. package/core/intelligence/tool_discovery.py +432 -0
  407. package/core/intelligence/validate_json_integrity.py +106 -0
  408. package/core/intelligence/validate_layers.py +310 -0
  409. package/core/intelligence/verify_classifications.py +94 -0
  410. package/core/intelligence/viability_scorer.py +592 -0
  411. package/core/jarvis/02-JARVIS-SOUL.md +390 -0
  412. package/core/jarvis/03-JARVIS-DNA.yaml +312 -0
  413. package/core/jarvis/AGENT.md +191 -0
  414. package/core/jarvis/agent-creator/AGENT.md +199 -0
  415. package/core/jarvis/agent-creator/SOUL.md +82 -0
  416. package/core/jarvis/agent-creator/tasks/create-agent.md +133 -0
  417. package/core/jarvis/agent-creator/tasks/sync-agents.md +100 -0
  418. package/core/jarvis/agent-creator/workflows/wf-create-agent.yaml +110 -0
  419. package/core/jarvis/agent-creator/workflows/wf-pipeline-trigger.yaml +111 -0
  420. package/core/jarvis/autonomous/benchmark/AGENT.md +347 -0
  421. package/core/jarvis/autonomous/benchmark/SOUL.md +78 -0
  422. package/core/jarvis/autonomous/critic/AGENT.md +324 -0
  423. package/core/jarvis/autonomous/critic/SOUL.md +78 -0
  424. package/core/jarvis/autonomous/evolver/AGENT.md +294 -0
  425. package/core/jarvis/autonomous/evolver/SOUL.md +85 -0
  426. package/core/jarvis/autonomous/playbook-generator/AGENT.md +399 -0
  427. package/core/jarvis/autonomous/playbook-generator/SOUL.md +80 -0
  428. package/core/patterns/_ROLE_PATTERNS.yaml +547 -0
  429. package/core/patterns/quality_gates.yaml +259 -0
  430. package/core/patterns/trigger_config.yaml +193 -0
  431. package/core/schemas/SCHEMA-INDEX.md +94 -0
  432. package/core/schemas/canonical-map.schema.json +98 -0
  433. package/core/schemas/chunks-state.schema.json +131 -0
  434. package/core/schemas/decisions-registry.schema.json +120 -0
  435. package/core/schemas/file-registry.schema.json +69 -0
  436. package/core/schemas/insights-state.schema.json +111 -0
  437. package/core/schemas/narratives-state.schema.json +150 -0
  438. package/core/tasks/CHANGELOG.md +55 -0
  439. package/core/tasks/TASK-REGISTRY.md +113 -0
  440. package/core/tasks/_templates/task-tmpl.md +105 -0
  441. package/core/tasks/analyze-themes.md +84 -0
  442. package/core/tasks/detect-role.md +82 -0
  443. package/core/tasks/extract-dna.md +114 -0
  444. package/core/tasks/normalize-entities.md +82 -0
  445. package/core/tasks/process-batch.md +111 -0
  446. package/core/tasks/validate-cascade.md +105 -0
  447. package/core/templates/README.md +27 -0
  448. package/core/templates/agents/dna-config-template.yaml +181 -0
  449. package/core/templates/agents/enrichment-protocol.md +408 -0
  450. package/core/templates/agents/memory-template.md +567 -0
  451. package/core/templates/agents/reasoning-model.md +331 -0
  452. package/core/templates/agents/soul-template.md +416 -0
  453. package/core/templates/agents/template-evolution.md +544 -0
  454. package/core/templates/debates/CONCLAVE-LOG-TEMPLATE-v2.md +309 -0
  455. package/core/templates/debates/conclave-log-template.md +309 -0
  456. package/core/templates/debates/conclave-protocol.md +518 -0
  457. package/core/templates/debates/debate-dynamics-config.yaml +322 -0
  458. package/core/templates/debates/debate-dynamics.md +613 -0
  459. package/core/templates/debates/debate-protocol.md +323 -0
  460. package/core/templates/logs/LOG-TEMPLATES.md +1068 -0
  461. package/core/templates/logs/batch-visual-template.md +841 -0
  462. package/core/templates/logs/log-structure.md +65 -0
  463. package/core/templates/logs/visual-diff.md +159 -0
  464. package/core/templates/phases/dossier-compilation.md +790 -0
  465. package/core/templates/phases/narrative-metabolism.md +292 -0
  466. package/core/templates/phases/narrative-synthesis.md +278 -0
  467. package/core/templates/phases/phase4-checkpoint.md +146 -0
  468. package/core/templates/phases/prompt-1.1-chunking.md +154 -0
  469. package/core/templates/phases/prompt-1.2-entity-resolution.md +186 -0
  470. package/core/templates/phases/prompt-2.1-dna-tags.md +208 -0
  471. package/core/templates/phases/prompt-2.1-insight-extraction.md +191 -0
  472. package/core/templates/phases/prompt-3.1-narrative.md +331 -0
  473. package/core/templates/phases/sources-compilation.md +340 -0
  474. package/core/workflows/PIPELINE-JARVIS-DOCS.md +606 -0
  475. package/core/workflows/wf-conclave.yaml +139 -0
  476. package/core/workflows/wf-extract-dna.yaml +158 -0
  477. package/core/workflows/wf-ingest.yaml +88 -0
  478. package/core/workflows/wf-pipeline-full.yaml +138 -0
  479. package/docs/API-KEYS-GUIDE.md +372 -0
  480. package/docs/INTEGRATION-POINTS.md +501 -0
  481. package/docs/LAYERS.md +403 -0
  482. package/docs/PLAN-MODE-PROTOCOL.md +388 -0
  483. package/docs/RESTORE-AND-INDEX.md +203 -0
  484. package/docs/TAG-RESOLVER-IMPLEMENTATION.md +597 -0
  485. package/docs/conselho.md +337 -0
  486. package/docs/context7-readme.md +28 -0
  487. package/docs/jarvis-logging-protocol.md +380 -0
  488. package/docs/pipeline-completa-v4.md +1315 -0
  489. package/docs/prompts/meta_agente_mapeamento_processos.md +297 -0
  490. package/docs/quick-start.md +197 -0
  491. package/docs/readme-ralph-cascateamento.md +207 -0
  492. package/docs/template-master.md +727 -0
  493. package/docs/templates/phase5/IMPLEMENTATION-GUIDE.md +355 -0
  494. package/docs/templates/phase5/MOGA-BRAIN-PHASE5-TEMPLATES.md +1284 -0
  495. package/docs/templates/phase5/README.md +165 -0
  496. package/docs/workflow-continuous-claude.md +2232 -0
  497. package/inbox/.gitkeep +0 -0
  498. package/inbox/README.md +15 -0
  499. package/knowledge/NAVIGATION-MAP.json +292 -0
  500. package/knowledge/README.md +11 -0
  501. package/knowledge/dna/.gitkeep +0 -0
  502. package/knowledge/dossiers/persons/.gitkeep +0 -0
  503. package/knowledge/dossiers/system/.gitkeep +0 -0
  504. package/knowledge/dossiers/themes/.gitkeep +0 -0
  505. package/knowledge/playbooks/.gitkeep +0 -0
  506. package/knowledge/sources/.gitkeep +0 -0
  507. package/logs/.gitkeep +0 -0
  508. package/logs/README.md +11 -0
  509. package/package.json +180 -0
  510. package/requirements.txt +4 -0
@@ -0,0 +1,1740 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ POST-BATCH CASCADING HOOK - REGRA #22 ENFORCEMENT
4
+ ===================================================
5
+
6
+ Executa cascateamento automatico apos criacao de batch.
7
+
8
+ REGRA #22: A secao "DESTINO DO CONHECIMENTO" nao e informativa - e ORDEM DE EXECUCAO.
9
+
10
+ Este hook:
11
+ 1. E chamado APOS criar qualquer batch
12
+ 2. Le a secao "DESTINO DO CONHECIMENTO" do batch
13
+ 3. Para cada destino:
14
+ - AGENTS: Verificar se existe, criar/atualizar MEMORY.md com CONTEUDO REAL
15
+ - PLAYBOOKS: Verificar se existe, criar/atualizar com CONTEUDO REAL dos frameworks
16
+ - DNAs: Atualizar DNA-CONFIG.yaml
17
+ - DOSSIERS: Atualizar theme dossiers
18
+ 4. Adiciona secao "### Cascateamento Executado" ao batch
19
+ 5. Loga acoes em /logs/cascading.jsonl
20
+
21
+ IMPORTANTE v2.0: Extrai CONTEUDO REAL dos frameworks, nao apenas referencias.
22
+
23
+ v2.1.0: Integra REGRA #26 - Valida integridade antes de marcar completo.
24
+ So marca batch como completo se destinos existem e foram atualizados.
25
+
26
+ Autor: JARVIS
27
+ Versao: 2.1.0
28
+ Data: 2026-01-13
29
+ """
30
+
31
+ import os
32
+ import re
33
+ import json
34
+ import yaml
35
+ from datetime import datetime
36
+ from pathlib import Path
37
+ from typing import Dict, List, Optional, Tuple
38
+
39
+
40
+ #=================================
41
+ # CONFIGURATION
42
+ #=================================
43
+
44
+ PROJECT_DIR = os.environ.get(
45
+ 'CLAUDE_PROJECT_DIR',
46
+ '.'
47
+ )
48
+
49
+ AGENTS_DIR = Path(PROJECT_DIR) / 'agents'
50
+ KNOWLEDGE_DIR = Path(PROJECT_DIR) / 'knowledge'
51
+ DOSSIERS_DIR = KNOWLEDGE_DIR / 'dossiers' / 'themes'
52
+ LOGS_DIR = Path(PROJECT_DIR) / 'logs'
53
+ CASCADING_LOG = LOGS_DIR / 'cascading.jsonl'
54
+
55
+
56
+ #=================================
57
+ # LOGGING
58
+ #=================================
59
+
60
+ def log_cascading_action(action: Dict) -> None:
61
+ """
62
+ Registra acao de cascateamento em JSONL.
63
+
64
+ Args:
65
+ action: Dicionario com detalhes da acao
66
+ """
67
+ LOGS_DIR.mkdir(parents=True, exist_ok=True)
68
+
69
+ action['timestamp'] = datetime.now().isoformat()
70
+
71
+ with open(CASCADING_LOG, 'a', encoding='utf-8') as f:
72
+ f.write(json.dumps(action, ensure_ascii=False) + '\n')
73
+
74
+
75
+ def log_batch_result(batch_id: str, result: Dict) -> None:
76
+ """
77
+ Registra resultado completo do cascateamento de um batch.
78
+ """
79
+ log_cascading_action({
80
+ 'type': 'batch_cascade_complete',
81
+ 'batch_id': batch_id,
82
+ 'result': result
83
+ })
84
+
85
+
86
+ #=================================
87
+ # DESTINATION EXTRACTION
88
+ #=================================
89
+
90
+ def extract_destinations(batch_content: str) -> Dict[str, List[Dict]]:
91
+ """
92
+ Extrai destinos da secao DESTINO DO CONHECIMENTO.
93
+
94
+ Suporta multiplos formatos de batch incluindo:
95
+ - Boxes ASCII com caracteres especiais
96
+ - Formato simples com identacao
97
+ - Blocos de codigo markdown
98
+
99
+ Returns:
100
+ Dict com listas de destinos por tipo
101
+ """
102
+ destinations = {
103
+ 'agents': [],
104
+ 'playbooks': [],
105
+ 'dnas': [],
106
+ 'dossiers': []
107
+ }
108
+
109
+ # Encontrar secao DESTINO DO CONHECIMENTO (mais flexivel)
110
+ # Pode estar com emoji ou sem, com # ou ##
111
+ destino_patterns = [
112
+ r'#+\s*.*DESTINO DO CONHECIMENTO.*?\n(.*?)(?=\n#+\s|\Z)',
113
+ r'DESTINO DO CONHECIMENTO[:\s]*\n(.*?)(?=\n#+\s|\Z)',
114
+ ]
115
+
116
+ destino_section = None
117
+ for pattern in destino_patterns:
118
+ match = re.search(pattern, batch_content, re.DOTALL | re.IGNORECASE)
119
+ if match:
120
+ destino_section = match.group(1)
121
+ break
122
+
123
+ if not destino_section:
124
+ # Fallback: procurar blocos com AGENTES/playbooks/dna diretamente
125
+ destino_section = batch_content
126
+
127
+ # Funcao auxiliar para limpar linha de caracteres de box
128
+ def clean_line(line: str) -> str:
129
+ # Remove caracteres de box ASCII do INICIO e FIM, e espacos extras
130
+ # Primeiro remove do inicio
131
+ cleaned = re.sub(r'^[\s│├└┌┐┘┬┴┼─\|\-\+]+', '', line)
132
+ # Depois remove do fim
133
+ cleaned = re.sub(r'[\s│├└┌┐┘┬┴┼─\|\-\+]+$', '', cleaned)
134
+ return cleaned.strip()
135
+
136
+ # Funcao para verificar se e um nome de agente (MAIUSCULAS-COM-HIFEN)
137
+ def is_agent_name(text: str) -> bool:
138
+ # Nome em maiusculas, pode ter hifen, sem espacos no meio
139
+ return bool(re.match(r'^[A-Z][A-Z0-9]+(?:-[A-Z0-9]+)*$', text))
140
+
141
+ # === EXTRAIR AGENTES ===
142
+ # Procurar bloco que comeca com AGENTES A ALIMENTAR
143
+ agents_patterns = [
144
+ r'AGENTES?\s*A\s*ALIMENTAR[:\s│]*\n(.*?)(?=\n[│\s]*(?:PLAYBOOK|DNA|DOSSIER|└─+\s*$)|```\s*\n|$)',
145
+ r'AGENTES?\s*A\s*ALIMENTAR[:\s]*\n(.*?)(?=PLAYBOOK|DNA\s*A|$)',
146
+ ]
147
+
148
+ for pattern in agents_patterns:
149
+ agents_match = re.search(pattern, destino_section, re.DOTALL | re.IGNORECASE)
150
+ if agents_match:
151
+ agents_block = agents_match.group(1)
152
+ current_agent = None
153
+ frameworks = []
154
+
155
+ for line in agents_block.split('\n'):
156
+ cleaned = clean_line(line)
157
+ if not cleaned:
158
+ continue
159
+
160
+ # Verifica se e um nome de agente
161
+ if is_agent_name(cleaned):
162
+ # Salvar agente anterior
163
+ if current_agent:
164
+ destinations['agents'].append({
165
+ 'name': current_agent,
166
+ 'frameworks': frameworks
167
+ })
168
+ current_agent = cleaned
169
+ frameworks = []
170
+ elif current_agent:
171
+ # E um framework do agente atual
172
+ if cleaned and not cleaned.startswith(('PLAYBOOK', 'dna', 'DOSSIER')):
173
+ frameworks.append(cleaned)
174
+
175
+ # Salvar ultimo agente
176
+ if current_agent:
177
+ destinations['agents'].append({
178
+ 'name': current_agent,
179
+ 'frameworks': frameworks
180
+ })
181
+ break
182
+
183
+ # === EXTRAIR PLAYBOOKS ===
184
+ playbooks_patterns = [
185
+ r'PLAYBOOKS?\s*A\s*ENRIQUECER[:\s│]*\n(.*?)(?=\n[│\s]*(?:DNA|DOSSIER|└─+\s*$)|```\s*\n|$)',
186
+ r'PLAYBOOKS?\s*A\s*ENRIQUECER[:\s]*\n(.*?)(?=DNA\s*A|$)',
187
+ ]
188
+
189
+ for pattern in playbooks_patterns:
190
+ pb_match = re.search(pattern, destino_section, re.DOTALL | re.IGNORECASE)
191
+ if pb_match:
192
+ pb_block = pb_match.group(1)
193
+
194
+ for line in pb_block.split('\n'):
195
+ cleaned = clean_line(line)
196
+ if not cleaned:
197
+ continue
198
+
199
+ # Procurar nome de playbook (PLAYBOOK-XXX ou apenas XXX em maiusculas)
200
+ if cleaned.startswith('PLAYBOOK'):
201
+ name = cleaned.split()[0] if ' ' in cleaned else cleaned
202
+ # Remover : do final se existir
203
+ name = name.rstrip(':')
204
+ desc = cleaned[len(name):].strip().lstrip(':').strip() if len(cleaned) > len(name) else ''
205
+ destinations['playbooks'].append({
206
+ 'name': name,
207
+ 'description': desc
208
+ })
209
+ elif is_agent_name(cleaned) and not cleaned.startswith(('dna', 'DOSSIER')):
210
+ # Pode ser um playbook sem prefixo PLAYBOOK-
211
+ destinations['playbooks'].append({
212
+ 'name': cleaned,
213
+ 'description': ''
214
+ })
215
+ elif cleaned.startswith('"') or cleaned.startswith("'"):
216
+ # E uma descricao do playbook anterior
217
+ if destinations['playbooks']:
218
+ destinations['playbooks'][-1]['description'] = cleaned.strip('"\'')
219
+ break
220
+
221
+ # === EXTRAIR DNAs ===
222
+ dna_patterns = [
223
+ r'DNAS?\s*A\s*CONSOLIDAR[:\s│]*\n(.*?)(?=\n[│\s]*(?:PLAYBOOK|DOSSIER|└─+\s*$)|```\s*\n|$)',
224
+ r'DNAS?\s*A\s*CONSOLIDAR[:\s]*\n(.*?)(?=PLAYBOOK|$)',
225
+ ]
226
+
227
+ for pattern in dna_patterns:
228
+ dna_match = re.search(pattern, destino_section, re.DOTALL | re.IGNORECASE)
229
+ if dna_match:
230
+ dna_block = dna_match.group(1)
231
+
232
+ for line in dna_block.split('\n'):
233
+ cleaned = clean_line(line)
234
+ if not cleaned:
235
+ continue
236
+
237
+ # Procurar DNA-NOME e quantidade
238
+ if 'dna' in cleaned.upper():
239
+ dna_name_match = re.search(r'(DNA[-_]?[A-Z0-9\-]+)', cleaned, re.IGNORECASE)
240
+ if dna_name_match:
241
+ name = dna_name_match.group(1).upper().replace('_', '-')
242
+ # Extrair quantidade de elementos
243
+ elements_match = re.search(r'\+?(\d+)\s*elementos?', cleaned, re.IGNORECASE)
244
+ elements = int(elements_match.group(1)) if elements_match else 0
245
+ destinations['dnas'].append({
246
+ 'name': name,
247
+ 'elements_to_add': elements
248
+ })
249
+ break
250
+
251
+ # === EXTRAIR TEMAS/dossiers ===
252
+ # Procurar na secao de analise de temas
253
+ themes_patterns = [
254
+ r'TEMAS?\s*(?:NOVOS?|CONSOLIDADOS?)[:\s│]*\n(.*?)(?=\n[│\s]*(?:TEMAS?|CROSS|└─+\s*$)|```\s*\n|$)',
255
+ r'TEMAS?\s*NOVOS?[:\s]*\n(.*?)(?=TEMAS?\s*CONSOLIDADOS?|CROSS|$)',
256
+ r'TEMAS?\s*CONSOLIDADOS?[:\s]*\n(.*?)(?=CROSS|$)',
257
+ ]
258
+
259
+ for pattern in themes_patterns:
260
+ themes_matches = list(re.finditer(pattern, batch_content, re.DOTALL | re.IGNORECASE))
261
+ if themes_matches:
262
+ for themes_match in themes_matches:
263
+ themes_block = themes_match.group(1)
264
+ for line in themes_block.split('\n'):
265
+ cleaned = clean_line(line)
266
+ if not cleaned:
267
+ continue
268
+ # Verificar se e um nome de tema valido
269
+ if is_agent_name(cleaned):
270
+ theme_name = cleaned
271
+ if not any(d['name'] == theme_name for d in destinations['dossiers']):
272
+ destinations['dossiers'].append({
273
+ 'name': theme_name,
274
+ 'type': 'theme'
275
+ })
276
+ break # Sair do loop de patterns se encontrou algo
277
+
278
+ return destinations
279
+
280
+
281
+ def extract_batch_metadata(batch_content: str) -> Dict:
282
+ """
283
+ Extrai metadados do batch (source, ID, elementos, etc).
284
+ """
285
+ metadata = {
286
+ 'batch_id': '',
287
+ 'source': '',
288
+ 'elements_count': 0,
289
+ 'frameworks': [],
290
+ 'frameworks_content': {}, # NOVO: conteudo real dos frameworks
291
+ 'heuristics': [],
292
+ 'heuristics_content': '', # NOVO: bloco completo de heuristicas
293
+ 'methodologies': [],
294
+ 'methodologies_content': '', # NOVO: bloco completo de metodologias
295
+ 'filosofias_content': '', # NOVO: bloco de filosofias
296
+ 'modelos_mentais_content': '' # NOVO: bloco de modelos mentais
297
+ }
298
+
299
+ # Extrair BATCH ID
300
+ batch_match = re.search(r'BATCH[\-_]?(\d+)', batch_content)
301
+ if batch_match:
302
+ metadata['batch_id'] = f"BATCH-{batch_match.group(1)}"
303
+
304
+ # Extrair SOURCE
305
+ source_match = re.search(r'(?:Source|FONTE)[:\s]+([A-Z][A-Z\s\-]+)', batch_content)
306
+ if source_match:
307
+ metadata['source'] = source_match.group(1).strip()
308
+
309
+ # Extrair total de elementos
310
+ elements_match = re.search(r'(?:TOTAL|Elementos?)[:\s]+(\d+)', batch_content)
311
+ if elements_match:
312
+ metadata['elements_count'] = int(elements_match.group(1))
313
+
314
+ #=============================
315
+ # EXTRAIR FRAMEWORKS COM CONTEUDO REAL
316
+ #=============================
317
+ fw_section_match = re.search(
318
+ r'(?:##\s*)?(?:🏗️\s*)?KEY\s*FRAMEWORKS?.*?\n(.*?)(?=\n---|\n##|\Z)',
319
+ batch_content, re.DOTALL | re.IGNORECASE
320
+ )
321
+ if fw_section_match:
322
+ fw_section = fw_section_match.group(1)
323
+
324
+ # Extrair cada framework como bloco ASCII completo
325
+ # Pattern: FRAMEWORK N: NOME seguido de box ate proximo FRAMEWORK ou fim
326
+ framework_blocks = extract_ascii_boxes(fw_section, 'FRAMEWORK')
327
+
328
+ for name, content in framework_blocks.items():
329
+ metadata['frameworks'].append(name)
330
+ metadata['frameworks_content'][name] = content
331
+
332
+ #=============================
333
+ # EXTRAIR HEURISTICAS COM CONTEUDO REAL
334
+ #=============================
335
+ # Buscar secao que comeca com ## HEURISTICAS ou similar
336
+ heur_section_match = re.search(
337
+ r'(?:##\s*)?(?:🔢\s*)?HEUR[IÍ]STICAS?\s*(?:COM\s*N[UÚ]MEROS?)?\s*(?:\(\d+\))?\s*\n(```\n)?(.*?)(?=\n```\n|\n---|\n##[^#]|\Z)',
338
+ batch_content, re.DOTALL | re.IGNORECASE
339
+ )
340
+ if heur_section_match:
341
+ heur_section = heur_section_match.group(2) if heur_section_match.group(2) else heur_section_match.group(1)
342
+ if heur_section:
343
+ # Guardar bloco completo
344
+ metadata['heuristics_content'] = heur_section.strip()
345
+ # Tambem extrair lista simples para compatibilidade
346
+ heuristics = re.findall(r'[├└│]\s*([^\n]+\d+[^\n]*)', heur_section)
347
+ metadata['heuristics'] = [h.strip() for h in heuristics[:10]]
348
+
349
+ #=============================
350
+ # EXTRAIR METODOLOGIAS COM CONTEUDO REAL
351
+ #=============================
352
+ # Buscar secao que comeca com ## METODOLOGIAS ou similar
353
+ meth_section_match = re.search(
354
+ r'(?:##\s*)?(?:📝\s*)?METODOLOGIAS?\s*(?:\(\d+\))?\s*\n(```\n)?(.*?)(?=\n```\s*\n---|\n---|\n##[^#]|\Z)',
355
+ batch_content, re.DOTALL | re.IGNORECASE
356
+ )
357
+ if meth_section_match:
358
+ meth_section = meth_section_match.group(2) if meth_section_match.group(2) else meth_section_match.group(1)
359
+ if meth_section:
360
+ # Verificar se pegou o bloco correto (deve conter STEP ou numeracao)
361
+ if 'STEP' in meth_section.upper() or re.search(r'\d+\.', meth_section):
362
+ # Guardar bloco completo
363
+ metadata['methodologies_content'] = meth_section.strip()
364
+ # Tambem extrair lista para compatibilidade (limpar caracteres de box)
365
+ meth_names = re.findall(r'\d+\.\s*([^\n]+)', meth_section)
366
+ metadata['methodologies'] = [
367
+ re.sub(r'[\s│]+$', '', m).strip()
368
+ for m in meth_names
369
+ ]
370
+
371
+ #=============================
372
+ # EXTRAIR FILOSOFIAS COM CONTEUDO REAL
373
+ #=============================
374
+ fil_section_match = re.search(
375
+ r'(?:##\s*)?(?:🧠\s*)?FILOSOFIAS?.*?\n(.*?)(?=\n---|\n##|\Z)',
376
+ batch_content, re.DOTALL | re.IGNORECASE
377
+ )
378
+ if fil_section_match:
379
+ metadata['filosofias_content'] = fil_section_match.group(1).strip()
380
+
381
+ #=============================
382
+ # EXTRAIR MODELOS MENTAIS COM CONTEUDO REAL
383
+ #=============================
384
+ mm_section_match = re.search(
385
+ r'(?:##\s*)?(?:🔄\s*)?MODELOS?\s*MENTAIS?.*?\n(.*?)(?=\n---|\n##|\Z)',
386
+ batch_content, re.DOTALL | re.IGNORECASE
387
+ )
388
+ if mm_section_match:
389
+ metadata['modelos_mentais_content'] = mm_section_match.group(1).strip()
390
+
391
+ return metadata
392
+
393
+
394
+ def extract_ascii_boxes(content: str, prefix: str = 'FRAMEWORK') -> Dict[str, str]:
395
+ """
396
+ Extrai blocos ASCII completos de uma secao.
397
+
398
+ Cada bloco comeca com uma linha contendo o prefixo (ex: FRAMEWORK 1: NOME)
399
+ e termina quando encontra outro bloco ou fim da secao.
400
+
401
+ Returns:
402
+ Dict com nome do bloco -> conteudo completo incluindo ASCII art
403
+ """
404
+ boxes = {}
405
+
406
+ # Estrategia: encontrar todos os headers FRAMEWORK N: e depois extrair ate o proximo
407
+ header_pattern = re.compile(
408
+ rf'{prefix}\s*(\d+)[:\s]+([^\n│]+)',
409
+ re.IGNORECASE
410
+ )
411
+
412
+ # Encontrar posicoes de todos os headers
413
+ headers = list(header_pattern.finditer(content))
414
+
415
+ for i, match in enumerate(headers):
416
+ name = match.group(2).strip()
417
+ # Limpar caracteres de box do nome
418
+ name = re.sub(r'[\s│]+$', '', name).strip()
419
+
420
+ # Encontrar inicio do box (procurar ┌ antes do header)
421
+ start_search = max(0, match.start() - 200) # Buscar ate 200 chars antes
422
+ box_start_match = None
423
+
424
+ # Procurar o ┌ mais proximo antes do header
425
+ section_before = content[start_search:match.start()]
426
+ box_starts = list(re.finditer(r'┌[─┬]+┐', section_before))
427
+ if box_starts:
428
+ # Pegar o ultimo (mais proximo do header)
429
+ box_start_match = box_starts[-1]
430
+ actual_start = start_search + box_start_match.start()
431
+ else:
432
+ actual_start = match.start()
433
+
434
+ # Encontrar fim do box
435
+ # O fim e quando encontra o proximo header ou └──...──┘ final
436
+ if i + 1 < len(headers):
437
+ # Ha proximo header - encontrar └ antes dele
438
+ next_header_pos = headers[i + 1].start()
439
+ section_between = content[match.end():next_header_pos]
440
+ # Procurar ultimo └──...──┘ antes do proximo header
441
+ box_ends = list(re.finditer(r'└[─┴]+┘', section_between))
442
+ if box_ends:
443
+ actual_end = match.end() + box_ends[-1].end()
444
+ else:
445
+ actual_end = next_header_pos
446
+ else:
447
+ # Ultimo header - ir ate fim ou proximo └
448
+ section_after = content[match.end():match.end() + 2000]
449
+ box_end_match = re.search(r'└[─┴]+┘', section_after)
450
+ if box_end_match:
451
+ actual_end = match.end() + box_end_match.end()
452
+ else:
453
+ actual_end = min(match.end() + 1000, len(content))
454
+
455
+ # Extrair bloco completo
456
+ full_box = content[actual_start:actual_end].strip()
457
+
458
+ if name and full_box:
459
+ boxes[name] = full_box
460
+
461
+ # Fallback se nao encontrou nada: tentar extrair boxes individuais
462
+ if not boxes:
463
+ box_blocks = re.findall(
464
+ r'(┌[─┬]+┐.*?└[─┴]+┘)',
465
+ content, re.DOTALL
466
+ )
467
+ for i, block in enumerate(box_blocks, 1):
468
+ header_match = re.search(rf'{prefix}\s*\d*[:\s]+([^│\n]+)', block, re.IGNORECASE)
469
+ if header_match:
470
+ name = header_match.group(1).strip()
471
+ name = re.sub(r'[\s│]+$', '', name).strip()
472
+ else:
473
+ first_line = re.search(r'│\s*([A-Z][^│\n]+)', block)
474
+ name = first_line.group(1).strip() if first_line else f"{prefix} {i}"
475
+
476
+ if name:
477
+ boxes[name] = block
478
+
479
+ return boxes
480
+
481
+
482
+ def extract_framework_content(batch_content: str, framework_name: str) -> Optional[str]:
483
+ """
484
+ Extrai o conteudo COMPLETO de um framework especifico do batch.
485
+
486
+ Busca o bloco ASCII que contem o framework e retorna todo o conteudo.
487
+
488
+ Args:
489
+ batch_content: Conteudo completo do batch
490
+ framework_name: Nome do framework a buscar
491
+
492
+ Returns:
493
+ Conteudo completo do framework incluindo ASCII box, ou None se nao encontrado
494
+ """
495
+ # Normalizar nome para busca
496
+ normalized_name = framework_name.upper().replace('-', ' ').replace('_', ' ')
497
+
498
+ # Buscar na secao de frameworks
499
+ fw_section_match = re.search(
500
+ r'(?:##\s*)?(?:🏗️\s*)?KEY\s*FRAMEWORKS?.*?\n(.*?)(?=\n---|\n##[^#]|\Z)',
501
+ batch_content, re.DOTALL | re.IGNORECASE
502
+ )
503
+
504
+ if not fw_section_match:
505
+ return None
506
+
507
+ fw_section = fw_section_match.group(1)
508
+
509
+ # Extrair todos os boxes
510
+ boxes = extract_ascii_boxes(fw_section, 'FRAMEWORK')
511
+
512
+ # Buscar o framework pelo nome
513
+ for name, content in boxes.items():
514
+ if normalized_name in name.upper().replace('-', ' ').replace('_', ' '):
515
+ return content
516
+ # Busca parcial
517
+ name_words = set(name.upper().split())
518
+ search_words = set(normalized_name.split())
519
+ if search_words & name_words: # Interseção
520
+ return content
521
+
522
+ # Fallback: buscar diretamente no conteudo
523
+ # Pattern: FRAMEWORK [N]: <nome_framework> seguido de box
524
+ direct_pattern = re.compile(
525
+ rf'(┌[─┬]+┐\s*\n\s*│[^│]*FRAMEWORK\s*\d*[:\s]+[^│]*{re.escape(framework_name)}[^└]*└[─┴]+┘)',
526
+ re.DOTALL | re.IGNORECASE
527
+ )
528
+ match = direct_pattern.search(batch_content)
529
+ if match:
530
+ return match.group(1)
531
+
532
+ return None
533
+
534
+
535
+ #=================================
536
+ # CASCADING FUNCTIONS
537
+ #=================================
538
+
539
+ def cascade_to_agents(agents: List[Dict], batch_id: str, metadata: Dict,
540
+ batch_content: str = None) -> List[Dict]:
541
+ """
542
+ Cascateia para agentes (PERSON e CARGO).
543
+
544
+ Para cada agente:
545
+ 1. Verifica se existe em /agents/
546
+ 2. Se NAO existe -> registra para criacao futura
547
+ 3. Se EXISTE -> atualiza MEMORY.md com novos elementos E CONTEUDO REAL
548
+
549
+ IMPORTANTE v2.0: Passa batch_content para extrair conteudo real.
550
+
551
+ Returns:
552
+ Lista de acoes executadas
553
+ """
554
+ actions = []
555
+
556
+ for agent in agents:
557
+ agent_name = agent['name']
558
+ frameworks = agent.get('frameworks', [])
559
+
560
+ # Mapear nome para caminho
561
+ # OBJECTION-HANDLER -> CARGO/SALES/OBJECTION-HANDLER ou similar
562
+ agent_path = find_agent_path(agent_name)
563
+
564
+ if agent_path:
565
+ # Agente existe - atualizar MEMORY.md
566
+ memory_path = agent_path / 'MEMORY.md'
567
+
568
+ if memory_path.exists():
569
+ update_result = update_agent_memory(
570
+ memory_path,
571
+ batch_id,
572
+ frameworks,
573
+ metadata,
574
+ batch_content # NOVO: passar conteudo do batch
575
+ )
576
+ actions.append({
577
+ 'action': 'update_memory',
578
+ 'agent': agent_name,
579
+ 'path': str(memory_path),
580
+ 'frameworks_added': len(frameworks),
581
+ 'content_extracted': batch_content is not None,
582
+ 'success': update_result
583
+ })
584
+ else:
585
+ # Criar MEMORY.md basico
586
+ create_result = create_agent_memory(
587
+ memory_path,
588
+ agent_name,
589
+ batch_id,
590
+ frameworks,
591
+ metadata,
592
+ batch_content # NOVO: passar conteudo do batch
593
+ )
594
+ actions.append({
595
+ 'action': 'create_memory',
596
+ 'agent': agent_name,
597
+ 'path': str(memory_path),
598
+ 'content_extracted': batch_content is not None,
599
+ 'success': create_result
600
+ })
601
+ else:
602
+ # Agente nao existe - registrar para criacao futura
603
+ actions.append({
604
+ 'action': 'agent_not_found',
605
+ 'agent': agent_name,
606
+ 'frameworks': frameworks,
607
+ 'note': 'Agent should be created in Phase 5.3'
608
+ })
609
+
610
+ log_cascading_action({
611
+ 'type': 'agent_cascade',
612
+ 'agent': agent_name,
613
+ 'batch_id': batch_id,
614
+ 'action': actions[-1]
615
+ })
616
+
617
+ return actions
618
+
619
+
620
+ def find_agent_path(agent_name: str) -> Optional[Path]:
621
+ """
622
+ Encontra o caminho de um agente pelo nome.
623
+
624
+ Busca em:
625
+ - /agents/persons/
626
+ - /agents/cargo/
627
+ - /agents/conclave/
628
+ """
629
+ # Normalizar nome
630
+ normalized = agent_name.upper().replace(' ', '-')
631
+
632
+ # Buscar em PERSONS
633
+ persons_dir = AGENTS_DIR / 'persons'
634
+ if persons_dir.exists():
635
+ for agent_dir in persons_dir.iterdir():
636
+ if agent_dir.is_dir() and normalized in agent_dir.name.upper():
637
+ return agent_dir
638
+
639
+ # Buscar em CARGO (recursivamente)
640
+ cargo_dir = AGENTS_DIR / 'cargo'
641
+ if cargo_dir.exists():
642
+ for category in cargo_dir.iterdir():
643
+ if category.is_dir():
644
+ for agent_dir in category.iterdir():
645
+ if agent_dir.is_dir() and normalized in agent_dir.name.upper():
646
+ return agent_dir
647
+
648
+ # Buscar em CONCLAVE
649
+ conclave_dir = AGENTS_DIR / 'conclave'
650
+ if conclave_dir.exists():
651
+ for agent_dir in conclave_dir.iterdir():
652
+ if agent_dir.is_dir() and normalized in agent_dir.name.upper():
653
+ return agent_dir
654
+
655
+ return None
656
+
657
+
658
+ def update_agent_memory(memory_path: Path, batch_id: str,
659
+ frameworks: List[str], metadata: Dict,
660
+ batch_content: str = None) -> bool:
661
+ """
662
+ Atualiza MEMORY.md de um agente com novos frameworks.
663
+
664
+ IMPORTANTE v2.0: Extrai CONTEUDO REAL dos frameworks, nao apenas referencias.
665
+ """
666
+ try:
667
+ content = memory_path.read_text(encoding='utf-8')
668
+
669
+ # Criar secao de atualizacao
670
+ update_section = f"""
671
+
672
+ ---
673
+
674
+ ## Atualizacao via Cascading - {batch_id}
675
+
676
+ **Data:** {datetime.now().strftime('%Y-%m-%d %H:%M')}
677
+ **Fonte:** {metadata.get('source', 'Unknown')}
678
+
679
+ ### Frameworks Adicionados
680
+
681
+ """
682
+ # NOVO v2.0: Incluir conteudo REAL dos frameworks
683
+ frameworks_content = metadata.get('frameworks_content', {})
684
+
685
+ for fw in frameworks:
686
+ # Tentar obter conteudo real do framework
687
+ fw_content = frameworks_content.get(fw)
688
+
689
+ if not fw_content and batch_content:
690
+ # Fallback: extrair diretamente do batch
691
+ fw_content = extract_framework_content(batch_content, fw)
692
+
693
+ if fw_content:
694
+ update_section += f"\n#### {fw}\n\n```\n{fw_content}\n```\n\n"
695
+ else:
696
+ # Fallback para referencia se nao conseguir extrair
697
+ update_section += f"- **{fw}** (ver `{batch_id}` para detalhes)\n"
698
+
699
+ update_section += f"""
700
+ ### Referencia
701
+
702
+ Batch: `{batch_id}`
703
+ Elementos totais: {metadata.get('elements_count', 'N/A')}
704
+ """
705
+
706
+ # Adicionar no final do arquivo
707
+ content += update_section
708
+ memory_path.write_text(content, encoding='utf-8')
709
+
710
+ return True
711
+
712
+ except Exception as e:
713
+ log_cascading_action({
714
+ 'type': 'error',
715
+ 'action': 'update_agent_memory',
716
+ 'path': str(memory_path),
717
+ 'error': str(e)
718
+ })
719
+ return False
720
+
721
+
722
+ def create_agent_memory(memory_path: Path, agent_name: str,
723
+ batch_id: str, frameworks: List[str],
724
+ metadata: Dict, batch_content: str = None) -> bool:
725
+ """
726
+ Cria MEMORY.md basico para um agente.
727
+
728
+ IMPORTANTE v2.0: Inclui CONTEUDO REAL dos frameworks, nao apenas nomes.
729
+ """
730
+ try:
731
+ memory_path.parent.mkdir(parents=True, exist_ok=True)
732
+
733
+ content = f"""# MEMORY - {agent_name}
734
+
735
+ > Memoria do agente, alimentada via cascateamento de batches.
736
+ > **VERSAO:** v2.0 - Conteudo real extraido
737
+
738
+ ---
739
+
740
+ ## Inicializacao
741
+
742
+ **Criado em:** {datetime.now().strftime('%Y-%m-%d %H:%M')}
743
+ **Fonte inicial:** {metadata.get('source', 'Unknown')}
744
+ **Batch inicial:** {batch_id}
745
+
746
+ ---
747
+
748
+ ## Conhecimento Absorvido
749
+
750
+ ### De {batch_id}
751
+
752
+ """
753
+ # NOVO v2.0: Incluir conteudo REAL dos frameworks
754
+ frameworks_content = metadata.get('frameworks_content', {})
755
+
756
+ for fw in frameworks:
757
+ # Tentar obter conteudo real do framework
758
+ fw_content = frameworks_content.get(fw)
759
+
760
+ if not fw_content and batch_content:
761
+ # Fallback: extrair diretamente do batch
762
+ fw_content = extract_framework_content(batch_content, fw)
763
+
764
+ if fw_content:
765
+ content += f"\n#### {fw}\n\n```\n{fw_content}\n```\n\n"
766
+ else:
767
+ content += f"- **{fw}**\n"
768
+
769
+ content += f"""
770
+ ---
771
+
772
+ ## Historico de Atualizacoes
773
+
774
+ | Data | Batch | Elementos |
775
+ |------|-------|-----------|
776
+ | {datetime.now().strftime('%Y-%m-%d')} | {batch_id} | {len(frameworks)} |
777
+
778
+ """
779
+
780
+ memory_path.write_text(content, encoding='utf-8')
781
+ return True
782
+
783
+ except Exception as e:
784
+ log_cascading_action({
785
+ 'type': 'error',
786
+ 'action': 'create_agent_memory',
787
+ 'path': str(memory_path),
788
+ 'error': str(e)
789
+ })
790
+ return False
791
+
792
+
793
+ def cascade_to_playbooks(playbooks: List[Dict], batch_id: str,
794
+ metadata: Dict, batch_content: str = None) -> List[Dict]:
795
+ """
796
+ Cascateia para playbooks.
797
+
798
+ Para cada playbook:
799
+ 1. Verifica se existe em /knowledge/playbooks/
800
+ 2. Se NAO existe -> cria com CONTEUDO REAL dos frameworks do batch
801
+ 3. Se EXISTE -> adiciona novos frameworks/metodologias COM CONTEUDO REAL
802
+
803
+ IMPORTANTE v2.0: Passa batch_content para extrair conteudo real.
804
+ """
805
+ actions = []
806
+
807
+ playbooks_dir = KNOWLEDGE_DIR / 'playbooks'
808
+ playbooks_dir.mkdir(parents=True, exist_ok=True)
809
+
810
+ for playbook in playbooks:
811
+ pb_name = playbook['name']
812
+ pb_desc = playbook.get('description', '')
813
+
814
+ # Normalizar nome do arquivo
815
+ pb_filename = f"{pb_name}.md"
816
+ pb_path = playbooks_dir / pb_filename
817
+
818
+ if pb_path.exists():
819
+ # Atualizar playbook existente
820
+ update_result = update_playbook(
821
+ pb_path, batch_id, pb_desc, metadata, batch_content
822
+ )
823
+ actions.append({
824
+ 'action': 'update_playbook',
825
+ 'playbook': pb_name,
826
+ 'path': str(pb_path),
827
+ 'content_extracted': batch_content is not None,
828
+ 'success': update_result
829
+ })
830
+ else:
831
+ # Criar novo playbook
832
+ create_result = create_playbook(
833
+ pb_path, pb_name, batch_id, pb_desc, metadata, batch_content
834
+ )
835
+ actions.append({
836
+ 'action': 'create_playbook',
837
+ 'playbook': pb_name,
838
+ 'path': str(pb_path),
839
+ 'content_extracted': batch_content is not None,
840
+ 'success': create_result
841
+ })
842
+
843
+ log_cascading_action({
844
+ 'type': 'playbook_cascade',
845
+ 'playbook': pb_name,
846
+ 'batch_id': batch_id,
847
+ 'action': actions[-1]
848
+ })
849
+
850
+ return actions
851
+
852
+
853
+ def update_playbook(pb_path: Path, batch_id: str,
854
+ description: str, metadata: Dict,
855
+ batch_content: str = None) -> bool:
856
+ """
857
+ Atualiza playbook existente com novos frameworks.
858
+
859
+ IMPORTANTE v2.0: Inclui CONTEUDO REAL dos frameworks.
860
+ """
861
+ try:
862
+ content = pb_path.read_text(encoding='utf-8')
863
+
864
+ # Adicionar secao de atualizacao
865
+ update_section = f"""
866
+
867
+ ---
868
+
869
+ ## Atualizacao - {batch_id}
870
+
871
+ **Data:** {datetime.now().strftime('%Y-%m-%d %H:%M')}
872
+ **Fonte:** {metadata.get('source', 'Unknown')}
873
+
874
+ ### Novos Elementos
875
+
876
+ {description if description else ''}
877
+
878
+ """
879
+ # NOVO v2.0: Incluir conteudo REAL dos frameworks
880
+ frameworks_content = metadata.get('frameworks_content', {})
881
+ frameworks = metadata.get('frameworks', [])[:5]
882
+
883
+ if frameworks_content or batch_content:
884
+ update_section += "### Frameworks Detalhados\n\n"
885
+ for fw in frameworks:
886
+ fw_content = frameworks_content.get(fw)
887
+
888
+ if not fw_content and batch_content:
889
+ fw_content = extract_framework_content(batch_content, fw)
890
+
891
+ if fw_content:
892
+ update_section += f"#### {fw}\n\n```\n{fw_content}\n```\n\n"
893
+ else:
894
+ update_section += f"- **{fw}**\n"
895
+ else:
896
+ update_section += "### Frameworks Relacionados\n\n"
897
+ for fw in frameworks:
898
+ update_section += f"- {fw}\n"
899
+
900
+ # Incluir heuristicas se disponivel
901
+ heur_content = metadata.get('heuristics_content', '')
902
+ if heur_content:
903
+ update_section += f"\n### Heuristicas\n\n```\n{heur_content}\n```\n\n"
904
+
905
+ # Incluir metodologias se disponivel
906
+ meth_content = metadata.get('methodologies_content', '')
907
+ if meth_content:
908
+ update_section += f"\n### Metodologias\n\n```\n{meth_content}\n```\n\n"
909
+
910
+ update_section += f"\n**Referencia:** `{batch_id}`\n"
911
+
912
+ content += update_section
913
+ pb_path.write_text(content, encoding='utf-8')
914
+
915
+ return True
916
+
917
+ except Exception as e:
918
+ log_cascading_action({
919
+ 'type': 'error',
920
+ 'action': 'update_playbook',
921
+ 'path': str(pb_path),
922
+ 'error': str(e)
923
+ })
924
+ return False
925
+
926
+
927
+ def create_playbook(pb_path: Path, name: str, batch_id: str,
928
+ description: str, metadata: Dict,
929
+ batch_content: str = None) -> bool:
930
+ """
931
+ Cria novo playbook.
932
+
933
+ IMPORTANTE v2.0: Inclui CONTEUDO REAL dos frameworks, heuristicas e metodologias.
934
+ """
935
+ try:
936
+ content = f"""# {name}
937
+
938
+ > Playbook gerado via cascateamento automatico.
939
+ > **Versao:** 2.0.0 (com conteudo real extraido)
940
+ > **Criado em:** {datetime.now().strftime('%Y-%m-%d')}
941
+ > **Fonte inicial:** {metadata.get('source', 'Unknown')}
942
+
943
+ ---
944
+
945
+ ## Objetivo
946
+
947
+ {description if description else 'Definir durante revisao manual.'}
948
+
949
+ ---
950
+
951
+ ## Frameworks Incluidos
952
+
953
+ """
954
+ # NOVO v2.0: Incluir conteudo REAL dos frameworks
955
+ frameworks_content = metadata.get('frameworks_content', {})
956
+
957
+ for fw in metadata.get('frameworks', []):
958
+ fw_content = frameworks_content.get(fw)
959
+
960
+ if not fw_content and batch_content:
961
+ fw_content = extract_framework_content(batch_content, fw)
962
+
963
+ if fw_content:
964
+ content += f"### {fw}\n\n```\n{fw_content}\n```\n\n"
965
+ else:
966
+ content += f"### {fw}\n\n*Detalhes em `{batch_id}`*\n\n"
967
+
968
+ content += f"""
969
+ ---
970
+
971
+ ## Heuristicas
972
+
973
+ """
974
+ # Incluir bloco de heuristicas
975
+ heur_content = metadata.get('heuristics_content', '')
976
+ if heur_content:
977
+ content += f"```\n{heur_content}\n```\n\n"
978
+ else:
979
+ for heur in metadata.get('heuristics', []):
980
+ content += f"- {heur}\n"
981
+
982
+ content += f"""
983
+ ---
984
+
985
+ ## Metodologias
986
+
987
+ """
988
+ # Incluir bloco de metodologias
989
+ meth_content = metadata.get('methodologies_content', '')
990
+ if meth_content:
991
+ content += f"```\n{meth_content}\n```\n\n"
992
+ else:
993
+ for meth in metadata.get('methodologies', []):
994
+ content += f"- {meth}\n"
995
+
996
+ # Incluir filosofias se disponivel
997
+ fil_content = metadata.get('filosofias_content', '')
998
+ if fil_content:
999
+ content += f"""
1000
+ ---
1001
+
1002
+ ## Filosofias
1003
+
1004
+ ```
1005
+ {fil_content}
1006
+ ```
1007
+
1008
+ """
1009
+
1010
+ # Incluir modelos mentais se disponivel
1011
+ mm_content = metadata.get('modelos_mentais_content', '')
1012
+ if mm_content:
1013
+ content += f"""
1014
+ ---
1015
+
1016
+ ## Modelos Mentais
1017
+
1018
+ ```
1019
+ {mm_content}
1020
+ ```
1021
+
1022
+ """
1023
+
1024
+ content += f"""
1025
+ ---
1026
+
1027
+ ## Historico
1028
+
1029
+ | Data | Batch | Acao |
1030
+ |------|-------|------|
1031
+ | {datetime.now().strftime('%Y-%m-%d')} | {batch_id} | Criacao inicial |
1032
+
1033
+ ---
1034
+
1035
+ ## Referencias
1036
+
1037
+ - Batch: `{batch_id}`
1038
+ - Fonte: {metadata.get('source', 'Unknown')}
1039
+ """
1040
+
1041
+ pb_path.write_text(content, encoding='utf-8')
1042
+ return True
1043
+
1044
+ except Exception as e:
1045
+ log_cascading_action({
1046
+ 'type': 'error',
1047
+ 'action': 'create_playbook',
1048
+ 'path': str(pb_path),
1049
+ 'error': str(e)
1050
+ })
1051
+ return False
1052
+
1053
+
1054
+ def cascade_to_dnas(dnas: List[Dict], batch_id: str, metadata: Dict) -> List[Dict]:
1055
+ """
1056
+ Cascateia para DNA-CONFIG.yaml dos agentes.
1057
+
1058
+ Atualiza contadores de elementos nas 5 camadas.
1059
+ """
1060
+ actions = []
1061
+
1062
+ for dna in dnas:
1063
+ dna_name = dna['name']
1064
+ elements_to_add = dna.get('elements_to_add', 0)
1065
+
1066
+ # Extrair nome do agente do DNA (DNA-JEREMY-HAYNES -> JEREMY-HAYNES)
1067
+ agent_name = dna_name.replace('DNA-', '')
1068
+ agent_path = find_agent_path(agent_name)
1069
+
1070
+ if agent_path:
1071
+ config_path = agent_path / 'DNA-CONFIG.yaml'
1072
+
1073
+ if config_path.exists():
1074
+ update_result = update_dna_config(
1075
+ config_path,
1076
+ batch_id,
1077
+ elements_to_add,
1078
+ metadata
1079
+ )
1080
+ actions.append({
1081
+ 'action': 'update_dna_config',
1082
+ 'dna': dna_name,
1083
+ 'path': str(config_path),
1084
+ 'elements_added': elements_to_add,
1085
+ 'success': update_result
1086
+ })
1087
+ else:
1088
+ actions.append({
1089
+ 'action': 'dna_config_not_found',
1090
+ 'dna': dna_name,
1091
+ 'expected_path': str(config_path),
1092
+ 'note': 'DNA-CONFIG.yaml should exist for this agent'
1093
+ })
1094
+ else:
1095
+ actions.append({
1096
+ 'action': 'agent_not_found',
1097
+ 'dna': dna_name,
1098
+ 'note': 'Agent for this DNA not found'
1099
+ })
1100
+
1101
+ log_cascading_action({
1102
+ 'type': 'dna_cascade',
1103
+ 'dna': dna_name,
1104
+ 'batch_id': batch_id,
1105
+ 'action': actions[-1]
1106
+ })
1107
+
1108
+ return actions
1109
+
1110
+
1111
+ def update_dna_config(config_path: Path, batch_id: str,
1112
+ elements_to_add: int, metadata: Dict) -> bool:
1113
+ """
1114
+ Atualiza DNA-CONFIG.yaml com novos elementos.
1115
+ """
1116
+ try:
1117
+ with open(config_path, 'r', encoding='utf-8') as f:
1118
+ config = yaml.safe_load(f) or {}
1119
+
1120
+ # Atualizar batches processados
1121
+ if 'batches_processed' not in config:
1122
+ config['batches_processed'] = []
1123
+ config['batches_processed'].append({
1124
+ 'batch_id': batch_id,
1125
+ 'date': datetime.now().strftime('%Y-%m-%d'),
1126
+ 'elements': elements_to_add
1127
+ })
1128
+
1129
+ # Atualizar total de elementos
1130
+ if 'total_elements' not in config:
1131
+ config['total_elements'] = 0
1132
+ config['total_elements'] += elements_to_add
1133
+
1134
+ # Atualizar timestamp
1135
+ config['last_updated'] = datetime.now().isoformat()
1136
+ config['last_batch'] = batch_id
1137
+
1138
+ with open(config_path, 'w', encoding='utf-8') as f:
1139
+ yaml.dump(config, f, default_flow_style=False, allow_unicode=True)
1140
+
1141
+ return True
1142
+
1143
+ except Exception as e:
1144
+ log_cascading_action({
1145
+ 'type': 'error',
1146
+ 'action': 'update_dna_config',
1147
+ 'path': str(config_path),
1148
+ 'error': str(e)
1149
+ })
1150
+ return False
1151
+
1152
+
1153
+ def cascade_to_dossiers(themes: List[Dict], batch_id: str,
1154
+ metadata: Dict, batch_content: str = None) -> List[Dict]:
1155
+ """
1156
+ Cascateia para theme dossiers.
1157
+
1158
+ Aplica REGRA #21: dossiers existentes devem ser ATUALIZADOS, nao ignorados.
1159
+
1160
+ IMPORTANTE v2.0: Passa batch_content para extrair conteudo real.
1161
+ """
1162
+ actions = []
1163
+
1164
+ DOSSIERS_DIR.mkdir(parents=True, exist_ok=True)
1165
+
1166
+ for theme in themes:
1167
+ theme_name = theme['name']
1168
+ dossier_name = f"DOSSIER-{theme_name}.md"
1169
+ dossier_path = DOSSIERS_DIR / dossier_name
1170
+
1171
+ if dossier_path.exists():
1172
+ # REGRA #21: Comparar versao do dossier vs batch
1173
+ update_result = update_theme_dossier(
1174
+ dossier_path, batch_id, metadata, batch_content
1175
+ )
1176
+ actions.append({
1177
+ 'action': 'update_dossier',
1178
+ 'theme': theme_name,
1179
+ 'path': str(dossier_path),
1180
+ 'content_extracted': batch_content is not None,
1181
+ 'success': update_result,
1182
+ 'rule': 'REGRA #21 applied'
1183
+ })
1184
+ else:
1185
+ # Criar novo dossier
1186
+ create_result = create_theme_dossier(
1187
+ dossier_path, theme_name, batch_id, metadata, batch_content
1188
+ )
1189
+ actions.append({
1190
+ 'action': 'create_dossier',
1191
+ 'theme': theme_name,
1192
+ 'path': str(dossier_path),
1193
+ 'content_extracted': batch_content is not None,
1194
+ 'success': create_result
1195
+ })
1196
+
1197
+ log_cascading_action({
1198
+ 'type': 'dossier_cascade',
1199
+ 'theme': theme_name,
1200
+ 'batch_id': batch_id,
1201
+ 'action': actions[-1]
1202
+ })
1203
+
1204
+ return actions
1205
+
1206
+
1207
+ def update_theme_dossier(dossier_path: Path, batch_id: str, metadata: Dict,
1208
+ batch_content: str = None) -> bool:
1209
+ """
1210
+ Atualiza theme dossier existente (REGRA #21).
1211
+
1212
+ IMPORTANTE v2.0: Inclui CONTEUDO REAL dos frameworks, heuristicas e metodologias.
1213
+ """
1214
+ try:
1215
+ content = dossier_path.read_text(encoding='utf-8')
1216
+
1217
+ # Verificar versao atual
1218
+ version_match = re.search(r'Vers[aã]o[:\s]+v?(\d+\.\d+\.?\d*)', content)
1219
+ current_version = version_match.group(1) if version_match else '1.0.0'
1220
+
1221
+ # Incrementar versao
1222
+ parts = current_version.split('.')
1223
+ if len(parts) >= 2:
1224
+ parts[1] = str(int(parts[1]) + 1)
1225
+ new_version = '.'.join(parts)
1226
+
1227
+ # Adicionar secao de atualizacao
1228
+ update_section = f"""
1229
+
1230
+ ---
1231
+
1232
+ ## Atualizacao v{new_version} - {batch_id}
1233
+
1234
+ **Data:** {datetime.now().strftime('%Y-%m-%d %H:%M')}
1235
+ **Fonte:** {metadata.get('source', 'Unknown')}
1236
+ **Regra aplicada:** REGRA #21 (Cascateamento de Theme Dossiers)
1237
+ **Versao Hook:** v2.0 (conteudo real extraido)
1238
+
1239
+ """
1240
+ # NOVO v2.0: Incluir conteudo REAL dos frameworks
1241
+ frameworks_content = metadata.get('frameworks_content', {})
1242
+ frameworks = metadata.get('frameworks', [])[:5]
1243
+
1244
+ if frameworks_content:
1245
+ update_section += "### Frameworks Detalhados\n\n"
1246
+ for fw in frameworks:
1247
+ fw_content = frameworks_content.get(fw)
1248
+ if not fw_content and batch_content:
1249
+ fw_content = extract_framework_content(batch_content, fw)
1250
+ if fw_content:
1251
+ update_section += f"#### {fw}\n\n```\n{fw_content}\n```\n\n"
1252
+ else:
1253
+ update_section += f"- **{fw}**\n"
1254
+ else:
1255
+ update_section += "### Novos Frameworks\n\n"
1256
+ for fw in frameworks:
1257
+ update_section += f"- {fw}\n"
1258
+
1259
+ # Incluir bloco de heuristicas
1260
+ heur_content = metadata.get('heuristics_content', '')
1261
+ if heur_content:
1262
+ update_section += f"\n### Heuristicas\n\n```\n{heur_content}\n```\n\n"
1263
+ else:
1264
+ heuristics = metadata.get('heuristics', [])[:5]
1265
+ if heuristics:
1266
+ update_section += "\n### Novas Heuristicas\n\n"
1267
+ for heur in heuristics:
1268
+ update_section += f"- {heur}\n"
1269
+
1270
+ # Incluir metodologias
1271
+ meth_content = metadata.get('methodologies_content', '')
1272
+ if meth_content:
1273
+ update_section += f"\n### Metodologias\n\n```\n{meth_content}\n```\n\n"
1274
+
1275
+ update_section += f"""
1276
+ ### Referencia
1277
+
1278
+ - Batch: `{batch_id}`
1279
+ - Elementos: {metadata.get('elements_count', 'N/A')}
1280
+ """
1281
+
1282
+ # Atualizar versao no header
1283
+ content = re.sub(
1284
+ r'(Vers[aã]o[:\s]+v?)(\d+\.\d+\.?\d*)',
1285
+ f'\\g<1>{new_version}',
1286
+ content
1287
+ )
1288
+
1289
+ content += update_section
1290
+ dossier_path.write_text(content, encoding='utf-8')
1291
+
1292
+ return True
1293
+
1294
+ except Exception as e:
1295
+ log_cascading_action({
1296
+ 'type': 'error',
1297
+ 'action': 'update_theme_dossier',
1298
+ 'path': str(dossier_path),
1299
+ 'error': str(e)
1300
+ })
1301
+ return False
1302
+
1303
+
1304
+ def create_theme_dossier(dossier_path: Path, theme_name: str,
1305
+ batch_id: str, metadata: Dict,
1306
+ batch_content: str = None) -> bool:
1307
+ """
1308
+ Cria novo theme dossier.
1309
+
1310
+ IMPORTANTE v2.0: Inclui CONTEUDO REAL dos frameworks, heuristicas e metodologias.
1311
+ """
1312
+ try:
1313
+ content = f"""# DOSSIER - {theme_name}
1314
+
1315
+ > Dossier tematico gerado via cascateamento automatico.
1316
+ > **Versao Hook:** v2.0 (conteudo real extraido)
1317
+
1318
+ ---
1319
+
1320
+ ## Metadata
1321
+
1322
+ - **Versao:** v2.0.0
1323
+ - **Criado em:** {datetime.now().strftime('%Y-%m-%d')}
1324
+ - **Fonte inicial:** {metadata.get('source', 'Unknown')}
1325
+ - **Batch inicial:** {batch_id}
1326
+
1327
+ ---
1328
+
1329
+ ## Visao Geral
1330
+
1331
+ Este dossier consolida conhecimento sobre **{theme_name.replace('-', ' ').title()}**.
1332
+
1333
+ ---
1334
+
1335
+ ## Frameworks
1336
+
1337
+ """
1338
+ # NOVO v2.0: Incluir conteudo REAL dos frameworks
1339
+ frameworks_content = metadata.get('frameworks_content', {})
1340
+
1341
+ for fw in metadata.get('frameworks', []):
1342
+ fw_content = frameworks_content.get(fw)
1343
+ if not fw_content and batch_content:
1344
+ fw_content = extract_framework_content(batch_content, fw)
1345
+
1346
+ if fw_content:
1347
+ content += f"### {fw}\n\n```\n{fw_content}\n```\n\n"
1348
+ else:
1349
+ content += f"### {fw}\n\n*Fonte: {batch_id}*\n\n"
1350
+
1351
+ content += f"""
1352
+ ---
1353
+
1354
+ ## Heuristicas
1355
+
1356
+ """
1357
+ # Incluir bloco completo de heuristicas
1358
+ heur_content = metadata.get('heuristics_content', '')
1359
+ if heur_content:
1360
+ content += f"```\n{heur_content}\n```\n\n"
1361
+ else:
1362
+ for heur in metadata.get('heuristics', []):
1363
+ content += f"- {heur}\n"
1364
+
1365
+ content += f"""
1366
+ ---
1367
+
1368
+ ## Metodologias
1369
+
1370
+ """
1371
+ # Incluir bloco completo de metodologias
1372
+ meth_content = metadata.get('methodologies_content', '')
1373
+ if meth_content:
1374
+ content += f"```\n{meth_content}\n```\n\n"
1375
+ else:
1376
+ for meth in metadata.get('methodologies', []):
1377
+ content += f"- {meth}\n"
1378
+
1379
+ # Incluir filosofias se disponivel
1380
+ fil_content = metadata.get('filosofias_content', '')
1381
+ if fil_content:
1382
+ content += f"""
1383
+ ---
1384
+
1385
+ ## Filosofias
1386
+
1387
+ ```
1388
+ {fil_content}
1389
+ ```
1390
+
1391
+ """
1392
+
1393
+ # Incluir modelos mentais se disponivel
1394
+ mm_content = metadata.get('modelos_mentais_content', '')
1395
+ if mm_content:
1396
+ content += f"""
1397
+ ---
1398
+
1399
+ ## Modelos Mentais
1400
+
1401
+ ```
1402
+ {mm_content}
1403
+ ```
1404
+
1405
+ """
1406
+
1407
+ content += f"""
1408
+ ---
1409
+
1410
+ ## Fontes
1411
+
1412
+ | Fonte | Batch | Data |
1413
+ |-------|-------|------|
1414
+ | {metadata.get('source', 'Unknown')} | {batch_id} | {datetime.now().strftime('%Y-%m-%d')} |
1415
+
1416
+ ---
1417
+
1418
+ ## Cross-References
1419
+
1420
+ *Conexoes com outros temas serao adicionadas em atualizacoes futuras.*
1421
+ """
1422
+
1423
+ dossier_path.write_text(content, encoding='utf-8')
1424
+ return True
1425
+
1426
+ except Exception as e:
1427
+ log_cascading_action({
1428
+ 'type': 'error',
1429
+ 'action': 'create_theme_dossier',
1430
+ 'path': str(dossier_path),
1431
+ 'error': str(e)
1432
+ })
1433
+ return False
1434
+
1435
+
1436
+ #=================================
1437
+ # BATCH UPDATE
1438
+ #=================================
1439
+
1440
+ def mark_cascading_complete(batch_path: str, cascaded_items: Dict) -> bool:
1441
+ """
1442
+ Adiciona secao 'Cascateamento Executado' ao batch.
1443
+ """
1444
+ try:
1445
+ batch_file = Path(batch_path)
1446
+ content = batch_file.read_text(encoding='utf-8')
1447
+
1448
+ # Verificar se ja tem secao de cascateamento
1449
+ if 'Cascateamento Executado' in content:
1450
+ return True # Ja executado
1451
+
1452
+ # Criar secao de cascateamento
1453
+ cascade_section = f"""
1454
+
1455
+ ---
1456
+
1457
+ ## Cascateamento Executado
1458
+
1459
+ **Data:** {datetime.now().strftime('%Y-%m-%d %H:%M')}
1460
+ **Regra aplicada:** REGRA #22 (Cascateamento Multi-Destino)
1461
+
1462
+ ### Resumo
1463
+
1464
+ | Tipo | Quantidade | Sucesso |
1465
+ |------|------------|---------|
1466
+ | Agentes | {len(cascaded_items.get('agents', []))} | {sum(1 for a in cascaded_items.get('agents', []) if a.get('success', False) or 'update' in a.get('action', ''))} |
1467
+ | Playbooks | {len(cascaded_items.get('playbooks', []))} | {sum(1 for p in cascaded_items.get('playbooks', []) if p.get('success', False))} |
1468
+ | DNAs | {len(cascaded_items.get('dnas', []))} | {sum(1 for d in cascaded_items.get('dnas', []) if d.get('success', False))} |
1469
+ | Dossiers | {len(cascaded_items.get('dossiers', []))} | {sum(1 for d in cascaded_items.get('dossiers', []) if d.get('success', False))} |
1470
+
1471
+ ### Detalhes
1472
+
1473
+ """
1474
+
1475
+ # Filtrar apenas chaves de cascateamento
1476
+ cascade_keys = ['agents', 'playbooks', 'dnas', 'dossiers']
1477
+ for action_type in cascade_keys:
1478
+ actions = cascaded_items.get(action_type, [])
1479
+ if actions and isinstance(actions, list):
1480
+ cascade_section += f"**{action_type.upper()}:**\n"
1481
+ for action in actions:
1482
+ if isinstance(action, dict):
1483
+ status = "OK" if action.get('success', False) else action.get('action', 'pending')
1484
+ name = action.get('agent') or action.get('playbook') or action.get('dna') or action.get('theme', 'unknown')
1485
+ cascade_section += f"- [{status}] {name}\n"
1486
+ cascade_section += "\n"
1487
+
1488
+ cascade_section += f"""
1489
+ ---
1490
+
1491
+ *Cascateamento automatico via `post_batch_cascading.py`*
1492
+ """
1493
+
1494
+ content += cascade_section
1495
+ batch_file.write_text(content, encoding='utf-8')
1496
+
1497
+ return True
1498
+
1499
+ except Exception as e:
1500
+ log_cascading_action({
1501
+ 'type': 'error',
1502
+ 'action': 'mark_cascading_complete',
1503
+ 'path': batch_path,
1504
+ 'error': str(e)
1505
+ })
1506
+ return False
1507
+
1508
+
1509
+ #=================================
1510
+ # MAIN ENTRY POINT
1511
+ #=================================
1512
+
1513
+ def process_batch(batch_path: str) -> Dict:
1514
+ """
1515
+ Processa um batch e executa cascateamento completo.
1516
+
1517
+ IMPORTANTE v2.0: Passa batch_content para extrair CONTEUDO REAL dos frameworks.
1518
+
1519
+ Returns:
1520
+ Dicionario com resultados do cascateamento
1521
+ """
1522
+ result = {
1523
+ 'batch_path': batch_path,
1524
+ 'success': False,
1525
+ 'version': '2.0.0', # NOVO: versao do hook
1526
+ 'content_extraction': True, # NOVO: indica que extrai conteudo real
1527
+ 'agents': [],
1528
+ 'playbooks': [],
1529
+ 'dnas': [],
1530
+ 'dossiers': [],
1531
+ 'errors': []
1532
+ }
1533
+
1534
+ try:
1535
+ # Ler conteudo do batch
1536
+ batch_file = Path(batch_path)
1537
+ if not batch_file.exists():
1538
+ result['errors'].append(f"Batch file not found: {batch_path}")
1539
+ return result
1540
+
1541
+ batch_content = batch_file.read_text(encoding='utf-8')
1542
+
1543
+ # Extrair metadados (agora inclui conteudo real dos frameworks)
1544
+ metadata = extract_batch_metadata(batch_content)
1545
+ batch_id = metadata.get('batch_id', batch_file.stem)
1546
+
1547
+ log_cascading_action({
1548
+ 'type': 'batch_cascade_start',
1549
+ 'batch_id': batch_id,
1550
+ 'batch_path': batch_path,
1551
+ 'version': '2.0.0',
1552
+ 'frameworks_extracted': len(metadata.get('frameworks_content', {}))
1553
+ })
1554
+
1555
+ # Extrair destinos
1556
+ destinations = extract_destinations(batch_content)
1557
+
1558
+ # Executar cascateamento para cada tipo
1559
+ # NOVO v2.0: Passa batch_content para extrair conteudo real
1560
+ if destinations['agents']:
1561
+ result['agents'] = cascade_to_agents(
1562
+ destinations['agents'],
1563
+ batch_id,
1564
+ metadata,
1565
+ batch_content # NOVO
1566
+ )
1567
+
1568
+ if destinations['playbooks']:
1569
+ result['playbooks'] = cascade_to_playbooks(
1570
+ destinations['playbooks'],
1571
+ batch_id,
1572
+ metadata,
1573
+ batch_content # NOVO
1574
+ )
1575
+
1576
+ if destinations['dnas']:
1577
+ result['dnas'] = cascade_to_dnas(
1578
+ destinations['dnas'],
1579
+ batch_id,
1580
+ metadata
1581
+ )
1582
+
1583
+ if destinations['dossiers']:
1584
+ result['dossiers'] = cascade_to_dossiers(
1585
+ destinations['dossiers'],
1586
+ batch_id,
1587
+ metadata,
1588
+ batch_content # NOVO v2.0
1589
+ )
1590
+
1591
+ #=========================
1592
+ # REGRA #26: VALIDAÇÃO DE INTEGRIDADE DO CASCATEAMENTO
1593
+ # Só marca como completo se validação passar
1594
+ #=========================
1595
+ try:
1596
+ import sys
1597
+ scripts_path = str(Path(PROJECT_DIR) / 'scripts')
1598
+ if scripts_path not in sys.path:
1599
+ sys.path.insert(0, scripts_path)
1600
+ from validate_cascading_integrity import validate_batch_integrity
1601
+
1602
+ validation = validate_batch_integrity(batch_id)
1603
+ result['validation'] = {
1604
+ 'status': validation['status'],
1605
+ 'destinations_total': validation.get('destinations_total', 0),
1606
+ 'destinations_exist': validation.get('destinations_exist', 0),
1607
+ 'reference_count': validation.get('reference_count', 0)
1608
+ }
1609
+
1610
+ if validation['status'] == 'FAILED':
1611
+ result['errors'].append(
1612
+ f"REGRA #26 Validation failed: {validation.get('error', 'Unknown')}"
1613
+ )
1614
+ log_cascading_action({
1615
+ 'type': 'validation_failed',
1616
+ 'batch_id': batch_id,
1617
+ 'validation': validation
1618
+ })
1619
+ # Não marca como completo, retorna com erro
1620
+ return result
1621
+
1622
+ log_cascading_action({
1623
+ 'type': 'validation_passed',
1624
+ 'batch_id': batch_id,
1625
+ 'status': validation['status']
1626
+ })
1627
+
1628
+ except ImportError as e:
1629
+ # Script não disponível - log warning mas continua
1630
+ log_cascading_action({
1631
+ 'type': 'validation_warning',
1632
+ 'batch_id': batch_id,
1633
+ 'warning': f"Validation script not available: {e}"
1634
+ })
1635
+ except Exception as e:
1636
+ # Erro na validação - log warning mas continua (não bloqueia)
1637
+ log_cascading_action({
1638
+ 'type': 'validation_error',
1639
+ 'batch_id': batch_id,
1640
+ 'error': str(e)
1641
+ })
1642
+
1643
+ # Marcar cascateamento como completo no batch
1644
+ mark_cascading_complete(batch_path, result)
1645
+
1646
+ result['success'] = True
1647
+ log_batch_result(batch_id, result)
1648
+
1649
+ except Exception as e:
1650
+ result['errors'].append(str(e))
1651
+ log_cascading_action({
1652
+ 'type': 'error',
1653
+ 'action': 'process_batch',
1654
+ 'path': batch_path,
1655
+ 'error': str(e)
1656
+ })
1657
+
1658
+ return result
1659
+
1660
+
1661
+ def main(batch_path: str = None):
1662
+ """
1663
+ Entry point do hook.
1664
+
1665
+ Pode ser chamado de duas formas:
1666
+ 1. Como hook: recebe input via stdin
1667
+ 2. Diretamente: recebe batch_path como argumento
1668
+ """
1669
+ import sys
1670
+
1671
+ if batch_path:
1672
+ # Chamada direta com path
1673
+ result = process_batch(batch_path)
1674
+ print(json.dumps(result, indent=2, ensure_ascii=False))
1675
+ return result
1676
+
1677
+ # Chamada como hook - ler stdin
1678
+ try:
1679
+ input_data = sys.stdin.read()
1680
+ hook_input = json.loads(input_data) if input_data else {}
1681
+
1682
+ # Extrair path do batch do input
1683
+ batch_path = hook_input.get('batch_path')
1684
+
1685
+ if not batch_path:
1686
+ # Tentar extrair de tool_input
1687
+ tool_input = hook_input.get('tool_input', {})
1688
+ batch_path = tool_input.get('file_path', '')
1689
+
1690
+ # Verificar se e um arquivo de batch
1691
+ if 'BATCH' not in batch_path.upper():
1692
+ output = {
1693
+ 'continue': True,
1694
+ 'feedback': None,
1695
+ 'note': 'Not a batch file, skipping cascading'
1696
+ }
1697
+ print(json.dumps(output))
1698
+ return
1699
+
1700
+ # Processar batch
1701
+ result = process_batch(batch_path)
1702
+
1703
+ # Preparar output do hook
1704
+ feedback = None
1705
+ if result['success']:
1706
+ total_cascaded = (
1707
+ len(result['agents']) +
1708
+ len(result['playbooks']) +
1709
+ len(result['dnas']) +
1710
+ len(result['dossiers'])
1711
+ )
1712
+ if total_cascaded > 0:
1713
+ feedback = f"[JARVIS] REGRA #22: Cascateamento executado - {total_cascaded} destinos processados"
1714
+ else:
1715
+ if result['errors']:
1716
+ feedback = f"[JARVIS] REGRA #22: Erro no cascateamento - {result['errors'][0]}"
1717
+
1718
+ output = {
1719
+ 'continue': True,
1720
+ 'feedback': feedback,
1721
+ 'result': result
1722
+ }
1723
+
1724
+ print(json.dumps(output))
1725
+
1726
+ except Exception as e:
1727
+ error_output = {
1728
+ 'continue': True,
1729
+ 'feedback': f"[JARVIS] Erro no hook de cascateamento: {str(e)}",
1730
+ 'error': str(e)
1731
+ }
1732
+ print(json.dumps(error_output))
1733
+
1734
+
1735
+ if __name__ == "__main__":
1736
+ import sys
1737
+ if len(sys.argv) > 1:
1738
+ main(sys.argv[1])
1739
+ else:
1740
+ main()