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,855 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ ROLE DETECTOR - Intelligence Layer v2.0
4
+ ========================================
5
+ Deteccao agnostica de cargos/funcoes em 3 niveis:
6
+ 1. DIRETA (peso 1.0) - nome do cargo aparece no texto
7
+ 2. INFERIDA (peso 0.7) - atividade descrita implica um cargo
8
+ 3. EMERGENTE (peso 0.5) - padroes genericos detectam role desconhecido
9
+
10
+ Mudancas vs v1.0:
11
+ - Vocabulario carregado de _ROLE_PATTERNS.yaml (nao hardcoded)
12
+ - Inferencia implicita via ACTIVITY_TO_ROLE_MAP
13
+ - Deteccao de roles emergentes (agnostico a qualquer dominio)
14
+ - Integracao com entity_normalizer para escrita no registry
15
+ - mention_breakdown (direct/inferred/emergent) + weighted_score
16
+
17
+ Versao: 2.0.0
18
+ Data: 2026-02-25
19
+ """
20
+
21
+ import json
22
+ import re
23
+ import sys
24
+ import yaml
25
+ from pathlib import Path
26
+ from datetime import datetime, timezone
27
+ from collections import defaultdict
28
+
29
+ sys.path.insert(0, str(Path(__file__).parent))
30
+ from entity_normalizer import (
31
+ load_registry, save_registry, normalize_entity, load_taxonomy
32
+ )
33
+
34
+ # ---------------------------------------------------------------------------
35
+ # PATHS
36
+ # ---------------------------------------------------------------------------
37
+ BASE_DIR = Path(__file__).parent.parent
38
+ ROLE_PATTERNS_PATH = BASE_DIR / "scripts" / "_ROLE_PATTERNS.yaml"
39
+ TAXONOMY_PATH = BASE_DIR / "knowledge" / "dna" / "DOMAINS-TAXONOMY.yaml"
40
+ TRIGGER_CONFIG_PATH = BASE_DIR / "scripts" / "trigger_config.yaml"
41
+ TRIGGERS_LOG_PATH = BASE_DIR / "logs" / "triggers.jsonl"
42
+
43
+ # ---------------------------------------------------------------------------
44
+ # DETECTION WEIGHTS (configuravel)
45
+ # ---------------------------------------------------------------------------
46
+ WEIGHT_DIRECT = 1.0
47
+ WEIGHT_STRONG = 2.0
48
+ WEIGHT_INFERRED = 0.7
49
+ WEIGHT_EMERGENT = 0.5
50
+
51
+ # Max items in detection_history per role
52
+ MAX_DETECTION_HISTORY = 20
53
+
54
+
55
+ # ---------------------------------------------------------------------------
56
+ # DYNAMIC VOCABULARY LOADER
57
+ # ---------------------------------------------------------------------------
58
+ _patterns_cache = None
59
+ _inference_cache = None
60
+ _emergence_cache = None
61
+
62
+
63
+ def _load_role_patterns():
64
+ """Load role patterns from _ROLE_PATTERNS.yaml (cached)."""
65
+ global _patterns_cache, _inference_cache, _emergence_cache
66
+ if _patterns_cache is not None:
67
+ return _patterns_cache, _inference_cache, _emergence_cache
68
+
69
+ if not ROLE_PATTERNS_PATH.exists():
70
+ _patterns_cache = {}
71
+ _inference_cache = {}
72
+ _emergence_cache = {"patterns": [], "stopwords": set()}
73
+ return _patterns_cache, _inference_cache, _emergence_cache
74
+
75
+ with open(ROLE_PATTERNS_PATH, "r", encoding="utf-8") as f:
76
+ raw = yaml.safe_load(f)
77
+
78
+ # Separate role patterns from special sections
79
+ role_patterns = {}
80
+ inference_map = raw.pop("_inference_map", {})
81
+ emergence_patterns = raw.pop("_emergence_patterns", [])
82
+ emergence_stopwords = set(raw.pop("_emergence_stopwords", []))
83
+
84
+ for key, val in raw.items():
85
+ if key.startswith("_") or not isinstance(val, dict):
86
+ continue
87
+ role_patterns[key] = val
88
+
89
+ _patterns_cache = role_patterns
90
+ _inference_cache = inference_map
91
+ _emergence_cache = {
92
+ "patterns": emergence_patterns,
93
+ "stopwords": emergence_stopwords,
94
+ }
95
+ return _patterns_cache, _inference_cache, _emergence_cache
96
+
97
+
98
+ def load_role_vocabulary():
99
+ """
100
+ Build complete role vocabulary from YAML sources.
101
+ Merges _ROLE_PATTERNS.yaml (patterns) with DOMAINS-TAXONOMY.yaml (domains).
102
+ """
103
+ role_patterns, _, _ = _load_role_patterns()
104
+ tax = load_taxonomy()
105
+ taxonomy_cargos = tax.get("cargos", {})
106
+
107
+ vocab = {}
108
+ # All roles from patterns file
109
+ for role_id, pdata in role_patterns.items():
110
+ cargo_data = taxonomy_cargos.get(role_id, {})
111
+ vocab[role_id] = {
112
+ "patterns": pdata.get("patterns", []),
113
+ "strong_patterns": pdata.get("strong_patterns", []),
114
+ "exclude_patterns": pdata.get("exclude_patterns", []),
115
+ "domains": (
116
+ cargo_data.get("dominios_primarios", []) +
117
+ cargo_data.get("dominios_secundarios", [])
118
+ ),
119
+ }
120
+
121
+ # Roles in taxonomy without patterns (basic detection by name)
122
+ for cargo_id, cargo_data in taxonomy_cargos.items():
123
+ if cargo_id not in vocab:
124
+ nice_name = cargo_id.lower().replace("-", " ")
125
+ vocab[cargo_id] = {
126
+ "patterns": [rf"\b{re.escape(nice_name)}\b"],
127
+ "strong_patterns": [],
128
+ "exclude_patterns": [],
129
+ "domains": (
130
+ cargo_data.get("dominios_primarios", []) +
131
+ cargo_data.get("dominios_secundarios", [])
132
+ ),
133
+ }
134
+
135
+ return vocab
136
+
137
+
138
+ # ---------------------------------------------------------------------------
139
+ # LEVEL 1: DIRECT DETECTION (peso 1.0 / 2.0)
140
+ # ---------------------------------------------------------------------------
141
+ def _detect_known_roles(text, role_vocab):
142
+ """
143
+ Detect roles by matching known patterns in text.
144
+ Returns list of {name, type, weight, match, context}.
145
+ """
146
+ text_lower = text.lower()
147
+ detections = []
148
+
149
+ for role_canonical, vocab in role_vocab.items():
150
+ role_matches = []
151
+
152
+ # Check exclude patterns first
153
+ excluded = False
154
+ for exc_pattern in vocab.get("exclude_patterns", []):
155
+ try:
156
+ if re.search(exc_pattern, text_lower):
157
+ excluded = True
158
+ break
159
+ except re.error:
160
+ continue
161
+ if excluded:
162
+ continue
163
+
164
+ # Strong patterns (weight: 2x)
165
+ for pattern in vocab.get("strong_patterns", []):
166
+ try:
167
+ matches = list(re.finditer(pattern, text_lower))
168
+ except re.error:
169
+ continue
170
+ for m in matches:
171
+ context = _extract_context(text, m.start(), m.end())
172
+ role_matches.append({
173
+ "sub_type": "strong",
174
+ "weight": WEIGHT_STRONG,
175
+ "match": m.group(),
176
+ "context": context,
177
+ })
178
+
179
+ # Normal patterns (weight: 1x)
180
+ for pattern in vocab.get("patterns", []):
181
+ try:
182
+ matches = list(re.finditer(pattern, text_lower))
183
+ except re.error:
184
+ continue
185
+ for m in matches:
186
+ already = any(
187
+ d["match"] in m.group() or m.group() in d["match"]
188
+ for d in role_matches
189
+ )
190
+ if already:
191
+ continue
192
+ context = _extract_context(text, m.start(), m.end())
193
+ role_matches.append({
194
+ "sub_type": "normal",
195
+ "weight": WEIGHT_DIRECT,
196
+ "match": m.group(),
197
+ "context": context,
198
+ })
199
+
200
+ if role_matches:
201
+ total_weight = sum(d["weight"] for d in role_matches)
202
+ detections.append({
203
+ "name": role_canonical,
204
+ "type": "direct",
205
+ "weight": total_weight,
206
+ "raw_matches": len(role_matches),
207
+ "contexts": [d["context"] for d in role_matches[:3]],
208
+ })
209
+
210
+ return detections
211
+
212
+
213
+ # ---------------------------------------------------------------------------
214
+ # LEVEL 2: INFERRED DETECTION (peso 0.7)
215
+ # ---------------------------------------------------------------------------
216
+ def _infer_roles_from_context(text):
217
+ """
218
+ Detect roles implied by activities described in text.
219
+ E.g. "writing the sales page copy" → COPYWRITER
220
+ Returns list of {name, type, weight, match, context}.
221
+ """
222
+ _, inference_map, _ = _load_role_patterns()
223
+ if not inference_map:
224
+ return []
225
+
226
+ text_lower = text.lower()
227
+ detections = []
228
+ seen_roles = set()
229
+
230
+ for role_canonical, patterns in inference_map.items():
231
+ for pattern in patterns:
232
+ try:
233
+ matches = list(re.finditer(pattern, text_lower))
234
+ except re.error:
235
+ continue
236
+ for m in matches:
237
+ if role_canonical not in seen_roles:
238
+ context = _extract_context(text, m.start(), m.end())
239
+ detections.append({
240
+ "name": role_canonical,
241
+ "type": "inferred",
242
+ "weight": WEIGHT_INFERRED,
243
+ "activity": m.group(),
244
+ "contexts": [context],
245
+ })
246
+ seen_roles.add(role_canonical)
247
+
248
+ return detections
249
+
250
+
251
+ # ---------------------------------------------------------------------------
252
+ # LEVEL 3: EMERGENT DETECTION (peso 0.5)
253
+ # ---------------------------------------------------------------------------
254
+ def _detect_emergent_roles(text, known_roles):
255
+ """
256
+ Detect roles NOT in the vocabulary using generic patterns.
257
+ E.g. "our data scientist handles analytics" → DATA-SCIENTIST (emergent)
258
+ Returns list of {name, type, weight, raw, context}.
259
+ """
260
+ _, _, emergence_data = _load_role_patterns()
261
+ if not emergence_data.get("patterns"):
262
+ return []
263
+
264
+ text_lower = text.lower()
265
+ stopwords = emergence_data.get("stopwords", set())
266
+ detections = []
267
+ seen = set()
268
+
269
+ # Common trailing words that regex greedily captures but aren't role names
270
+ trailing_noise = {
271
+ "for", "is", "are", "was", "were", "in", "on", "at", "to", "of",
272
+ "and", "or", "the", "a", "an", "who", "that", "this", "with",
273
+ "all", "por", "para", "que", "com", "do", "da", "dos", "das",
274
+ "no", "na", "nos", "nas", "de", "em", "um", "uma",
275
+ }
276
+
277
+ # Common English words that are NOT role names (broad filter for single-word matches)
278
+ # Emergent detection is aggressive by design; this filter prevents noise.
279
+ _common_non_roles = {
280
+ # Verbs
281
+ "have", "has", "had", "get", "got", "make", "made", "take", "took",
282
+ "give", "gave", "want", "need", "know", "think", "say", "said",
283
+ "go", "went", "come", "came", "see", "saw", "find", "found",
284
+ "put", "set", "run", "ran", "let", "keep", "kept", "call",
285
+ "try", "tried", "start", "stop", "pay", "paid", "build", "built",
286
+ "close", "open", "send", "sent", "sell", "sold", "buy", "bought",
287
+ "train", "hire", "fire", "qualify", "scale", "grow", "grew",
288
+ "approach", "handle", "manage", "lead", "drive", "drove",
289
+ # Adjectives / Adverbs
290
+ "good", "bad", "best", "worst", "better", "worse", "right", "wrong",
291
+ "big", "small", "long", "short", "high", "low", "fast", "slow",
292
+ "exact", "same", "different", "many", "much", "more", "most",
293
+ "less", "least", "only", "just", "really", "very", "even",
294
+ "enough", "sure", "every", "whole", "entire", "real", "true",
295
+ "top", "bottom", "front", "back", "full", "early", "late",
296
+ # Nouns (generic, not roles)
297
+ "time", "year", "month", "week", "day", "hour", "number", "money",
298
+ "way", "thing", "point", "fact", "case", "place", "reason",
299
+ "result", "end", "problem", "question", "answer", "example",
300
+ "level", "type", "kind", "sort", "step", "stage", "process",
301
+ "system", "model", "method", "plan", "goal", "value", "cost",
302
+ "price", "rate", "deal", "offer", "call", "meeting", "event",
303
+ "launch", "growth", "revenue", "profit", "loss", "margin",
304
+ "lead", "leads", "pipeline", "funnel", "script", "pitch",
305
+ "objection", "closing", "follow-up", "outreach", "campaign",
306
+ "setting", "inbound", "outbound",
307
+ # Pronouns / Determiners
308
+ "you", "they", "them", "we", "us", "he", "she", "him", "her",
309
+ "its", "my", "your", "his", "their", "our", "who", "what",
310
+ # Compound noise
311
+ "exact-same", "best-possible", "get-your", "train-your",
312
+ "the-launch", "mortgage-leads",
313
+ }
314
+
315
+ for pattern in emergence_data["patterns"]:
316
+ try:
317
+ matches = re.findall(pattern, text_lower)
318
+ except re.error:
319
+ continue
320
+ for match in matches:
321
+ raw = match.strip()
322
+ # Strip leading and trailing noise words (greedy regex artifact)
323
+ words = raw.split()
324
+ while words and words[-1] in trailing_noise:
325
+ words.pop()
326
+ while words and words[0] in trailing_noise:
327
+ words.pop(0)
328
+ raw = " ".join(words)
329
+
330
+ # Filter noise
331
+ if not raw or len(raw) < 3 or len(raw) > 40:
332
+ continue
333
+ # Check stopwords
334
+ words = raw.split()
335
+ if all(w in stopwords for w in words):
336
+ continue
337
+ if any(w in stopwords for w in words) and len(words) <= 1:
338
+ continue
339
+
340
+ # Single-word filter: must look like a plausible role name
341
+ if len(words) == 1:
342
+ word = words[0]
343
+ if word in _common_non_roles:
344
+ continue
345
+ # Very short single words are almost never roles
346
+ if len(word) < 5:
347
+ continue
348
+
349
+ # Multi-word filter: all words being common is noise
350
+ if len(words) >= 2 and all(w in _common_non_roles for w in words):
351
+ continue
352
+
353
+ # Multi-word with pronoun/article pattern (e.g. "if-your", "get-your")
354
+ if len(words) >= 2 and any(w in trailing_noise or w in stopwords for w in words):
355
+ # At least one meaningful word must remain
356
+ meaningful = [w for w in words if w not in trailing_noise and w not in stopwords and w not in _common_non_roles]
357
+ if not meaningful:
358
+ continue
359
+
360
+ normalized = raw.upper().replace(" ", "-")
361
+ # Skip if already a known role
362
+ if normalized in known_roles:
363
+ continue
364
+ if normalized in seen:
365
+ continue
366
+ seen.add(normalized)
367
+
368
+ detections.append({
369
+ "name": normalized,
370
+ "type": "emergent",
371
+ "weight": WEIGHT_EMERGENT,
372
+ "raw": raw,
373
+ "contexts": [_extract_context(text, 0, min(100, len(text)))],
374
+ })
375
+
376
+ return detections
377
+
378
+
379
+ # ---------------------------------------------------------------------------
380
+ # CORE: DETECT ROLES IN TEXT (v2.0)
381
+ # ---------------------------------------------------------------------------
382
+ def detect_roles_in_text(text, source_id=None, registry=None):
383
+ """
384
+ Detect roles/positions mentioned in text using 3-level detection.
385
+
386
+ Args:
387
+ text: raw text to analyze
388
+ source_id: source identifier for tracking
389
+ registry: ENTITY-REGISTRY dict
390
+
391
+ Returns:
392
+ {
393
+ "roles_detected": [{role, detection_type, weight, contexts}],
394
+ "new_roles": [{role, detection_type}],
395
+ "triggers_activated": [{role, trigger_type, details}]
396
+ }
397
+ """
398
+ if registry is None:
399
+ registry = load_registry()
400
+
401
+ role_vocab = load_role_vocabulary()
402
+
403
+ # Level 1: Direct detection (peso 1.0/2.0)
404
+ direct_roles = _detect_known_roles(text, role_vocab)
405
+
406
+ # Level 2: Inferred detection (peso 0.7)
407
+ inferred_roles = _infer_roles_from_context(text)
408
+
409
+ # Level 3: Emergent detection (peso 0.5)
410
+ emergent_roles = _detect_emergent_roles(text, set(role_vocab.keys()))
411
+
412
+ # Merge all detections
413
+ all_detections = []
414
+ roles_section = registry.setdefault("roles", {})
415
+
416
+ for det in direct_roles + inferred_roles + emergent_roles:
417
+ role_name = det["name"]
418
+
419
+ # Ensure role exists in registry (via entity_normalizer for known,
420
+ # direct creation for emergent)
421
+ if role_name not in roles_section:
422
+ if det["type"] == "emergent":
423
+ # Create emergent candidate directly
424
+ roles_section[role_name] = _create_role_entry(
425
+ role_name, source_id, status="emergent_candidate"
426
+ )
427
+ else:
428
+ # Use normalize_entity for known roles (taxonomy lookup)
429
+ result = normalize_entity(
430
+ role_name, "role", registry=registry,
431
+ source_id=source_id, auto_save=False
432
+ )
433
+ role_name = result["canonical"]
434
+
435
+ # Update mention_breakdown and weighted_score
436
+ role_data = roles_section.get(role_name)
437
+ if role_data:
438
+ _update_role_detection(role_data, det, source_id)
439
+
440
+ all_detections.append({
441
+ "role": role_name,
442
+ "detection_type": det["type"],
443
+ "weight": det["weight"],
444
+ "contexts": det.get("contexts", []),
445
+ })
446
+
447
+ # Check triggers for all detected roles
448
+ triggers = []
449
+ for det in all_detections:
450
+ trigger = _check_role_trigger(det["role"], registry)
451
+ if trigger:
452
+ triggers.append(trigger)
453
+
454
+ # new_roles = emergent-only (roles not previously in vocabulary)
455
+ new = [d for d in all_detections if d["detection_type"] == "emergent"]
456
+
457
+ return {
458
+ "roles_detected": all_detections,
459
+ "new_roles": new,
460
+ "triggers_activated": triggers,
461
+ }
462
+
463
+
464
+ def _create_role_entry(role_name, source_id=None, status="tracking"):
465
+ """Create a new role entry with v2.0 fields."""
466
+ now = datetime.now(timezone.utc).isoformat()
467
+ return {
468
+ "canonical": role_name,
469
+ "aliases": [],
470
+ "mention_count": 0,
471
+ "mention_breakdown": {"direct": 0, "inferred": 0, "emergent": 0},
472
+ "weighted_score": 0.0,
473
+ "sources": [source_id] if source_id else [],
474
+ "has_agent": False,
475
+ "domain_ids": [],
476
+ "responsibilities": [],
477
+ "status": status,
478
+ "detection_history": [],
479
+ "created_at": now,
480
+ "last_seen": now,
481
+ }
482
+
483
+
484
+ def _update_role_detection(role_data, detection, source_id):
485
+ """Update a role's mention data with a new detection."""
486
+ det_type = detection["type"]
487
+ weight = detection["weight"]
488
+
489
+ # Ensure v2.0 fields exist (backward compat)
490
+ if "mention_breakdown" not in role_data:
491
+ old_count = role_data.get("mention_count", 0)
492
+ role_data["mention_breakdown"] = {
493
+ "direct": old_count, "inferred": 0, "emergent": 0
494
+ }
495
+ if "weighted_score" not in role_data:
496
+ role_data["weighted_score"] = float(role_data.get("mention_count", 0))
497
+ if "detection_history" not in role_data:
498
+ role_data["detection_history"] = []
499
+
500
+ # Increment breakdown
501
+ breakdown = role_data["mention_breakdown"]
502
+ breakdown[det_type] = breakdown.get(det_type, 0) + 1
503
+
504
+ # Update total mention_count
505
+ role_data["mention_count"] = (
506
+ breakdown.get("direct", 0) +
507
+ breakdown.get("inferred", 0) +
508
+ breakdown.get("emergent", 0)
509
+ )
510
+
511
+ # Recalculate weighted_score
512
+ role_data["weighted_score"] = (
513
+ breakdown.get("direct", 0) * WEIGHT_DIRECT +
514
+ breakdown.get("inferred", 0) * WEIGHT_INFERRED +
515
+ breakdown.get("emergent", 0) * WEIGHT_EMERGENT
516
+ )
517
+
518
+ # Add source
519
+ if source_id:
520
+ sources = role_data.setdefault("sources", [])
521
+ if source_id not in sources:
522
+ sources.append(source_id)
523
+
524
+ # Update detection_history (capped)
525
+ history = role_data.setdefault("detection_history", [])
526
+ history_entry = {
527
+ "type": det_type,
528
+ "weight": weight,
529
+ "timestamp": datetime.now(timezone.utc).isoformat(),
530
+ }
531
+ if source_id:
532
+ history_entry["source"] = source_id
533
+ if det_type == "inferred" and "activity" in detection:
534
+ history_entry["activity"] = detection["activity"][:100]
535
+ if det_type == "emergent" and "raw" in detection:
536
+ history_entry["raw"] = detection["raw"][:60]
537
+ if detection.get("contexts"):
538
+ history_entry["context"] = detection["contexts"][0][:120]
539
+
540
+ history.append(history_entry)
541
+ # Keep only last N entries
542
+ if len(history) > MAX_DETECTION_HISTORY:
543
+ role_data["detection_history"] = history[-MAX_DETECTION_HISTORY:]
544
+
545
+ # Update last_seen
546
+ role_data["last_seen"] = datetime.now(timezone.utc).isoformat()
547
+
548
+ # Status lifecycle: emergent_candidate → tracking → active
549
+ _update_role_status(role_data)
550
+
551
+
552
+ def _update_role_status(role_data):
553
+ """Update role status based on weighted_score and sources."""
554
+ ws = role_data.get("weighted_score", 0)
555
+ n_sources = len(role_data.get("sources", []))
556
+ current = role_data.get("status", "tracking")
557
+
558
+ # Don't downgrade from active
559
+ if current == "active":
560
+ return
561
+
562
+ if ws >= 10 and n_sources >= 2:
563
+ role_data["status"] = "active"
564
+ elif ws >= 5 and n_sources >= 1:
565
+ role_data["status"] = "tracking"
566
+ elif ws >= 3:
567
+ if current == "emergent_candidate":
568
+ role_data["status"] = "tracking"
569
+ # else keep current status
570
+
571
+
572
+ # ---------------------------------------------------------------------------
573
+ # FILE-LEVEL DETECTION
574
+ # ---------------------------------------------------------------------------
575
+ def detect_roles_in_chunk(chunk_data, source_id=None, registry=None):
576
+ """Detect roles in a chunk, handling all chunk formats."""
577
+ text = ""
578
+ if "content" in chunk_data:
579
+ text = chunk_data["content"]
580
+ elif "texto" in chunk_data:
581
+ text = chunk_data["texto"]
582
+ elif "text" in chunk_data:
583
+ text = chunk_data["text"]
584
+
585
+ if not text:
586
+ return {"roles_detected": [], "new_roles": [], "triggers_activated": []}
587
+
588
+ return detect_roles_in_text(text, source_id=source_id, registry=registry)
589
+
590
+
591
+ def detect_roles_in_file(filepath, registry=None, save=True):
592
+ """
593
+ Detect roles across all chunks in a file.
594
+ Returns aggregated results.
595
+ """
596
+ if registry is None:
597
+ registry = load_registry()
598
+
599
+ filepath = Path(filepath)
600
+ with open(filepath, "r", encoding="utf-8") as f:
601
+ data = json.load(f)
602
+
603
+ source_id = data.get("source_id", data.get("source_hash", filepath.stem))
604
+
605
+ if "chunks" in data:
606
+ chunks = data["chunks"]
607
+ else:
608
+ chunks = [data]
609
+
610
+ all_detections = defaultdict(lambda: {"direct": 0, "inferred": 0, "emergent": 0})
611
+ all_triggers = []
612
+ all_new_roles = []
613
+
614
+ for chunk in chunks:
615
+ result = detect_roles_in_chunk(chunk, source_id=source_id, registry=registry)
616
+ for det in result["roles_detected"]:
617
+ all_detections[det["role"]][det["detection_type"]] += 1
618
+ for det in result["new_roles"]:
619
+ all_detections[det["role"]][det["detection_type"]] += 1
620
+ all_new_roles.append(det)
621
+ all_triggers.extend(result["triggers_activated"])
622
+
623
+ if save:
624
+ save_registry(registry)
625
+
626
+ # Deduplicate triggers
627
+ seen_triggers = set()
628
+ unique_triggers = []
629
+ for t in all_triggers:
630
+ key = (t["role"], t["trigger_type"])
631
+ if key not in seen_triggers:
632
+ seen_triggers.add(key)
633
+ unique_triggers.append(t)
634
+
635
+ # Build summary
636
+ role_summary = []
637
+ for role, breakdown in sorted(all_detections.items(),
638
+ key=lambda x: sum(x[1].values()), reverse=True):
639
+ total = sum(breakdown.values())
640
+ role_summary.append({
641
+ "role": role,
642
+ "total_mentions": total,
643
+ "breakdown": dict(breakdown),
644
+ })
645
+
646
+ return {
647
+ "source_id": source_id,
648
+ "roles_detected": role_summary,
649
+ "new_roles": all_new_roles,
650
+ "triggers_activated": unique_triggers,
651
+ "chunk_count": len(chunks),
652
+ }
653
+
654
+
655
+ # ---------------------------------------------------------------------------
656
+ # SCAN ALL CHUNKS
657
+ # ---------------------------------------------------------------------------
658
+ def scan_all_chunks(registry=None, save=True):
659
+ """Scan ALL chunk files for role mentions."""
660
+ if registry is None:
661
+ registry = load_registry()
662
+
663
+ chunks_dir = BASE_DIR / "processing" / "chunks"
664
+ all_detections = defaultdict(lambda: {"direct": 0, "inferred": 0, "emergent": 0})
665
+ all_triggers = []
666
+ all_new_roles = []
667
+ files_scanned = 0
668
+
669
+ for fpath in sorted(chunks_dir.glob("*.json")):
670
+ if fpath.name in ("CHUNKS-STATE.json", "_INDEX.json", "_rag_export.json"):
671
+ continue
672
+
673
+ result = detect_roles_in_file(fpath, registry=registry, save=False)
674
+ files_scanned += 1
675
+
676
+ for det in result["roles_detected"]:
677
+ for dtype, count in det.get("breakdown", {}).items():
678
+ all_detections[det["role"]][dtype] += count
679
+ for det in result.get("new_roles", []):
680
+ all_new_roles.append(det)
681
+ all_triggers.extend(result["triggers_activated"])
682
+
683
+ if save:
684
+ save_registry(registry)
685
+
686
+ # Deduplicate triggers
687
+ seen = set()
688
+ unique_triggers = []
689
+ for t in all_triggers:
690
+ key = (t["role"], t["trigger_type"])
691
+ if key not in seen:
692
+ seen.add(key)
693
+ unique_triggers.append(t)
694
+
695
+ # Build sorted summary
696
+ summary = []
697
+ for role, breakdown in sorted(all_detections.items(),
698
+ key=lambda x: sum(x[1].values()), reverse=True):
699
+ total = sum(breakdown.values())
700
+ ws = (breakdown.get("direct", 0) * WEIGHT_DIRECT +
701
+ breakdown.get("inferred", 0) * WEIGHT_INFERRED +
702
+ breakdown.get("emergent", 0) * WEIGHT_EMERGENT)
703
+ summary.append({
704
+ "role": role,
705
+ "total_mentions": total,
706
+ "weighted_score": round(ws, 1),
707
+ "breakdown": dict(breakdown),
708
+ })
709
+
710
+ return {
711
+ "files_scanned": files_scanned,
712
+ "roles_detected": summary,
713
+ "new_roles": all_new_roles,
714
+ "triggers_activated": unique_triggers,
715
+ }
716
+
717
+
718
+ # ---------------------------------------------------------------------------
719
+ # HELPERS
720
+ # ---------------------------------------------------------------------------
721
+ def _extract_context(text, start, end, window=80):
722
+ """Extract surrounding context around a match."""
723
+ ctx_start = max(0, start - window)
724
+ ctx_end = min(len(text), end + window)
725
+ context = text[ctx_start:ctx_end].strip()
726
+ if ctx_start > 0:
727
+ context = "..." + context
728
+ if ctx_end < len(text):
729
+ context = context + "..."
730
+ return context
731
+
732
+
733
+ def _check_role_trigger(role_canonical, registry):
734
+ """Check if a role has crossed the threshold for agent creation (tiered)."""
735
+ if TRIGGER_CONFIG_PATH.exists():
736
+ with open(TRIGGER_CONFIG_PATH, "r", encoding="utf-8") as f:
737
+ config = yaml.safe_load(f)
738
+ else:
739
+ return None
740
+
741
+ cargo_thresholds = config.get("thresholds", {}).get("agent_creation_cargo", {})
742
+
743
+ role_data = registry.get("roles", {}).get(role_canonical, {})
744
+ weighted_score = role_data.get("weighted_score", role_data.get("mention_count", 0))
745
+ source_count = len(role_data.get("sources", []))
746
+ has_agent = role_data.get("has_agent", False)
747
+
748
+ if has_agent:
749
+ return None
750
+
751
+ # Check tiered thresholds
752
+ tier = None
753
+
754
+ # Tier 1: Established
755
+ est = cargo_thresholds.get("established", {})
756
+ if est:
757
+ min_ws = est.get("min_weighted_score", cargo_thresholds.get("min_mentions", 10))
758
+ min_src = est.get("min_sources", cargo_thresholds.get("min_sources", 2))
759
+ if weighted_score >= min_ws and source_count >= min_src:
760
+ tier = "established"
761
+
762
+ # Tier 2: Emerging (only if not established)
763
+ if tier is None:
764
+ emg = cargo_thresholds.get("emerging", {})
765
+ if emg:
766
+ min_ws = emg.get("min_weighted_score", 5)
767
+ min_src = emg.get("min_sources", 1)
768
+ if weighted_score >= min_ws and source_count >= min_src:
769
+ tier = "emerging"
770
+ # Check promotion rules
771
+ promo = emg.get("promotion_rules", {})
772
+ if promo:
773
+ promo_ws = promo.get("min_weighted_score", 15)
774
+ promo_src = promo.get("min_sources", 2)
775
+ if weighted_score >= promo_ws and source_count >= promo_src:
776
+ tier = "established"
777
+
778
+ if tier == "established":
779
+ trigger = {
780
+ "role": role_canonical,
781
+ "trigger_type": "create_agent",
782
+ "tier": "established",
783
+ "weighted_score": weighted_score,
784
+ "source_count": source_count,
785
+ "timestamp": datetime.now(timezone.utc).isoformat(),
786
+ }
787
+ _log_trigger(trigger)
788
+ return trigger
789
+
790
+ return None
791
+
792
+
793
+ def _log_trigger(trigger):
794
+ """Log trigger activation to triggers.jsonl."""
795
+ TRIGGERS_LOG_PATH.parent.mkdir(parents=True, exist_ok=True)
796
+ with open(TRIGGERS_LOG_PATH, "a", encoding="utf-8") as f:
797
+ f.write(json.dumps(trigger, ensure_ascii=False) + "\n")
798
+
799
+
800
+ # ---------------------------------------------------------------------------
801
+ # CLI
802
+ # ---------------------------------------------------------------------------
803
+ def main():
804
+ if len(sys.argv) > 1 and sys.argv[1] == "--all":
805
+ print("\n=== ROLE DETECTOR v2.0: Full Scan ===\n")
806
+ result = scan_all_chunks(save=True)
807
+ print(f"Files scanned: {result['files_scanned']}")
808
+
809
+ print(f"\n--- Roles Detected ({len(result['roles_detected'])}) ---")
810
+ print(f"{'Role':<30} {'Total':>6} {'WScore':>7} {'Direct':>7} {'Infer':>7} {'Emerg':>7}")
811
+ print("-" * 74)
812
+ for det in result["roles_detected"]:
813
+ bd = det.get("breakdown", {})
814
+ print(f" {det['role']:<28} {det['total_mentions']:>6} "
815
+ f"{det['weighted_score']:>7.1f} "
816
+ f"{bd.get('direct', 0):>7} {bd.get('inferred', 0):>7} "
817
+ f"{bd.get('emergent', 0):>7}")
818
+
819
+ if result.get("new_roles"):
820
+ unique_new = set(d["role"] for d in result["new_roles"])
821
+ print(f"\n--- EMERGENT ROLES ({len(unique_new)}) ---")
822
+ for role in sorted(unique_new):
823
+ print(f" [NEW] {role}")
824
+
825
+ if result["triggers_activated"]:
826
+ print(f"\n--- TRIGGERS ACTIVATED ({len(result['triggers_activated'])}) ---")
827
+ for t in result["triggers_activated"]:
828
+ print(f" [!] {t['role']}: {t['trigger_type']} "
829
+ f"(ws={t.get('weighted_score', '?')}, "
830
+ f"tier={t.get('tier', '?')}, "
831
+ f"sources={t.get('source_count', '?')})")
832
+ else:
833
+ print(f"\nNo new triggers activated.")
834
+
835
+ elif len(sys.argv) > 1 and sys.argv[1] == "--text":
836
+ text = " ".join(sys.argv[2:])
837
+ result = detect_roles_in_text(text)
838
+ print(json.dumps(result, indent=2, ensure_ascii=False, default=str))
839
+
840
+ elif len(sys.argv) > 1:
841
+ filepath = sys.argv[1]
842
+ print(f"\n=== ROLE DETECTOR v2.0: {filepath} ===\n")
843
+ result = detect_roles_in_file(filepath)
844
+ print(json.dumps(result, indent=2, ensure_ascii=False, default=str))
845
+
846
+ else:
847
+ print("Uso:")
848
+ print(" python3 role_detector.py --all # Scan all chunk files")
849
+ print(" python3 role_detector.py <filepath> # Scan single file")
850
+ print(" python3 role_detector.py --text 'o closer deve...' # Test text")
851
+ sys.exit(1)
852
+
853
+
854
+ if __name__ == "__main__":
855
+ main()