mega-brain-ai 1.1.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.

Potentially problematic release.


This version of mega-brain-ai might be problematic. Click here for more details.

Files changed (308) hide show
  1. package/.claude/CLAUDE.md +155 -0
  2. package/.claude/commands/agents.md +161 -0
  3. package/.claude/commands/ask.md +117 -0
  4. package/.claude/commands/benchmark.md +224 -0
  5. package/.claude/commands/chat.md +343 -0
  6. package/.claude/commands/compare.md +116 -0
  7. package/.claude/commands/conclave.md +194 -0
  8. package/.claude/commands/config.md +133 -0
  9. package/.claude/commands/council.md +194 -0
  10. package/.claude/commands/create-agent.md +452 -0
  11. package/.claude/commands/debate.md +157 -0
  12. package/.claude/commands/documentation/create-architecture-documentation.md +175 -0
  13. package/.claude/commands/dossiers.md +180 -0
  14. package/.claude/commands/evolve.md +223 -0
  15. package/.claude/commands/extract-dna.md +170 -0
  16. package/.claude/commands/extract-knowledge.md +507 -0
  17. package/.claude/commands/inbox.md +296 -0
  18. package/.claude/commands/ingest-empresa.md +191 -0
  19. package/.claude/commands/ingest.md +182 -0
  20. package/.claude/commands/jarvis-briefing.md +67 -0
  21. package/.claude/commands/jarvis-control.md +169 -0
  22. package/.claude/commands/jarvis-full.md +181 -0
  23. package/.claude/commands/jarvis.md +212 -0
  24. package/.claude/commands/ler-drive.md +212 -0
  25. package/.claude/commands/log.md +158 -0
  26. package/.claude/commands/loop.md +133 -0
  27. package/.claude/commands/loops.md +73 -0
  28. package/.claude/commands/mission-autopilot.md +538 -0
  29. package/.claude/commands/mission.md +353 -0
  30. package/.claude/commands/process-inbox.md +148 -0
  31. package/.claude/commands/process-jarvis.md +3036 -0
  32. package/.claude/commands/process-video.md +131 -0
  33. package/.claude/commands/rag-search.md +78 -0
  34. package/.claude/commands/resume.md +33 -0
  35. package/.claude/commands/save.md +38 -0
  36. package/.claude/commands/scan-inbox.md +125 -0
  37. package/.claude/commands/setup.md +99 -0
  38. package/.claude/commands/system-digest.md +243 -0
  39. package/.claude/commands/verify.md +182 -0
  40. package/.claude/commands/view-dna.md +169 -0
  41. package/.claude/hooks/agent_doctor.py +433 -0
  42. package/.claude/hooks/agent_memory_persister.py +203 -0
  43. package/.claude/hooks/auto_formatter.py +158 -0
  44. package/.claude/hooks/checkpoint_writer.py +244 -0
  45. package/.claude/hooks/claude_md_guard.py +146 -0
  46. package/.claude/hooks/creation_validator.py +357 -0
  47. package/.claude/hooks/enforce_dual_location.py +501 -0
  48. package/.claude/hooks/enforce_plan_mode.py +220 -0
  49. package/.claude/hooks/inbox_age_alert.py +367 -0
  50. package/.claude/hooks/jarvis_briefing.py +506 -0
  51. package/.claude/hooks/ledger_updater.py +301 -0
  52. package/.claude/hooks/memory_hints_injector.py +251 -0
  53. package/.claude/hooks/memory_updater.py +202 -0
  54. package/.claude/hooks/multi_agent_hook.py +464 -0
  55. package/.claude/hooks/notification_system.py +120 -0
  56. package/.claude/hooks/pattern_analyzer.py +526 -0
  57. package/.claude/hooks/pending_tracker.py +188 -0
  58. package/.claude/hooks/post_batch_cascading.py +1740 -0
  59. package/.claude/hooks/post_output_validator.py +358 -0
  60. package/.claude/hooks/post_tool_use.py +120 -0
  61. package/.claude/hooks/post_write_validator.py +200 -0
  62. package/.claude/hooks/quality_watchdog.py +394 -0
  63. package/.claude/hooks/ralph_wiggum.py +277 -0
  64. package/.claude/hooks/session-source-sync.py +218 -0
  65. package/.claude/hooks/session_autosave_v2.py +1135 -0
  66. package/.claude/hooks/session_end.py +203 -0
  67. package/.claude/hooks/session_start.py +939 -0
  68. package/.claude/hooks/skill_indexer.py +48 -0
  69. package/.claude/hooks/skill_router.py +358 -0
  70. package/.claude/hooks/stop_hook_completeness.py +178 -0
  71. package/.claude/hooks/subagent_tracker.py +163 -0
  72. package/.claude/hooks/token_checkpoint.py +584 -0
  73. package/.claude/hooks/user_prompt_submit.py +125 -0
  74. package/.claude/rules/ANTHROPIC-STANDARDS.md +384 -0
  75. package/.claude/rules/CLAUDE-LITE.md +201 -0
  76. package/.claude/rules/RULE-GROUP-1.md +320 -0
  77. package/.claude/rules/RULE-GROUP-2.md +307 -0
  78. package/.claude/rules/RULE-GROUP-3.md +248 -0
  79. package/.claude/rules/RULE-GROUP-4.md +427 -0
  80. package/.claude/rules/RULE-GROUP-5.md +388 -0
  81. package/.claude/rules/RULE-GROUP-6.md +387 -0
  82. package/.claude/rules/logging.md +53 -0
  83. package/.claude/rules/mcp-governance.md +128 -0
  84. package/.claude/rules/pipeline.md +60 -0
  85. package/.claude/rules/state-management.md +93 -0
  86. package/.claude/scripts/apply-tags.py +77 -0
  87. package/.claude/scripts/batch-extract-transcriptions.py +132 -0
  88. package/.claude/scripts/build-complete-index.py +250 -0
  89. package/.claude/scripts/build-planilha-index.py +170 -0
  90. package/.claude/scripts/complete-tag-matching.py +250 -0
  91. package/.claude/scripts/deduplicate-inbox.py +139 -0
  92. package/.claude/scripts/docx-xml-extractor.py +141 -0
  93. package/.claude/scripts/extract-docx-text.py +58 -0
  94. package/.claude/scripts/extract-single-transcription.py +74 -0
  95. package/.claude/scripts/extract_docx_from_gdrive.py +77 -0
  96. package/.claude/scripts/organized-downloader.py +246 -0
  97. package/.claude/scripts/planilha-tagger.py +187 -0
  98. package/.claude/scripts/revert-tags.py +70 -0
  99. package/.claude/scripts/source-sync.py +265 -0
  100. package/.claude/scripts/tag-inbox-files.py +276 -0
  101. package/.claude/scripts/tag-inbox-v2.py +253 -0
  102. package/.claude/scripts/test-extraction.py +35 -0
  103. package/.claude/scripts/test-full-extraction.py +74 -0
  104. package/.claude/skills/00-SKILL-CREATOR/SKILL.md +186 -0
  105. package/.claude/skills/01-SKILL-DOCS-MEGABRAIN/SKILL.md +251 -0
  106. package/.claude/skills/02-SKILL-PYTHON-MEGABRAIN/SKILL.md +323 -0
  107. package/.claude/skills/03-SKILL-AGENT-CREATION/SKILL.md +374 -0
  108. package/.claude/skills/04-SKILL-KNOWLEDGE-EXTRACTION/SKILL.md +318 -0
  109. package/.claude/skills/05-SKILL-PIPELINE-JARVIS/SKILL.md +430 -0
  110. package/.claude/skills/06-SKILL-BRAINSTORMING/SKILL.md +72 -0
  111. package/.claude/skills/07-SKILL-DISPATCHING-PARALLEL-AGENTS/SKILL.md +193 -0
  112. package/.claude/skills/08-SKILL-EXECUTING-PLANS/SKILL.md +114 -0
  113. package/.claude/skills/09-SKILL-WRITING-PLANS/SKILL.md +184 -0
  114. package/.claude/skills/10-SKILL-VERIFICATION-BEFORE-COMPLETION/SKILL.md +130 -0
  115. package/.claude/skills/11-SKILL-USING-SUPERPOWERS/SKILL.md +105 -0
  116. package/.claude/skills/DETECTION-PROTOCOL.md +217 -0
  117. package/.claude/skills/README.md +240 -0
  118. package/.claude/skills/SKILL-REGISTRY.md +284 -0
  119. package/.claude/skills/SKILL-SUGGESTIONS.md +114 -0
  120. package/.claude/skills/_TEMPLATES/SKILL-WRITER-GUIDE.md +385 -0
  121. package/.claude/skills/chronicler/SKILL.md +146 -0
  122. package/.claude/skills/chronicler/chronicler_core.py +468 -0
  123. package/.claude/skills/code-review/SKILL.md +160 -0
  124. package/.claude/skills/council/SKILL.md +210 -0
  125. package/.claude/skills/executor/SKILL.md +161 -0
  126. package/.claude/skills/fase-2-5-tagging/SKILL.md +182 -0
  127. package/.claude/skills/feature-dev/SKILL.md +154 -0
  128. package/.claude/skills/finance-agent/SKILL.md +137 -0
  129. package/.claude/skills/frontend-design/SKILL.md +165 -0
  130. package/.claude/skills/gdrive-transcription-downloader/SKILL.md +249 -0
  131. package/.claude/skills/gemini-fallback/SKILL.md +67 -0
  132. package/.claude/skills/gemini-fallback/gemini_fetch.py +0 -0
  133. package/.claude/skills/gha/SKILL.md +96 -0
  134. package/.claude/skills/gha/gha_diagnostic.py +227 -0
  135. package/.claude/skills/github-workflow/SKILL.md +190 -0
  136. package/.claude/skills/hookify/SKILL.md +134 -0
  137. package/.claude/skills/hybrid-source-reading/SKILL.md +265 -0
  138. package/.claude/skills/jarvis/SKILL.md +546 -0
  139. package/.claude/skills/jarvis-briefing/SKILL.md +340 -0
  140. package/.claude/skills/ler-planilha/SKILL.md +281 -0
  141. package/.claude/skills/plugin-dev/SKILL.md +176 -0
  142. package/.claude/skills/pr-review-toolkit/SKILL.md +178 -0
  143. package/.claude/skills/resume/SKILL.md +61 -0
  144. package/.claude/skills/save/SKILL.md +87 -0
  145. package/.claude/skills/skill-writer/SKILL.md +153 -0
  146. package/.claude/skills/skill-writer/examples.md +191 -0
  147. package/.claude/skills/skill-writer/troubleshooting.md +205 -0
  148. package/.claude/skills/smart-download-tagger/SKILL.md +148 -0
  149. package/.claude/skills/source-sync/SKILL.md +240 -0
  150. package/.claude/skills/sync-docs/SKILL.md +193 -0
  151. package/.claude/skills/sync-docs/config.json +37 -0
  152. package/.claude/skills/sync-docs/gdrive_sync.py +358 -0
  153. package/.claude/skills/sync-docs/reauth.py +71 -0
  154. package/.claude/skills/talent-agent/SKILL.md +183 -0
  155. package/.claude/skills/verify/SKILL.md +154 -0
  156. package/.claude/skills/verify/verify_runner.py +0 -0
  157. package/.claude/skills/verify-6-levels/SKILL.md +234 -0
  158. package/.claude/templates/BATCH-LOG-TEMPLATE.md +221 -0
  159. package/.claudeignore +9 -0
  160. package/.gitattributes +4 -0
  161. package/.github/layer1-allowlist.txt +80 -0
  162. package/.github/layer2-manifest.txt +40 -0
  163. package/.gitignore +219 -0
  164. package/README.md +1210 -0
  165. package/agents/_templates/INDEX.md +741 -0
  166. package/agents/_templates/TEMPLATE-AGENT-MD-ULTRA-ROBUSTO-V3.md +2399 -0
  167. package/agents/boardroom/CHECKLIST-MASTER.md +281 -0
  168. package/agents/boardroom/INTEGRATION-GUIDE.md +406 -0
  169. package/agents/boardroom/README.md +238 -0
  170. package/agents/boardroom/config/BOARDROOM-CONFIG.md +186 -0
  171. package/agents/boardroom/config/TTS-INTEGRATION.md +258 -0
  172. package/agents/boardroom/config/VOICE-PROFILES.md +624 -0
  173. package/agents/boardroom/config/voice_mapping.json +128 -0
  174. package/agents/boardroom/scripts/audio_generator.py +375 -0
  175. package/agents/boardroom/scripts/audio_generator_edge.py +353 -0
  176. package/agents/boardroom/scripts/jarvis_boardroom_hook.py +415 -0
  177. package/agents/boardroom/scripts/notebooklm_generator.py +578 -0
  178. package/agents/boardroom/templates/EPISODE-TEMPLATE.md +367 -0
  179. package/agents/boardroom/templates/scene-templates/SCENE-AGENT-DEBATE.md +252 -0
  180. package/agents/boardroom/templates/scene-templates/SCENE-COUNCIL.md +270 -0
  181. package/agents/boardroom/templates/scene-templates/SCENE-DNA-CONSULTATION.md +126 -0
  182. package/agents/boardroom/templates/scene-templates/SCENE-QUESTION.md +174 -0
  183. package/agents/boardroom/workflows/WORKFLOW-AUDIO-GENERATION.md +421 -0
  184. package/agents/constitution/BASE-CONSTITUTION.md +254 -0
  185. package/agents/council/CRITIC.md +197 -0
  186. package/agents/council/DEVILS-ADVOCATE.md +274 -0
  187. package/agents/council/SYNTHESIZER.md +293 -0
  188. package/agents/council/advogado-do-diabo/AGENT.md +489 -0
  189. package/agents/council/advogado-do-diabo/SOUL.md +100 -0
  190. package/agents/council/critico-metodologico/AGENT.md +670 -0
  191. package/agents/council/critico-metodologico/SOUL.md +107 -0
  192. package/agents/council/sintetizador/AGENT.md +558 -0
  193. package/agents/council/sintetizador/SOUL.md +94 -0
  194. package/agents/persons/_example/AGENT-EXAMPLE.md +42 -0
  195. package/agents/persons/_example/DNA-EXAMPLE.yaml +61 -0
  196. package/agents/protocols/AGENT-COGNITION-PROTOCOL.md +779 -0
  197. package/agents/protocols/AGENT-INTEGRITY-PROTOCOL.md +692 -0
  198. package/agents/protocols/BATCH-VISUAL-PROTOCOL.md +841 -0
  199. package/agents/protocols/DNA-CONFIG-TEMPLATE.yaml +181 -0
  200. package/agents/protocols/DNA-EXTRACTION-PROTOCOL.md +370 -0
  201. package/agents/protocols/EPISTEMIC-PROTOCOL.md +333 -0
  202. package/agents/protocols/LOG-STRUCTURE-PROTOCOL.md +65 -0
  203. package/agents/protocols/MEMORY-PROTOCOL.md +567 -0
  204. package/agents/protocols/NARRATIVE-SYNTHESIS-PROTOCOL.md +278 -0
  205. package/agents/protocols/PHASE-4-VERIFICATION-CHECKPOINT.md +146 -0
  206. package/agents/protocols/SOUL-TEMPLATE.md +416 -0
  207. package/agents/protocols/TEMPLATE-EVOLUTION-PROTOCOL.md +544 -0
  208. package/agents/protocols/VISUAL-DIFF-PROTOCOL.md +159 -0
  209. package/agents/sua-empresa/README.md +44 -0
  210. package/agents/sua-empresa/_example/jds/EXAMPLE-JD.md +42 -0
  211. package/agents/sua-empresa/_example/org/EXAMPLE-ORG.md +32 -0
  212. package/agents/sua-empresa/_example/roles/EXAMPLE-ROLE.md +38 -0
  213. package/bin/cli.js +2 -0
  214. package/bin/lib/ascii-art.js +234 -0
  215. package/bin/lib/installer.js +402 -0
  216. package/bin/lib/setup-wizard.js +95 -0
  217. package/bin/lib/validate-email.js +109 -0
  218. package/bin/mega-brain.js +97 -0
  219. package/bin/push.js +342 -0
  220. package/bin/templates/env.example +38 -0
  221. package/inbox/.gitkeep +0 -0
  222. package/integrations/README.md +46 -0
  223. package/integrations/mcps/MCP-REGISTRY.md +56 -0
  224. package/integrations/mcps/excalidraw/CONFIG.md +56 -0
  225. package/integrations/mcps/gdrive/CONFIG.md +38 -0
  226. package/knowledge/dna/.gitkeep +0 -0
  227. package/knowledge/dossiers/persons/.gitkeep +0 -0
  228. package/knowledge/dossiers/persons/DOSSIER-EXAMPLE.md +49 -0
  229. package/knowledge/dossiers/system/.gitkeep +0 -0
  230. package/knowledge/dossiers/themes/.gitkeep +0 -0
  231. package/knowledge/playbooks/.gitkeep +0 -0
  232. package/knowledge/playbooks/PLAYBOOK-EXAMPLE.md +50 -0
  233. package/knowledge/sources/.gitkeep +0 -0
  234. package/logs/.gitkeep +0 -0
  235. package/package.json +128 -0
  236. package/processing/canonical/.gitkeep +0 -0
  237. package/processing/chunks/.gitkeep +0 -0
  238. package/processing/insights/.gitkeep +0 -0
  239. package/processing/narratives/.gitkeep +0 -0
  240. package/reference/CONSELHO.md +337 -0
  241. package/reference/CONTEXT7_README.md +28 -0
  242. package/reference/JARVIS-LOGGING-PROTOCOL.md +380 -0
  243. package/reference/QUICK-START.md +197 -0
  244. package/reference/README-RALPH-CASCATEAMENTO.md +207 -0
  245. package/reference/TEMPLATE-MASTER.md +727 -0
  246. package/reference/prds/prd-jarvis-mega-brain-v3.md +1305 -0
  247. package/reference/templates/phase5/IMPLEMENTATION-GUIDE.md +355 -0
  248. package/reference/templates/phase5/MOGA-BRAIN-PHASE5-TEMPLATES.md +1284 -0
  249. package/reference/templates/phase5/README.md +165 -0
  250. package/reference/workflow-claude-code-boris-cherny-continuous-claude.md +2232 -0
  251. package/system/database/001_moneyclub_buyers.sql +160 -0
  252. package/system/database/002_premium_token.sql +97 -0
  253. package/system/database/apply-migration.mjs +129 -0
  254. package/system/docs/MEGA-BRAIN-DEMO-COMPLETA.md +1226 -0
  255. package/system/docs/MEGA-BRAIN-MANIFESTO-COMPLETO.md +1054 -0
  256. package/system/docs/MOGA-BRAIN-EXPLICACAO-COMPLETA.md +791 -0
  257. package/system/docs/STRATEGIC-INTEGRATION-GUIDE.md +725 -0
  258. package/system/docs/architecture/01-system-context.md +136 -0
  259. package/system/docs/architecture/02-components.md +225 -0
  260. package/system/docs/architecture/03-data-flow.md +235 -0
  261. package/system/docs/architecture/04-integrations.md +283 -0
  262. package/system/docs/architecture/README.md +71 -0
  263. package/system/docs/architecture/diagrams/component-diagram.mmd +50 -0
  264. package/system/docs/architecture/diagrams/data-flow.mmd +39 -0
  265. package/system/docs/architecture/diagrams/system-overview.mmd +68 -0
  266. package/system/protocols/AGENT-AUTHORITY.md +217 -0
  267. package/system/protocols/CONSTITUICAO-BASE.md +115 -0
  268. package/system/protocols/CONSTITUTION.md +231 -0
  269. package/system/protocols/GOVERNANCE-MAP.md +123 -0
  270. package/system/protocols/HOOK-SECURITY-THREAT-MODEL.md +152 -0
  271. package/system/protocols/ORQUESTRACAO-PROTOCOL.md +215 -0
  272. package/system/protocols/_archive/CHUNKING-PROTOCOL.md +207 -0
  273. package/system/protocols/_archive/ENTITY-RESOLUTION-PROTOCOL.md +269 -0
  274. package/system/protocols/_archive/INSIGHT-EXTRACTION-PROTOCOL.md +257 -0
  275. package/system/protocols/_archive/NARRATIVE-SYNTHESIS-PROTOCOL.md +290 -0
  276. package/system/protocols/agents/AGENT-INTERACTION.md +315 -0
  277. package/system/protocols/agents/CORTEX-PROTOCOL.md +520 -0
  278. package/system/protocols/agents/EPISTEMIC-PROTOCOL.md +465 -0
  279. package/system/protocols/agents/MEMORY-PROTOCOL.md +366 -0
  280. package/system/protocols/agents/WAR-ROOM.md +355 -0
  281. package/system/protocols/company/COMPANY-DOCUMENT-PROTOCOL.md +793 -0
  282. package/system/protocols/company/COMPANY-ENRICHMENT-PROTOCOL.md +679 -0
  283. package/system/protocols/conclave/CONCLAVE-LOG-TEMPLATE-v2.md +309 -0
  284. package/system/protocols/conclave/CONCLAVE-PROTOCOL.md +518 -0
  285. package/system/protocols/conclave/DEBATE-DYNAMICS-CONFIG.yaml +322 -0
  286. package/system/protocols/conclave/DEBATE-DYNAMICS-PROTOCOL.md +613 -0
  287. package/system/protocols/conclave/DEBATE-PROTOCOL.md +323 -0
  288. package/system/protocols/council/COUNCIL-LOG-TEMPLATE-v2.md +309 -0
  289. package/system/protocols/council/COUNCIL-PROTOCOL.md +518 -0
  290. package/system/protocols/council/DEBATE-DYNAMICS-CONFIG.yaml +322 -0
  291. package/system/protocols/council/DEBATE-DYNAMICS-PROTOCOL.md +613 -0
  292. package/system/protocols/council/DEBATE-PROTOCOL.md +323 -0
  293. package/system/protocols/dna/DNA-EXTRACTION-PROTOCOL.md +1214 -0
  294. package/system/protocols/dna/ENRICHMENT-PROTOCOL.md +408 -0
  295. package/system/protocols/dna/REASONING-MODEL-PROTOCOL.md +331 -0
  296. package/system/protocols/pipeline/DOSSIER-COMPILATION-PROTOCOL.md +790 -0
  297. package/system/protocols/pipeline/NARRATIVE-METABOLISM-PROTOCOL.md +292 -0
  298. package/system/protocols/pipeline/PIPELINE-JARVIS-v2.1.md +606 -0
  299. package/system/protocols/pipeline/PROMPT-1.1-CHUNKING.md +154 -0
  300. package/system/protocols/pipeline/PROMPT-1.2-ENTITY-RESOLUTION.md +186 -0
  301. package/system/protocols/pipeline/PROMPT-2.1-DNA-TAGS-INCREMENT.md +208 -0
  302. package/system/protocols/pipeline/PROMPT-2.1-INSIGHT-EXTRACTION.md +191 -0
  303. package/system/protocols/pipeline/PROMPT-3.1-NARRATIVE-SYNTHESIS.md +331 -0
  304. package/system/protocols/pipeline/SOURCES-COMPILATION-PROTOCOL.md +340 -0
  305. package/system/protocols/system/AUTO-LOG-PROTOCOL.md +369 -0
  306. package/system/protocols/system/CHECKPOINT-ENFORCEMENT.md +176 -0
  307. package/system/protocols/system/ENFORCEMENT.md +435 -0
  308. package/system/protocols/system/LOG-TEMPLATES.md +1068 -0
@@ -0,0 +1,433 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Agent Doctor - Layer 2 do META-AGENT System v1.0
4
+
5
+ FUNÇÃO: Diagnostica gaps de qualidade e PROPÕE fixes para revisão humana.
6
+ NÃO aplica fixes automaticamente - salva em doctor_proposals.jsonl.
7
+
8
+ REGRA #28: META-AGENT QUALITY AWARENESS
9
+ PRINCÍPIO: DOCTOR PROPÕE, NÃO APLICA
10
+ """
11
+
12
+ import json
13
+ import os
14
+ import re
15
+ from pathlib import Path
16
+ from datetime import datetime
17
+ from typing import Dict, List, Optional
18
+
19
+ PROJECT_ROOT = Path(os.environ.get('CLAUDE_PROJECT_DIR', '.'))
20
+ LOGS_PATH = PROJECT_ROOT / "logs"
21
+ DOCTOR_PROPOSALS_LOG = LOGS_PATH / "doctor_proposals.jsonl"
22
+ DOCTOR_FIXES_LOG = LOGS_PATH / "doctor_fixes.jsonl"
23
+
24
+
25
+ # ═══════════════════════════════════════════════════════════════════════════
26
+ # MANDATORY HEADER TEMPLATE
27
+ # ═══════════════════════════════════════════════════════════════════════════
28
+
29
+ MANDATORY_HEADER_TEMPLATE = '''## ⚠️ MANDATORY OUTPUT SECTIONS (NEVER SKIP)
30
+ <!-- MANDATORY -->
31
+
32
+ | Section | Required | Marker | Example |
33
+ |---------|----------|--------|---------|
34
+ {sections_table}
35
+
36
+ ## MINIMUM OUTPUT REQUIREMENTS
37
+ {requirements_list}
38
+
39
+ ## QUALITY CHECKLIST (score 0-100)
40
+ - Section present: +10 points each
41
+ - Section complete: +15 points each
42
+ - Format correct: +10 points each
43
+ - MINIMUM TO DELIVER: 70 points
44
+
45
+ <!-- End MANDATORY -->
46
+
47
+ '''
48
+
49
+
50
+ # ═══════════════════════════════════════════════════════════════════════════
51
+ # DIAGNOSIS
52
+ # ═══════════════════════════════════════════════════════════════════════════
53
+
54
+ def diagnose_gap(agent_path: Path, missing_sections: List[str]) -> Dict:
55
+ """
56
+ Diagnostica a causa raiz do gap de qualidade e propõe estratégia de fix.
57
+
58
+ Args:
59
+ agent_path: Caminho para pasta do agente
60
+ missing_sections: Lista de seções que faltaram no output
61
+
62
+ Returns:
63
+ dict com diagnóstico e proposta de fix
64
+ """
65
+ agent_md = agent_path / "AGENT.md"
66
+
67
+ if not agent_md.exists():
68
+ return {
69
+ "root_cause": "agent_not_found",
70
+ "fix_strategy": "create_agent",
71
+ "changes_needed": [],
72
+ "error": f"AGENT.md not found at {agent_md}"
73
+ }
74
+
75
+ try:
76
+ content = agent_md.read_text(encoding='utf-8')
77
+ except Exception as e:
78
+ return {
79
+ "root_cause": "read_error",
80
+ "fix_strategy": "manual_review",
81
+ "changes_needed": [],
82
+ "error": str(e)
83
+ }
84
+
85
+ diagnosis = {
86
+ "root_cause": None,
87
+ "fix_strategy": None,
88
+ "changes_needed": [],
89
+ "agent_path": str(agent_path),
90
+ "file_stats": {
91
+ "total_lines": len(content.split('\n')),
92
+ "total_chars": len(content)
93
+ }
94
+ }
95
+
96
+ # Verificação 1: Tem MANDATORY_SECTIONS header?
97
+ has_mandatory = "MANDATORY OUTPUT SECTIONS" in content or "<!-- MANDATORY -->" in content
98
+
99
+ if not has_mandatory:
100
+ diagnosis["root_cause"] = "no_mandatory_header"
101
+ diagnosis["fix_strategy"] = "add_mandatory_header"
102
+ diagnosis["changes_needed"].append({
103
+ "action": "prepend",
104
+ "description": "Add MANDATORY_SECTIONS header to top of file",
105
+ "content_preview": generate_mandatory_header(missing_sections)[:200] + "..."
106
+ })
107
+ else:
108
+ # MANDATORY existe, mas seções não estão completas
109
+ diagnosis["root_cause"] = "incomplete_mandatory"
110
+ diagnosis["fix_strategy"] = "update_mandatory_header"
111
+ diagnosis["changes_needed"].append({
112
+ "action": "update_mandatory",
113
+ "description": "Update MANDATORY_SECTIONS with missing items",
114
+ "missing": missing_sections
115
+ })
116
+
117
+ # Verificação 2: Arquivo muito longo (pode ser truncado)?
118
+ lines = len(content.split('\n'))
119
+ if lines > 200:
120
+ diagnosis["changes_needed"].append({
121
+ "action": "generate_compact_summary",
122
+ "description": f"Agent file has {lines} lines - may be truncated in context",
123
+ "reason": "Long files may lose MANDATORY sections when loaded",
124
+ "suggested_max": 150
125
+ })
126
+
127
+ # Verificação 3: MANDATORY está no final (bad position)?
128
+ if has_mandatory:
129
+ mandatory_position = content.find("MANDATORY OUTPUT SECTIONS")
130
+ if mandatory_position > len(content) * 0.3: # Depois de 30% do arquivo
131
+ diagnosis["changes_needed"].append({
132
+ "action": "move_mandatory_to_top",
133
+ "description": "MANDATORY section is not at the top of file",
134
+ "current_position": f"{int(mandatory_position/len(content)*100)}% into file",
135
+ "recommended": "First 50 lines"
136
+ })
137
+
138
+ return diagnosis
139
+
140
+
141
+ def generate_mandatory_header(missing_sections: List[str]) -> str:
142
+ """
143
+ Gera header MANDATORY_SECTIONS baseado nas seções faltantes.
144
+ """
145
+ # Mapeia seções para marcadores
146
+ section_markers = {
147
+ "ASCII Header": ("╔═══", "Large title with double border"),
148
+ "Progress Bar": ("████", "Visual progress ████████░░"),
149
+ "Metrics Panel": ("┌─ MÉTRICAS", "Metrics card with [explanations]"),
150
+ "Changes Section": ("O QUE MUDOU", "What changed since last"),
151
+ "Personal Notes": ("NOTAS DO", "Personal observations from agent"),
152
+ "ASCII Boxes": ("┌───┐", "Structured information boxes"),
153
+ "Explanations": ("[explanation]", "Technical terms with context"),
154
+ }
155
+
156
+ sections_table = ""
157
+ requirements_list = ""
158
+
159
+ for section in missing_sections:
160
+ if section in section_markers:
161
+ marker, example = section_markers[section]
162
+ sections_table += f"| {section} | YES | `{marker}` | {example} |\n"
163
+ requirements_list += f"- [ ] Include {section}\n"
164
+ else:
165
+ sections_table += f"| {section} | YES | `{section[:5]}` | Required element |\n"
166
+ requirements_list += f"- [ ] Include {section}\n"
167
+
168
+ return MANDATORY_HEADER_TEMPLATE.format(
169
+ sections_table=sections_table.strip(),
170
+ requirements_list=requirements_list.strip()
171
+ )
172
+
173
+
174
+ # ═══════════════════════════════════════════════════════════════════════════
175
+ # PROPOSAL SYSTEM (NÃO APLICA AUTOMATICAMENTE)
176
+ # ═══════════════════════════════════════════════════════════════════════════
177
+
178
+ def create_fix_proposal(agent_path: Path, diagnosis: Dict) -> Dict:
179
+ """
180
+ Cria proposta de fix para revisão humana.
181
+
182
+ IMPORTANTE: NÃO modifica arquivos diretamente.
183
+ Salva proposta em doctor_proposals.jsonl para revisão.
184
+ """
185
+ proposal_id = f"PROP-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
186
+
187
+ proposal = {
188
+ "proposal_id": proposal_id,
189
+ "timestamp": datetime.now().isoformat(),
190
+ "agent": agent_path.name if agent_path else "unknown",
191
+ "agent_path": str(agent_path) if agent_path else None,
192
+ "diagnosis": {
193
+ "root_cause": diagnosis.get("root_cause"),
194
+ "fix_strategy": diagnosis.get("fix_strategy"),
195
+ "file_stats": diagnosis.get("file_stats", {})
196
+ },
197
+ "proposed_changes": diagnosis.get("changes_needed", []),
198
+ "status": "pending_approval",
199
+ "reviewed_by": None,
200
+ "review_date": None,
201
+ "applied": False
202
+ }
203
+
204
+ # Salva proposta para revisão humana
205
+ save_proposal(proposal)
206
+
207
+ # Log que proposta foi criada (não aplicada)
208
+ log_proposal_created(proposal)
209
+
210
+ return {
211
+ "success": True,
212
+ "action": "proposed",
213
+ "proposal_id": proposal_id,
214
+ "review_required": True,
215
+ "message": f"Fix proposal created: {proposal_id}. Awaiting human review."
216
+ }
217
+
218
+
219
+ def save_proposal(proposal: Dict):
220
+ """Salva proposta no log de proposals."""
221
+ DOCTOR_PROPOSALS_LOG.parent.mkdir(parents=True, exist_ok=True)
222
+
223
+ try:
224
+ with open(DOCTOR_PROPOSALS_LOG, "a", encoding='utf-8') as f:
225
+ f.write(json.dumps(proposal, ensure_ascii=False) + "\n")
226
+ except Exception as e:
227
+ print(f"Error saving proposal: {e}")
228
+
229
+
230
+ def log_proposal_created(proposal: Dict):
231
+ """Loga que proposta foi criada (para histórico/auditoria)."""
232
+ DOCTOR_FIXES_LOG.parent.mkdir(parents=True, exist_ok=True)
233
+
234
+ entry = {
235
+ "timestamp": datetime.now().isoformat(),
236
+ "proposal_id": proposal.get("proposal_id"),
237
+ "agent": proposal.get("agent"),
238
+ "root_cause": proposal.get("diagnosis", {}).get("root_cause"),
239
+ "fix_strategy": proposal.get("diagnosis", {}).get("fix_strategy"),
240
+ "status": "proposed_pending_review",
241
+ "auto_applied": False
242
+ }
243
+
244
+ try:
245
+ with open(DOCTOR_FIXES_LOG, "a", encoding='utf-8') as f:
246
+ f.write(json.dumps(entry, ensure_ascii=False) + "\n")
247
+ except Exception:
248
+ pass
249
+
250
+
251
+ # ═══════════════════════════════════════════════════════════════════════════
252
+ # PROPOSAL MANAGEMENT
253
+ # ═══════════════════════════════════════════════════════════════════════════
254
+
255
+ def list_pending_proposals() -> List[Dict]:
256
+ """Lista todas as propostas pendentes de aprovação."""
257
+ if not DOCTOR_PROPOSALS_LOG.exists():
258
+ return []
259
+
260
+ pending = []
261
+ try:
262
+ with open(DOCTOR_PROPOSALS_LOG, "r", encoding='utf-8') as f:
263
+ for line in f:
264
+ if line.strip():
265
+ proposal = json.loads(line)
266
+ if proposal.get("status") == "pending_approval":
267
+ pending.append(proposal)
268
+ except Exception:
269
+ pass
270
+
271
+ return pending
272
+
273
+
274
+ def approve_proposal(proposal_id: str, reviewer: str = "human") -> Dict:
275
+ """
276
+ Marca proposta como aprovada (ainda não aplica).
277
+
278
+ Para aplicar de fato, use apply_approved_proposal().
279
+ """
280
+ proposals = []
281
+ approved = None
282
+
283
+ if DOCTOR_PROPOSALS_LOG.exists():
284
+ with open(DOCTOR_PROPOSALS_LOG, "r", encoding='utf-8') as f:
285
+ for line in f:
286
+ if line.strip():
287
+ proposal = json.loads(line)
288
+ if proposal.get("proposal_id") == proposal_id:
289
+ proposal["status"] = "approved"
290
+ proposal["reviewed_by"] = reviewer
291
+ proposal["review_date"] = datetime.now().isoformat()
292
+ approved = proposal
293
+ proposals.append(proposal)
294
+
295
+ if approved:
296
+ # Reescreve arquivo com status atualizado
297
+ with open(DOCTOR_PROPOSALS_LOG, "w", encoding='utf-8') as f:
298
+ for p in proposals:
299
+ f.write(json.dumps(p, ensure_ascii=False) + "\n")
300
+
301
+ return {"success": True, "proposal": approved}
302
+
303
+ return {"success": False, "error": f"Proposal {proposal_id} not found"}
304
+
305
+
306
+ def reject_proposal(proposal_id: str, reason: str, reviewer: str = "human") -> Dict:
307
+ """Marca proposta como rejeitada."""
308
+ proposals = []
309
+ rejected = None
310
+
311
+ if DOCTOR_PROPOSALS_LOG.exists():
312
+ with open(DOCTOR_PROPOSALS_LOG, "r", encoding='utf-8') as f:
313
+ for line in f:
314
+ if line.strip():
315
+ proposal = json.loads(line)
316
+ if proposal.get("proposal_id") == proposal_id:
317
+ proposal["status"] = "rejected"
318
+ proposal["reviewed_by"] = reviewer
319
+ proposal["review_date"] = datetime.now().isoformat()
320
+ proposal["rejection_reason"] = reason
321
+ rejected = proposal
322
+ proposals.append(proposal)
323
+
324
+ if rejected:
325
+ with open(DOCTOR_PROPOSALS_LOG, "w", encoding='utf-8') as f:
326
+ for p in proposals:
327
+ f.write(json.dumps(p, ensure_ascii=False) + "\n")
328
+
329
+ return {"success": True, "proposal": rejected}
330
+
331
+ return {"success": False, "error": f"Proposal {proposal_id} not found"}
332
+
333
+
334
+ # ═══════════════════════════════════════════════════════════════════════════
335
+ # MAIN INTERFACE
336
+ # ═══════════════════════════════════════════════════════════════════════════
337
+
338
+ def process_quality_gap(
339
+ agent_path: Path,
340
+ missing_sections: List[str],
341
+ score: int
342
+ ) -> Dict:
343
+ """
344
+ Processa um gap de qualidade detectado pelo WATCHDOG.
345
+
346
+ Interface principal para integração com post_output_validator.py
347
+
348
+ Args:
349
+ agent_path: Path para a pasta do agente
350
+ missing_sections: Seções que faltaram no output
351
+ score: Score de qualidade (0-100)
352
+
353
+ Returns:
354
+ dict com resultado do processamento
355
+ """
356
+ result = {
357
+ "timestamp": datetime.now().isoformat(),
358
+ "agent": agent_path.name if agent_path else "unknown",
359
+ "score": score,
360
+ "missing": missing_sections
361
+ }
362
+
363
+ # Só processa se score for muito baixo (< 50)
364
+ if score >= 50:
365
+ result["action"] = "skipped"
366
+ result["reason"] = "Score above proposal threshold (50)"
367
+ return result
368
+
369
+ # Diagnostica o problema
370
+ diagnosis = diagnose_gap(agent_path, missing_sections)
371
+
372
+ # Cria proposta (não aplica)
373
+ proposal_result = create_fix_proposal(agent_path, diagnosis)
374
+
375
+ result["diagnosis"] = diagnosis
376
+ result["proposal"] = proposal_result
377
+ result["action"] = "proposal_created"
378
+
379
+ return result
380
+
381
+
382
+ # ═══════════════════════════════════════════════════════════════════════════
383
+ # CLI INTERFACE
384
+ # ═══════════════════════════════════════════════════════════════════════════
385
+
386
+ if __name__ == "__main__":
387
+ import sys
388
+
389
+ if len(sys.argv) > 1:
390
+ command = sys.argv[1]
391
+
392
+ if command == "list":
393
+ # Listar propostas pendentes
394
+ pending = list_pending_proposals()
395
+ print(f"Pending proposals: {len(pending)}\n")
396
+ for p in pending:
397
+ print(f" {p['proposal_id']}: {p['agent']} - {p['diagnosis']['root_cause']}")
398
+
399
+ elif command == "approve" and len(sys.argv) > 2:
400
+ # Aprovar proposta
401
+ proposal_id = sys.argv[2]
402
+ result = approve_proposal(proposal_id)
403
+ print(f"Approve result: {result}")
404
+
405
+ elif command == "reject" and len(sys.argv) > 3:
406
+ # Rejeitar proposta
407
+ proposal_id = sys.argv[2]
408
+ reason = sys.argv[3]
409
+ result = reject_proposal(proposal_id, reason)
410
+ print(f"Reject result: {result}")
411
+
412
+ else:
413
+ print("Usage:")
414
+ print(" python agent_doctor.py list - List pending proposals")
415
+ print(" python agent_doctor.py approve <proposal_id> - Approve proposal")
416
+ print(" python agent_doctor.py reject <proposal_id> <reason> - Reject proposal")
417
+
418
+ else:
419
+ # Test mode
420
+ test_path = PROJECT_ROOT / ".claude" / "jarvis" / "sub-agents" / "chronicler"
421
+ test_missing = ["ASCII Header", "Progress Bar", "Changes Section"]
422
+
423
+ print(f"Testing diagnosis for: {test_path}\n")
424
+
425
+ diagnosis = diagnose_gap(test_path, test_missing)
426
+ print(f"Diagnosis:")
427
+ print(f" Root cause: {diagnosis['root_cause']}")
428
+ print(f" Fix strategy: {diagnosis['fix_strategy']}")
429
+ print(f" Changes needed: {len(diagnosis['changes_needed'])}")
430
+
431
+ print("\nCreating proposal (not applying)...")
432
+ result = create_fix_proposal(test_path, diagnosis)
433
+ print(f"Result: {result}")
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Agent Memory Persister Hook v1.0 (Mega Brain)
4
+
5
+ Persists session learnings to the active agent's memory file at session end.
6
+ Adapted from: aios-core/.claude/hooks/agent_memory_persister.py
7
+
8
+ LIFECYCLE:
9
+ READ: skill_router.py (UserPromptSubmit) -> loads .claude/agent-memory/{slug}/MEMORY.md
10
+ WRITE: post_batch_cascading.py (PostToolUse) -> writes batch learnings
11
+ WRITE: THIS HOOK (SessionEnd) -> writes session summary
12
+
13
+ BEHAVIOR:
14
+ - Reads active agent from STATE.json (session.agent_active)
15
+ - Appends a session entry to .claude/agent-memory/{slug}/MEMORY.md
16
+ - Creates the memory file if it doesn't exist
17
+ - Fail-open: NEVER blocks session end
18
+
19
+ EXIT CODES:
20
+ - 0: Always (advisory only, never blocks)
21
+
22
+ Hook Type: SessionEnd
23
+ """
24
+
25
+ import json
26
+ import sys
27
+ import os
28
+ import time
29
+ from datetime import datetime
30
+ from pathlib import Path
31
+
32
+ PROJECT_ROOT = Path(os.environ.get('CLAUDE_PROJECT_DIR', '.'))
33
+ STATE_DIR = PROJECT_ROOT / ".claude" / "jarvis"
34
+ STATE_FILE = STATE_DIR / "STATE.json"
35
+ AGENT_MEMORY_DIR = PROJECT_ROOT / ".claude" / "agent-memory"
36
+
37
+ # Internal time budget (ms)
38
+ INTERNAL_TIMEOUT_MS = 3000
39
+
40
+
41
+ def load_state() -> dict:
42
+ """Load current state."""
43
+ if not STATE_FILE.exists():
44
+ return {}
45
+ try:
46
+ with open(STATE_FILE, 'r', encoding='utf-8') as f:
47
+ return json.load(f)
48
+ except (json.JSONDecodeError, IOError):
49
+ return {}
50
+
51
+
52
+ def get_active_agent(state: dict) -> str | None:
53
+ """Extract active agent slug from STATE.json."""
54
+ # Check session.agent_active (set by skill_router/post_tool_use)
55
+ session = state.get("session", {})
56
+ agent = session.get("agent_active")
57
+ if agent and isinstance(agent, str) and agent.strip():
58
+ return agent.strip()
59
+ return None
60
+
61
+
62
+ def get_session_metadata(state: dict) -> dict:
63
+ """Extract useful session metadata for the memory entry."""
64
+ accumulated = state.get("accumulated", {})
65
+ pipeline = state.get("pipeline", {})
66
+
67
+ return {
68
+ "session_id": state.get("session_id", "unknown"),
69
+ "ended_at": datetime.now().isoformat(),
70
+ "files_processed": pipeline.get("files_processed", 0),
71
+ "progress_percent": accumulated.get("progress_percent", 0),
72
+ "current_step": pipeline.get("current_step", "unknown"),
73
+ }
74
+
75
+
76
+ def get_memory_path(agent_slug: str) -> Path:
77
+ """Resolve agent memory path."""
78
+ return AGENT_MEMORY_DIR / agent_slug / "MEMORY.md"
79
+
80
+
81
+ def create_memory_file(memory_path: Path, agent_slug: str) -> None:
82
+ """Create a new MEMORY.md with header."""
83
+ memory_path.parent.mkdir(parents=True, exist_ok=True)
84
+ header = f"""# {agent_slug} - Agent Memory
85
+
86
+ > Auto-managed by hooks. Do not edit manually.
87
+ > READ: skill_router.py (on activation)
88
+ > WRITE: agent_memory_persister.py (on session end)
89
+
90
+ ---
91
+
92
+ """
93
+ memory_path.write_text(header, encoding='utf-8')
94
+
95
+
96
+ def build_session_entry(agent_slug: str, metadata: dict) -> str:
97
+ """Build a markdown session entry to append to MEMORY.md."""
98
+ now = datetime.now()
99
+ date_str = now.strftime("%Y-%m-%d %H:%M")
100
+ session_id_short = metadata.get("session_id", "unknown")[:8]
101
+
102
+ lines = [
103
+ f"## Session {date_str} [{session_id_short}]",
104
+ "",
105
+ f"- **Step:** {metadata.get('current_step', 'unknown')}",
106
+ f"- **Progress:** {metadata.get('progress_percent', 0)}%",
107
+ f"- **Files processed:** {metadata.get('files_processed', 0)}",
108
+ "",
109
+ "---",
110
+ "",
111
+ ]
112
+
113
+ return "\n".join(lines)
114
+
115
+
116
+ def append_to_memory(memory_path: Path, entry: str) -> bool:
117
+ """Append session entry to MEMORY.md, trimming if over 200 lines."""
118
+ try:
119
+ if not memory_path.exists():
120
+ return False
121
+
122
+ content = memory_path.read_text(encoding='utf-8')
123
+ new_content = content.rstrip('\n') + '\n\n' + entry
124
+
125
+ final_lines = new_content.split('\n')
126
+ if len(final_lines) > 200:
127
+ header = final_lines[:20]
128
+ recent = final_lines[-175:]
129
+ final_lines = header + ["", "<!-- Older entries trimmed by agent_memory_persister.py -->", ""] + recent
130
+
131
+ memory_path.write_text('\n'.join(final_lines), encoding='utf-8')
132
+ return True
133
+ except Exception:
134
+ return False
135
+
136
+
137
+ def check_timeout(start_time):
138
+ """Check if we've exceeded internal time budget."""
139
+ elapsed_ms = (time.time() - start_time) * 1000
140
+ return elapsed_ms > INTERNAL_TIMEOUT_MS
141
+
142
+
143
+ def main():
144
+ """Main hook execution with timeout protection."""
145
+ start_time = time.time()
146
+
147
+ try:
148
+ input_data = sys.stdin.read()
149
+ hook_input = json.loads(input_data) if input_data.strip() else {}
150
+
151
+ state = load_state()
152
+ if not state:
153
+ print(json.dumps({"continue": True}))
154
+ return
155
+
156
+ raw_slug = get_active_agent(state)
157
+ if not raw_slug:
158
+ print(json.dumps({"continue": True}))
159
+ return
160
+
161
+ if check_timeout(start_time):
162
+ print(json.dumps({
163
+ "continue": True,
164
+ "feedback": "[MB] Memory persister skipped (timeout after state load)"
165
+ }))
166
+ return
167
+
168
+ agent_slug = raw_slug
169
+ memory_path = get_memory_path(agent_slug)
170
+
171
+ if not memory_path.exists():
172
+ create_memory_file(memory_path, agent_slug)
173
+
174
+ if check_timeout(start_time):
175
+ print(json.dumps({
176
+ "continue": True,
177
+ "feedback": "[MB] Memory persister skipped (timeout before entry build)"
178
+ }))
179
+ return
180
+
181
+ metadata = get_session_metadata(state)
182
+ entry = build_session_entry(agent_slug, metadata)
183
+ success = append_to_memory(memory_path, entry)
184
+
185
+ output = {"continue": True}
186
+
187
+ if success:
188
+ elapsed_ms = round((time.time() - start_time) * 1000)
189
+ output["feedback"] = f"[MB] Session memory persisted for @{agent_slug} ({elapsed_ms}ms)"
190
+ else:
191
+ output["feedback"] = f"[MB] Could not persist memory for @{agent_slug}"
192
+
193
+ print(json.dumps(output))
194
+
195
+ except Exception as e:
196
+ print(json.dumps({
197
+ "continue": True,
198
+ "feedback": f"[MB] Memory persister error (fail-open): {str(e)}"
199
+ }))
200
+
201
+
202
+ if __name__ == "__main__":
203
+ main()