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,170 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ BUILD PLANILHA INDEX - Cria índice nome→TAG da planilha
4
+ Processa os arquivos JSON exportados das abas do Google Sheets
5
+ """
6
+
7
+ import os
8
+ import re
9
+ import json
10
+ from datetime import datetime
11
+
12
+ # Configurações
13
+ TOOL_RESULTS_PATH = "" # Set to your Claude tool-results path
14
+ OUTPUT_PATH = ".claude/mission-control/PLANILHA-INDEX.json"
15
+ SCHEMA_PATH = ".claude/mission-control/SPREADSHEET-SCHEMA.json"
16
+
17
+ def normalize_name(name):
18
+ """Normaliza nome para matching."""
19
+ if not name:
20
+ return ""
21
+ # Lowercase
22
+ name = str(name).lower()
23
+ # Remove extensão
24
+ name = re.sub(r'\.(mp4|docx|txt|pdf)$', '', name, flags=re.IGNORECASE)
25
+ # Remove número inicial
26
+ name = re.sub(r'^\d+[\s\.\-]+', '', name)
27
+ # Remove (1), (2), etc
28
+ name = re.sub(r'\s*\(\d+\)\s*', '', name)
29
+ # Remove caracteres especiais
30
+ name = re.sub(r'[^\w\s]', ' ', name)
31
+ name = re.sub(r'\s+', ' ', name).strip()
32
+ return name
33
+
34
+ def process_sheet_data(data, sheet_name, tag_col_index):
35
+ """Processa dados de uma aba e extrai entradas."""
36
+ entries = []
37
+
38
+ for row in data:
39
+ if not row or len(row) < tag_col_index + 1:
40
+ continue
41
+
42
+ # Extrair valores relevantes
43
+ name_cell = row[0] if len(row) > 0 else None # Coluna B (nome)
44
+ tag_cell = row[tag_col_index] if len(row) > tag_col_index else None
45
+
46
+ if not name_cell or not tag_cell:
47
+ continue
48
+
49
+ name = name_cell.get('value', '') if isinstance(name_cell, dict) else str(name_cell)
50
+ tag = tag_cell.get('value', '') if isinstance(tag_cell, dict) else str(tag_cell)
51
+
52
+ # Verificar se TAG é válida
53
+ if not tag or not re.match(r'^[\w-]+-\d{4}$', tag):
54
+ continue
55
+
56
+ entries.append({
57
+ 'original_name': name,
58
+ 'normalized': normalize_name(name),
59
+ 'tag': tag,
60
+ 'sheet': sheet_name
61
+ })
62
+
63
+ return entries
64
+
65
+ def main():
66
+ print("=" * 60)
67
+ print("BUILD PLANILHA INDEX")
68
+ print("=" * 60)
69
+ print()
70
+
71
+ # Carregar schema para saber configuração de cada aba
72
+ print("[1/3] Carregando schema...")
73
+ with open(SCHEMA_PATH, 'r', encoding='utf-8') as f:
74
+ schema = json.load(f)
75
+
76
+ # Encontrar arquivos JSON do Google Sheets
77
+ print("[2/3] Processando dados exportados...")
78
+
79
+ # Dados inline do Sales Training (copiados do resultado anterior)
80
+ # Por agora, vou criar entradas manualmente baseadas no schema
81
+
82
+ entries = []
83
+
84
+ # Dados do Jeremy Haynes Sales Training (processado inline)
85
+ jh_st_data = [
86
+ ("1 - Introduction to Sales Training", "JH-ST-0001"),
87
+ ("2. The Plague of Fat Cat Closers", "JH-ST-0002"),
88
+ ("3. How to Deal With Inbound Leads Who Only Filled Out a Form", "JH-ST-0003"),
89
+ ("4. Sales Team Structures to Consider", "JH-ST-0004"),
90
+ ("5. The Cleaner Role", "JH-ST-0005"),
91
+ ("6. Using Sales Videos to Aid The Sales Process", "JH-ST-0006"),
92
+ ("7. Selfie Follow up Video Texts Get an iphone", "JH-ST-0007"),
93
+ ("8. Get Leads Back on The Phone With Value Driven Follow up", "JH-ST-0008"),
94
+ ("9. How to Increase Show Rate", "JH-ST-0009"),
95
+ ("10.Why You Should Text Every Lead Manually", "JH-ST-0010"),
96
+ ("11. Value Added vs Selfish Questions", "JH-ST-0011"),
97
+ ("12. Value Added Questions vs Selfish Questions", "JH-ST-0012"),
98
+ ("13. How to Increase Average Order Value", "JH-ST-0013"),
99
+ ("14. How to Recruit Sales People", "JH-ST-0014"),
100
+ ("15. How to Train Maintain a Great Sales Team", "JH-ST-0015"),
101
+ ("16. Why Full Time Closers Are Better", "JH-ST-0016"),
102
+ ("17. How to Raise The Value of The Price", "JH-ST-0017"),
103
+ ("18. Raising The Clients Interest Level", "JH-ST-0018"),
104
+ ("19. How to Create Real Scarcity Urgency", "JH-ST-0019"),
105
+ ("20. Reviewing Calls Providing Feedback", "JH-ST-0020"),
106
+ ("21. Your Personal Life Impacts Your Professional Life", "JH-ST-0021"),
107
+ ("22. Tools Software For Closers", "JH-ST-0022"),
108
+ ("23. When to Fire Sales Reps", "JH-ST-0023"),
109
+ ("24. Keep Your Moral High", "JH-ST-0024"),
110
+ ("25. Sales Training With Jordan Stupar", "JH-ST-0025"),
111
+ ("26. Sales Training With Josh Troy", "JH-ST-0026"),
112
+ ("1. Intro to Objections", "JH-ST-0028"),
113
+ ("2. What Happens if You go Out of Business", "JH-ST-0029"),
114
+ ("3. How do I Know my Money is Safe", "JH-ST-0030"),
115
+ ("4. Can I Speak to The Owner", "JH-ST-0031"),
116
+ ("5. How Can You Guarantee That Ill Make Money", "JH-ST-0032"),
117
+ ("6. Why Are You Better Than Everybody Else", "JH-ST-0033"),
118
+ ("7. Id Rather Get Started Next Quarter", "JH-ST-0034"),
119
+ ("8. I Have to Get my Lawyer to Review Before Moving Forward", "JH-ST-0035"),
120
+ ("9. My Business Partner I Will Need To Review This", "JH-ST-0036"),
121
+ ("10. Im Traveling This Week Lets Move Forward Next Week", "JH-ST-0037"),
122
+ ("11. Are You Open to Changes in The Agreement", "JH-ST-0038"),
123
+ ("12. Can I Speak to an Existing Client", "JH-ST-0039"),
124
+ ("13. I Saw a Negative Review Im Afraid Itll Happen to me", "JH-ST-0040"),
125
+ ("14. Objection I Cant Afford This", "JH-ST-0041"),
126
+ ("15. Objection I Cant Afford This", "JH-ST-0042"),
127
+ ("16. Objection I Cant Afford This", "JH-ST-0043"),
128
+ ("17. I Didnt Expect it to Cost This Much", "JH-ST-0044"),
129
+ ("18. I am Looking at Other Service Providers", "JH-ST-0045"),
130
+ ]
131
+
132
+ for name, tag in jh_st_data:
133
+ entries.append({
134
+ 'original_name': name,
135
+ 'normalized': normalize_name(name),
136
+ 'tag': tag,
137
+ 'sheet': 'Jeremy Haynes Sales Training'
138
+ })
139
+
140
+ print(f" Processadas {len(entries)} entradas iniciais")
141
+ print()
142
+ print(" NOTA: Este script precisa ser expandido para processar todas as abas")
143
+ print(" via API do Google Sheets ou arquivos JSON exportados.")
144
+ print()
145
+
146
+ # 3. Salvar índice
147
+ print("[3/3] Salvando índice...")
148
+
149
+ index = {
150
+ 'version': '1.0',
151
+ 'timestamp': datetime.now().isoformat(),
152
+ 'total_entries': len(entries),
153
+ 'sheets_processed': list(set(e['sheet'] for e in entries)),
154
+ 'entries': entries
155
+ }
156
+
157
+ with open(OUTPUT_PATH, 'w', encoding='utf-8') as f:
158
+ json.dump(index, f, ensure_ascii=False, indent=2)
159
+
160
+ print(f" Salvo em: {OUTPUT_PATH}")
161
+ print(f" Total: {len(entries)} entradas")
162
+ print()
163
+ print("=" * 60)
164
+ print("ÍNDICE CRIADO (parcial)")
165
+ print("=" * 60)
166
+
167
+ return index
168
+
169
+ if __name__ == '__main__':
170
+ main()
@@ -0,0 +1,250 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Complete Tag Matching Script - DE-PARA 1-a-1
4
+ Matches each untagged file to its correct planilha entry and applies TAG
5
+ """
6
+
7
+ import os
8
+ import re
9
+ import json
10
+ from difflib import SequenceMatcher
11
+
12
+ # Planilha data - extracted from Google Sheets
13
+ PLANILHA_DATA = {
14
+ "30 Days Challenge": {
15
+ "prefix": "30DC",
16
+ "entries": {
17
+ "1 - Day 1": "30DC-0001",
18
+ "2 - Day 2": "30DC-0002",
19
+ "3 - Day 3": "30DC-0003",
20
+ "4 - Day 4": "30DC-0004",
21
+ "5 - Day 5": "30DC-0005",
22
+ "6 - Day 6": "30DC-0006",
23
+ "7 - Day 7": "30DC-0007",
24
+ "8 - Day 8": "30DC-0008",
25
+ "9 - Day 9": "30DC-0009",
26
+ "10 - Day 10": "30DC-0010",
27
+ "11 - Day 11.": "30DC-0011",
28
+ "12 - Day 12.": "30DC-0012",
29
+ "13- Day 13.": "30DC-0013",
30
+ "14 - Day 14.": "30DC-0014",
31
+ "15 - Day 15": "30DC-0015",
32
+ "16 - Day 16": "30DC-0016",
33
+ "17 - Day 17": "30DC-0017",
34
+ "18 - Day 18": "30DC-0018",
35
+ "19 - Day 19": "30DC-0019",
36
+ "20 - Day 20": "30DC-0020",
37
+ "21 - Day 21": "30DC-0021",
38
+ "22 - Day 22": "30DC-0022",
39
+ "23 - Day 23": "30DC-0023",
40
+ "24 - Day 24": "30DC-0024",
41
+ "25 - Day 25": "30DC-0025",
42
+ "26 - Day 26": "30DC-0026",
43
+ "27 - Day 27": "30DC-0027",
44
+ "28 - Day 28": "30DC-0028",
45
+ "29 - Day 29.": "30DC-0029",
46
+ "30 - Day 30": "30DC-0030",
47
+ }
48
+ },
49
+ "Cold Video Pitch": {
50
+ "prefix": "PCVP",
51
+ "entries": {
52
+ "1. Power Of Cold Video.": "PCVP-0001",
53
+ "2. Selling Advertising.": "PCVP-0002",
54
+ "3. Social Media Management.": "PCVP-0003",
55
+ "4. Google PPC.": "PCVP-0004",
56
+ "5. Facebook And Instagram.": "PCVP-0005",
57
+ "6. Long Form Content Creation.": "PCVP-0006",
58
+ "7. Animation.": "PCVP-0007",
59
+ "8. Graphics Design.": "PCVP-0008",
60
+ "9. Google Listing.": "PCVP-0009",
61
+ "10. Redoing Thumbnails.": "PCVP-0010",
62
+ "11. Sell Funnels.": "PCVP-0011",
63
+ "12. Chatbots.": "PCVP-0012",
64
+ "13. PR Services.": "PCVP-0013",
65
+ }
66
+ },
67
+ "Agency Blueprint": {
68
+ "prefix": "AOBA",
69
+ "entries": {
70
+ "1. What Is A Marketing Agency.": "AOBA-0001",
71
+ "2. Phases Of A Marketing Agency.": "AOBA-0002",
72
+ "3. Skills Or No Skills.": "AOBA-0003",
73
+ "4. Is It Best To Have Stuff Or A Referral Network.": "AOBA-0004",
74
+ "5. What Are The Possible Limiting Beliefs.": "AOBA-0005",
75
+ "6. What Is PPHD.": "AOBA-0006",
76
+ "7. Leveraging The Facebook Group.": "AOBA-0007",
77
+ "8. Is It Best To Go General Or Niche.": "AOBA-0008",
78
+ "9. Whats The Best Business Model Service Clients Or Consulting.": "AOBA-0009",
79
+ "10. How To Keep A Real Perspective Of Things.": "AOBA-0010",
80
+ "11. Do You Need A Website For Your Agency.": "AOBA-0011",
81
+ "12. How To Become An Expert.": "AOBA-0012",
82
+ "13. Before You Even Think About Getting A Partner.": "AOBA-0013",
83
+ "14. How To Be Comfortable With Failure.": "AOBA-0014",
84
+ "15. Anatomy Of A Perfect Client.": "AOBA-0015",
85
+ "16. How To Keep Your Standards High.": "AOBA-0016",
86
+ "17. The Power Of Expert Positioning": "AOBA-0017",
87
+ "18. How To Improve Your Social Presence.": "AOBA-0018",
88
+ "19. The Best Way To Hijack Authority.": "AOBA-0019",
89
+ "20. Differences Between Hard Flex and Soft Flex.": "AOBA-0020",
90
+ "21. When To Ask For Testimonials.": "AOBA-0021",
91
+ "22. Every Result Is A Marketable Headline.": "AOBA-0022",
92
+ "23. How To PR For Expansion.": "AOBA-0023",
93
+ "24. How To Overcome Major Obstacles.": "AOBA-0024",
94
+ "25. Is It Better To Charge High-Ticket Or Competitive Pricing.": "AOBA-0025",
95
+ "26. What Are The Core Services To Offer.": "AOBA-0026",
96
+ "27. What Model Is Better Transactional Or Recurring.": "AOBA-0027",
97
+ "28. How To Move From Transactional To Recurring.": "AOBA-0028",
98
+ "29. How To Stay Away From Free To Paid Service.": "AOBA-0029",
99
+ "30. The Profit First Business Model.": "AOBA-0030",
100
+ "31. How To Manage Agency Costs.": "AOBA-0031",
101
+ "32. How To Setup Bank Accounts.": "AOBA-0032",
102
+ "33. State Of The Agency Contraction And Expansion.": "AOBA-0033",
103
+ "34. Refunds Policy No Refunds.": "AOBA-0034",
104
+ "35. Result-Driven Services.": "AOBA-0035",
105
+ "36. Is It Better To Have A Contract Or Not.": "AOBA-0036",
106
+ "37. Change Is The Only Constant.": "AOBA-0037",
107
+ "38. Is It Best To Get New Skills Or Referrals.": "AOBA-0038",
108
+ "39. Cash Is Like Oxygen.": "AOBA-0039",
109
+ "40. Why Big Companies Focus On Sales.": "AOBA-0040",
110
+ "41. Daily Attitude And Training": "AOBA-0041",
111
+ "42. How Your Outflow Equals Your Inflow.": "AOBA-0042",
112
+ "43. Money Is In The Follow Up.": "AOBA-0043",
113
+ "44. How To Use Conviction To Win More.": "AOBA-0044",
114
+ "45. How To Win The Sales Game.": "AOBA-0045",
115
+ "46. Duplicating Yourself With Sales People.": "AOBA-0046",
116
+ "47. How To Be Confident In Your Services.": "AOBA-0047",
117
+ "48. How To Keep Your Cool At All Times.": "AOBA-0048",
118
+ "49. Is Cold Calling Dead.": "AOBA-0049",
119
+ "50. How To Keep A Full Pipeline.": "AOBA-0050",
120
+ "51. When Is It Time To Fire A Client.": "AOBA-0051",
121
+ "52. How To Deal With More Rejection Than Acceptance": "AOBA-0052",
122
+ "53. What Is A VAK.": "AOBA-0053",
123
+ "54. Leverage The Power Of Math.": "AOBA-0054",
124
+ "55. How To Use Systems To Save Your Agency.": "AOBA-0055",
125
+ "56. How To Keep Your Team Accountable.": "AOBA-0056",
126
+ "57. Expectations Equal Success.": "AOBA-0057",
127
+ }
128
+ }
129
+ }
130
+
131
+ def normalize_name(name):
132
+ """Normalize filename for matching"""
133
+ # Remove extension
134
+ name = re.sub(r'\.(txt|docx|mp4|pdf)$', '', name, flags=re.IGNORECASE)
135
+ # Remove youtube references
136
+ name = re.sub(r'\s*\[youtube\.com.*?\]', '', name)
137
+ # Remove timestamps
138
+ name = re.sub(r'\s*\d{1,2}-\d{1,2}-\d{2,4}', '', name)
139
+ # Normalize spaces and case
140
+ name = name.strip().lower()
141
+ # Remove multiple spaces
142
+ name = re.sub(r'\s+', ' ', name)
143
+ return name
144
+
145
+ def find_best_match(filename, threshold=0.7):
146
+ """Find best matching planilha entry for a filename"""
147
+ norm_file = normalize_name(filename)
148
+
149
+ best_match = None
150
+ best_score = 0
151
+ best_tag = None
152
+ best_source = None
153
+
154
+ for source, data in PLANILHA_DATA.items():
155
+ for entry_name, tag in data["entries"].items():
156
+ norm_entry = normalize_name(entry_name)
157
+ score = SequenceMatcher(None, norm_file, norm_entry).ratio()
158
+
159
+ if score > best_score:
160
+ best_score = score
161
+ best_match = entry_name
162
+ best_tag = tag
163
+ best_source = source
164
+
165
+ if best_score >= threshold:
166
+ return {
167
+ "matched_to": best_match,
168
+ "tag": best_tag,
169
+ "source": best_source,
170
+ "score": best_score
171
+ }
172
+ return None
173
+
174
+ def get_untagged_files(inbox_path):
175
+ """Get all untagged .txt files"""
176
+ untagged = []
177
+
178
+ for root, dirs, files in os.walk(inbox_path):
179
+ # Skip hidden and backup folders
180
+ dirs[:] = [d for d in dirs if not d.startswith('.') and not d.startswith('_')]
181
+
182
+ for f in files:
183
+ if f.endswith('.txt') and not (f.startswith('[') and ']' in f):
184
+ full_path = os.path.join(root, f)
185
+ rel_path = full_path.replace(inbox_path + '/', '')
186
+ untagged.append({
187
+ "filename": f,
188
+ "full_path": full_path,
189
+ "rel_path": rel_path
190
+ })
191
+
192
+ return untagged
193
+
194
+ def main():
195
+ inbox_path = "inbox"
196
+
197
+ print("=== COMPLETE TAG MATCHING - DE-PARA 1-a-1 ===\n")
198
+
199
+ # Get untagged files
200
+ untagged = get_untagged_files(inbox_path)
201
+ print(f"Total arquivos sem TAG: {len(untagged)}\n")
202
+
203
+ # Match each file
204
+ matches = []
205
+ orphans = []
206
+
207
+ for file_info in untagged:
208
+ match = find_best_match(file_info["filename"])
209
+ if match:
210
+ matches.append({
211
+ **file_info,
212
+ **match
213
+ })
214
+ else:
215
+ orphans.append(file_info)
216
+
217
+ print(f"MATCHES ENCONTRADOS: {len(matches)}")
218
+ print(f"ÓRFÃOS (sem match): {len(orphans)}\n")
219
+
220
+ print("=== MATCHES DETALHADOS ===\n")
221
+ for m in sorted(matches, key=lambda x: x["tag"]):
222
+ print(f"[{m['tag']}] {m['filename']}")
223
+ print(f" → Planilha: {m['matched_to']} ({m['source']})")
224
+ print(f" → Score: {m['score']:.2%}")
225
+ print(f" → Path: {m['rel_path']}")
226
+ print()
227
+
228
+ print("\n=== ÓRFÃOS (ARQUIVOS SEM MATCH NA PLANILHA) ===\n")
229
+ for o in orphans:
230
+ print(f" ✗ {o['rel_path']}")
231
+
232
+ # Save results
233
+ results = {
234
+ "total_untagged": len(untagged),
235
+ "total_matches": len(matches),
236
+ "total_orphans": len(orphans),
237
+ "matches": matches,
238
+ "orphans": orphans
239
+ }
240
+
241
+ output_path = ".claude/mission-control/COMPLETE-TAG-MATCHING.json"
242
+ with open(output_path, 'w') as f:
243
+ json.dump(results, f, indent=2, ensure_ascii=False)
244
+
245
+ print(f"\n\nResultados salvos em: {output_path}")
246
+
247
+ return results
248
+
249
+ if __name__ == "__main__":
250
+ main()
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Deduplication Script - Remove duplicate files keeping only the most recent
4
+ """
5
+
6
+ import os
7
+ import re
8
+ import shutil
9
+ from collections import defaultdict
10
+ from datetime import datetime
11
+
12
+ INBOX_PATH = "inbox"
13
+ BACKUP_PATH = os.path.join(INBOX_PATH, "_DEDUP_BACKUP")
14
+
15
+ def find_tagged_files():
16
+ """Find all files with [TAG-XXXX] format"""
17
+ tagged_files = defaultdict(list)
18
+ tag_pattern = re.compile(r'^\[([A-Z0-9\-]+)\]')
19
+
20
+ for root, dirs, files in os.walk(INBOX_PATH):
21
+ # Skip the backup folder itself
22
+ if "_DEDUP_BACKUP" in root:
23
+ continue
24
+
25
+ for filename in files:
26
+ if not filename.endswith('.txt'):
27
+ continue
28
+
29
+ match = tag_pattern.match(filename)
30
+ if match:
31
+ tag = match.group(1)
32
+ full_path = os.path.join(root, filename)
33
+ mtime = os.path.getmtime(full_path)
34
+ tagged_files[tag].append({
35
+ 'filename': filename,
36
+ 'path': full_path,
37
+ 'mtime': mtime,
38
+ 'rel_path': os.path.relpath(full_path, INBOX_PATH)
39
+ })
40
+
41
+ return tagged_files
42
+
43
+ def deduplicate(execute=False):
44
+ """Remove duplicates, keeping the most recent file for each TAG"""
45
+
46
+ print("=" * 70)
47
+ print("DEDUPLICAÇÃO DO INBOX - MEGA BRAIN")
48
+ print("=" * 70)
49
+ print(f"\nModo: {'EXECUTAR' if execute else 'PREVIEW (--execute para aplicar)'}")
50
+ print("=" * 70)
51
+
52
+ # Ensure backup folder exists
53
+ if execute and not os.path.exists(BACKUP_PATH):
54
+ os.makedirs(BACKUP_PATH)
55
+
56
+ tagged_files = find_tagged_files()
57
+
58
+ # Stats
59
+ total_tags = len(tagged_files)
60
+ duplicated_tags = 0
61
+ files_to_remove = 0
62
+
63
+ duplicates_list = []
64
+
65
+ for tag, files in sorted(tagged_files.items()):
66
+ if len(files) > 1:
67
+ duplicated_tags += 1
68
+ # Sort by mtime descending (most recent first)
69
+ files_sorted = sorted(files, key=lambda x: x['mtime'], reverse=True)
70
+ keep = files_sorted[0]
71
+ remove = files_sorted[1:]
72
+
73
+ print(f"\n[{tag}] {len(files)} cópias encontradas:")
74
+ print(f" ✓ MANTER: {keep['rel_path']}")
75
+ print(f" (modificado: {datetime.fromtimestamp(keep['mtime']).strftime('%Y-%m-%d %H:%M')})")
76
+
77
+ for f in remove:
78
+ files_to_remove += 1
79
+ print(f" ✗ REMOVER: {f['rel_path']}")
80
+ print(f" (modificado: {datetime.fromtimestamp(f['mtime']).strftime('%Y-%m-%d %H:%M')})")
81
+ duplicates_list.append({
82
+ 'tag': tag,
83
+ 'file': f,
84
+ 'keep': keep
85
+ })
86
+
87
+ print("\n" + "=" * 70)
88
+ print("RESUMO")
89
+ print("=" * 70)
90
+ print(f"Total de TAGs únicas: {total_tags}")
91
+ print(f"TAGs com duplicatas: {duplicated_tags}")
92
+ print(f"Arquivos a remover: {files_to_remove}")
93
+
94
+ if execute and duplicates_list:
95
+ print("\n" + "=" * 70)
96
+ print("EXECUTANDO REMOÇÃO")
97
+ print("=" * 70)
98
+
99
+ success = 0
100
+ errors = 0
101
+
102
+ for dup in duplicates_list:
103
+ src = dup['file']['path']
104
+ # Create subfolder in backup based on original relative path
105
+ rel_dir = os.path.dirname(dup['file']['rel_path'])
106
+ if rel_dir:
107
+ dest_dir = os.path.join(BACKUP_PATH, rel_dir)
108
+ else:
109
+ dest_dir = BACKUP_PATH
110
+
111
+ if not os.path.exists(dest_dir):
112
+ os.makedirs(dest_dir)
113
+
114
+ dest = os.path.join(dest_dir, dup['file']['filename'])
115
+
116
+ try:
117
+ shutil.move(src, dest)
118
+ print(f"✓ Movido: {dup['file']['rel_path']}")
119
+ success += 1
120
+ except Exception as e:
121
+ print(f"✗ Erro: {dup['file']['rel_path']} - {e}")
122
+ errors += 1
123
+
124
+ print("\n" + "=" * 70)
125
+ print("RESULTADO FINAL")
126
+ print("=" * 70)
127
+ print(f"✓ Arquivos movidos para backup: {success}")
128
+ print(f"✗ Erros: {errors}")
129
+ print(f"\nBackup em: {BACKUP_PATH}")
130
+
131
+ elif not execute:
132
+ print(f"\nExecute com: python3 deduplicate-inbox.py --execute")
133
+
134
+ return duplicated_tags, files_to_remove
135
+
136
+ if __name__ == "__main__":
137
+ import sys
138
+ execute = '--execute' in sys.argv
139
+ deduplicate(execute)