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.
- package/.claude/CLAUDE.md +155 -0
- package/.claude/commands/agents.md +161 -0
- package/.claude/commands/ask.md +117 -0
- package/.claude/commands/benchmark.md +224 -0
- package/.claude/commands/chat.md +343 -0
- package/.claude/commands/compare.md +116 -0
- package/.claude/commands/conclave.md +194 -0
- package/.claude/commands/config.md +133 -0
- package/.claude/commands/council.md +194 -0
- package/.claude/commands/create-agent.md +452 -0
- package/.claude/commands/debate.md +157 -0
- package/.claude/commands/documentation/create-architecture-documentation.md +175 -0
- package/.claude/commands/dossiers.md +180 -0
- package/.claude/commands/evolve.md +223 -0
- package/.claude/commands/extract-dna.md +170 -0
- package/.claude/commands/extract-knowledge.md +507 -0
- package/.claude/commands/inbox.md +296 -0
- package/.claude/commands/ingest-empresa.md +191 -0
- package/.claude/commands/ingest.md +182 -0
- package/.claude/commands/jarvis-briefing.md +67 -0
- package/.claude/commands/jarvis-control.md +169 -0
- package/.claude/commands/jarvis-full.md +181 -0
- package/.claude/commands/jarvis.md +212 -0
- package/.claude/commands/ler-drive.md +212 -0
- package/.claude/commands/log.md +158 -0
- package/.claude/commands/loop.md +133 -0
- package/.claude/commands/loops.md +73 -0
- package/.claude/commands/mission-autopilot.md +538 -0
- package/.claude/commands/mission.md +353 -0
- package/.claude/commands/process-inbox.md +148 -0
- package/.claude/commands/process-jarvis.md +3036 -0
- package/.claude/commands/process-video.md +131 -0
- package/.claude/commands/rag-search.md +78 -0
- package/.claude/commands/resume.md +33 -0
- package/.claude/commands/save.md +38 -0
- package/.claude/commands/scan-inbox.md +125 -0
- package/.claude/commands/setup.md +99 -0
- package/.claude/commands/system-digest.md +243 -0
- package/.claude/commands/verify.md +182 -0
- package/.claude/commands/view-dna.md +169 -0
- package/.claude/hooks/agent_doctor.py +433 -0
- package/.claude/hooks/agent_memory_persister.py +203 -0
- package/.claude/hooks/auto_formatter.py +158 -0
- package/.claude/hooks/checkpoint_writer.py +244 -0
- package/.claude/hooks/claude_md_guard.py +146 -0
- package/.claude/hooks/creation_validator.py +357 -0
- package/.claude/hooks/enforce_dual_location.py +501 -0
- package/.claude/hooks/enforce_plan_mode.py +220 -0
- package/.claude/hooks/inbox_age_alert.py +367 -0
- package/.claude/hooks/jarvis_briefing.py +506 -0
- package/.claude/hooks/ledger_updater.py +301 -0
- package/.claude/hooks/memory_hints_injector.py +251 -0
- package/.claude/hooks/memory_updater.py +202 -0
- package/.claude/hooks/multi_agent_hook.py +464 -0
- package/.claude/hooks/notification_system.py +120 -0
- package/.claude/hooks/pattern_analyzer.py +526 -0
- package/.claude/hooks/pending_tracker.py +188 -0
- package/.claude/hooks/post_batch_cascading.py +1740 -0
- package/.claude/hooks/post_output_validator.py +358 -0
- package/.claude/hooks/post_tool_use.py +120 -0
- package/.claude/hooks/post_write_validator.py +200 -0
- package/.claude/hooks/quality_watchdog.py +394 -0
- package/.claude/hooks/ralph_wiggum.py +277 -0
- package/.claude/hooks/session-source-sync.py +218 -0
- package/.claude/hooks/session_autosave_v2.py +1135 -0
- package/.claude/hooks/session_end.py +203 -0
- package/.claude/hooks/session_start.py +939 -0
- package/.claude/hooks/skill_indexer.py +48 -0
- package/.claude/hooks/skill_router.py +358 -0
- package/.claude/hooks/stop_hook_completeness.py +178 -0
- package/.claude/hooks/subagent_tracker.py +163 -0
- package/.claude/hooks/token_checkpoint.py +584 -0
- package/.claude/hooks/user_prompt_submit.py +125 -0
- package/.claude/rules/ANTHROPIC-STANDARDS.md +384 -0
- package/.claude/rules/CLAUDE-LITE.md +201 -0
- package/.claude/rules/RULE-GROUP-1.md +320 -0
- package/.claude/rules/RULE-GROUP-2.md +307 -0
- package/.claude/rules/RULE-GROUP-3.md +248 -0
- package/.claude/rules/RULE-GROUP-4.md +427 -0
- package/.claude/rules/RULE-GROUP-5.md +388 -0
- package/.claude/rules/RULE-GROUP-6.md +387 -0
- package/.claude/rules/logging.md +53 -0
- package/.claude/rules/mcp-governance.md +128 -0
- package/.claude/rules/pipeline.md +60 -0
- package/.claude/rules/state-management.md +93 -0
- package/.claude/scripts/apply-tags.py +77 -0
- package/.claude/scripts/batch-extract-transcriptions.py +132 -0
- package/.claude/scripts/build-complete-index.py +250 -0
- package/.claude/scripts/build-planilha-index.py +170 -0
- package/.claude/scripts/complete-tag-matching.py +250 -0
- package/.claude/scripts/deduplicate-inbox.py +139 -0
- package/.claude/scripts/docx-xml-extractor.py +141 -0
- package/.claude/scripts/extract-docx-text.py +58 -0
- package/.claude/scripts/extract-single-transcription.py +74 -0
- package/.claude/scripts/extract_docx_from_gdrive.py +77 -0
- package/.claude/scripts/organized-downloader.py +246 -0
- package/.claude/scripts/planilha-tagger.py +187 -0
- package/.claude/scripts/revert-tags.py +70 -0
- package/.claude/scripts/source-sync.py +265 -0
- package/.claude/scripts/tag-inbox-files.py +276 -0
- package/.claude/scripts/tag-inbox-v2.py +253 -0
- package/.claude/scripts/test-extraction.py +35 -0
- package/.claude/scripts/test-full-extraction.py +74 -0
- package/.claude/skills/00-SKILL-CREATOR/SKILL.md +186 -0
- package/.claude/skills/01-SKILL-DOCS-MEGABRAIN/SKILL.md +251 -0
- package/.claude/skills/02-SKILL-PYTHON-MEGABRAIN/SKILL.md +323 -0
- package/.claude/skills/03-SKILL-AGENT-CREATION/SKILL.md +374 -0
- package/.claude/skills/04-SKILL-KNOWLEDGE-EXTRACTION/SKILL.md +318 -0
- package/.claude/skills/05-SKILL-PIPELINE-JARVIS/SKILL.md +430 -0
- package/.claude/skills/06-SKILL-BRAINSTORMING/SKILL.md +72 -0
- package/.claude/skills/07-SKILL-DISPATCHING-PARALLEL-AGENTS/SKILL.md +193 -0
- package/.claude/skills/08-SKILL-EXECUTING-PLANS/SKILL.md +114 -0
- package/.claude/skills/09-SKILL-WRITING-PLANS/SKILL.md +184 -0
- package/.claude/skills/10-SKILL-VERIFICATION-BEFORE-COMPLETION/SKILL.md +130 -0
- package/.claude/skills/11-SKILL-USING-SUPERPOWERS/SKILL.md +105 -0
- package/.claude/skills/DETECTION-PROTOCOL.md +217 -0
- package/.claude/skills/README.md +240 -0
- package/.claude/skills/SKILL-REGISTRY.md +284 -0
- package/.claude/skills/SKILL-SUGGESTIONS.md +114 -0
- package/.claude/skills/_TEMPLATES/SKILL-WRITER-GUIDE.md +385 -0
- package/.claude/skills/chronicler/SKILL.md +146 -0
- package/.claude/skills/chronicler/chronicler_core.py +468 -0
- package/.claude/skills/code-review/SKILL.md +160 -0
- package/.claude/skills/council/SKILL.md +210 -0
- package/.claude/skills/executor/SKILL.md +161 -0
- package/.claude/skills/fase-2-5-tagging/SKILL.md +182 -0
- package/.claude/skills/feature-dev/SKILL.md +154 -0
- package/.claude/skills/finance-agent/SKILL.md +137 -0
- package/.claude/skills/frontend-design/SKILL.md +165 -0
- package/.claude/skills/gdrive-transcription-downloader/SKILL.md +249 -0
- package/.claude/skills/gemini-fallback/SKILL.md +67 -0
- package/.claude/skills/gemini-fallback/gemini_fetch.py +0 -0
- package/.claude/skills/gha/SKILL.md +96 -0
- package/.claude/skills/gha/gha_diagnostic.py +227 -0
- package/.claude/skills/github-workflow/SKILL.md +190 -0
- package/.claude/skills/hookify/SKILL.md +134 -0
- package/.claude/skills/hybrid-source-reading/SKILL.md +265 -0
- package/.claude/skills/jarvis/SKILL.md +546 -0
- package/.claude/skills/jarvis-briefing/SKILL.md +340 -0
- package/.claude/skills/ler-planilha/SKILL.md +281 -0
- package/.claude/skills/plugin-dev/SKILL.md +176 -0
- package/.claude/skills/pr-review-toolkit/SKILL.md +178 -0
- package/.claude/skills/resume/SKILL.md +61 -0
- package/.claude/skills/save/SKILL.md +87 -0
- package/.claude/skills/skill-writer/SKILL.md +153 -0
- package/.claude/skills/skill-writer/examples.md +191 -0
- package/.claude/skills/skill-writer/troubleshooting.md +205 -0
- package/.claude/skills/smart-download-tagger/SKILL.md +148 -0
- package/.claude/skills/source-sync/SKILL.md +240 -0
- package/.claude/skills/sync-docs/SKILL.md +193 -0
- package/.claude/skills/sync-docs/config.json +37 -0
- package/.claude/skills/sync-docs/gdrive_sync.py +358 -0
- package/.claude/skills/sync-docs/reauth.py +71 -0
- package/.claude/skills/talent-agent/SKILL.md +183 -0
- package/.claude/skills/verify/SKILL.md +154 -0
- package/.claude/skills/verify/verify_runner.py +0 -0
- package/.claude/skills/verify-6-levels/SKILL.md +234 -0
- package/.claude/templates/BATCH-LOG-TEMPLATE.md +221 -0
- package/.claudeignore +9 -0
- package/.gitattributes +4 -0
- package/.github/layer1-allowlist.txt +80 -0
- package/.github/layer2-manifest.txt +40 -0
- package/.gitignore +219 -0
- package/README.md +1210 -0
- package/agents/_templates/INDEX.md +741 -0
- package/agents/_templates/TEMPLATE-AGENT-MD-ULTRA-ROBUSTO-V3.md +2399 -0
- package/agents/boardroom/CHECKLIST-MASTER.md +281 -0
- package/agents/boardroom/INTEGRATION-GUIDE.md +406 -0
- package/agents/boardroom/README.md +238 -0
- package/agents/boardroom/config/BOARDROOM-CONFIG.md +186 -0
- package/agents/boardroom/config/TTS-INTEGRATION.md +258 -0
- package/agents/boardroom/config/VOICE-PROFILES.md +624 -0
- package/agents/boardroom/config/voice_mapping.json +128 -0
- package/agents/boardroom/scripts/audio_generator.py +375 -0
- package/agents/boardroom/scripts/audio_generator_edge.py +353 -0
- package/agents/boardroom/scripts/jarvis_boardroom_hook.py +415 -0
- package/agents/boardroom/scripts/notebooklm_generator.py +578 -0
- package/agents/boardroom/templates/EPISODE-TEMPLATE.md +367 -0
- package/agents/boardroom/templates/scene-templates/SCENE-AGENT-DEBATE.md +252 -0
- package/agents/boardroom/templates/scene-templates/SCENE-COUNCIL.md +270 -0
- package/agents/boardroom/templates/scene-templates/SCENE-DNA-CONSULTATION.md +126 -0
- package/agents/boardroom/templates/scene-templates/SCENE-QUESTION.md +174 -0
- package/agents/boardroom/workflows/WORKFLOW-AUDIO-GENERATION.md +421 -0
- package/agents/constitution/BASE-CONSTITUTION.md +254 -0
- package/agents/council/CRITIC.md +197 -0
- package/agents/council/DEVILS-ADVOCATE.md +274 -0
- package/agents/council/SYNTHESIZER.md +293 -0
- package/agents/council/advogado-do-diabo/AGENT.md +489 -0
- package/agents/council/advogado-do-diabo/SOUL.md +100 -0
- package/agents/council/critico-metodologico/AGENT.md +670 -0
- package/agents/council/critico-metodologico/SOUL.md +107 -0
- package/agents/council/sintetizador/AGENT.md +558 -0
- package/agents/council/sintetizador/SOUL.md +94 -0
- package/agents/persons/_example/AGENT-EXAMPLE.md +42 -0
- package/agents/persons/_example/DNA-EXAMPLE.yaml +61 -0
- package/agents/protocols/AGENT-COGNITION-PROTOCOL.md +779 -0
- package/agents/protocols/AGENT-INTEGRITY-PROTOCOL.md +692 -0
- package/agents/protocols/BATCH-VISUAL-PROTOCOL.md +841 -0
- package/agents/protocols/DNA-CONFIG-TEMPLATE.yaml +181 -0
- package/agents/protocols/DNA-EXTRACTION-PROTOCOL.md +370 -0
- package/agents/protocols/EPISTEMIC-PROTOCOL.md +333 -0
- package/agents/protocols/LOG-STRUCTURE-PROTOCOL.md +65 -0
- package/agents/protocols/MEMORY-PROTOCOL.md +567 -0
- package/agents/protocols/NARRATIVE-SYNTHESIS-PROTOCOL.md +278 -0
- package/agents/protocols/PHASE-4-VERIFICATION-CHECKPOINT.md +146 -0
- package/agents/protocols/SOUL-TEMPLATE.md +416 -0
- package/agents/protocols/TEMPLATE-EVOLUTION-PROTOCOL.md +544 -0
- package/agents/protocols/VISUAL-DIFF-PROTOCOL.md +159 -0
- package/agents/sua-empresa/README.md +44 -0
- package/agents/sua-empresa/_example/jds/EXAMPLE-JD.md +42 -0
- package/agents/sua-empresa/_example/org/EXAMPLE-ORG.md +32 -0
- package/agents/sua-empresa/_example/roles/EXAMPLE-ROLE.md +38 -0
- package/bin/cli.js +2 -0
- package/bin/lib/ascii-art.js +234 -0
- package/bin/lib/installer.js +402 -0
- package/bin/lib/setup-wizard.js +95 -0
- package/bin/lib/validate-email.js +109 -0
- package/bin/mega-brain.js +97 -0
- package/bin/push.js +342 -0
- package/bin/templates/env.example +38 -0
- package/inbox/.gitkeep +0 -0
- package/integrations/README.md +46 -0
- package/integrations/mcps/MCP-REGISTRY.md +56 -0
- package/integrations/mcps/excalidraw/CONFIG.md +56 -0
- package/integrations/mcps/gdrive/CONFIG.md +38 -0
- package/knowledge/dna/.gitkeep +0 -0
- package/knowledge/dossiers/persons/.gitkeep +0 -0
- package/knowledge/dossiers/persons/DOSSIER-EXAMPLE.md +49 -0
- package/knowledge/dossiers/system/.gitkeep +0 -0
- package/knowledge/dossiers/themes/.gitkeep +0 -0
- package/knowledge/playbooks/.gitkeep +0 -0
- package/knowledge/playbooks/PLAYBOOK-EXAMPLE.md +50 -0
- package/knowledge/sources/.gitkeep +0 -0
- package/logs/.gitkeep +0 -0
- package/package.json +128 -0
- package/processing/canonical/.gitkeep +0 -0
- package/processing/chunks/.gitkeep +0 -0
- package/processing/insights/.gitkeep +0 -0
- package/processing/narratives/.gitkeep +0 -0
- package/reference/CONSELHO.md +337 -0
- package/reference/CONTEXT7_README.md +28 -0
- package/reference/JARVIS-LOGGING-PROTOCOL.md +380 -0
- package/reference/QUICK-START.md +197 -0
- package/reference/README-RALPH-CASCATEAMENTO.md +207 -0
- package/reference/TEMPLATE-MASTER.md +727 -0
- package/reference/prds/prd-jarvis-mega-brain-v3.md +1305 -0
- package/reference/templates/phase5/IMPLEMENTATION-GUIDE.md +355 -0
- package/reference/templates/phase5/MOGA-BRAIN-PHASE5-TEMPLATES.md +1284 -0
- package/reference/templates/phase5/README.md +165 -0
- package/reference/workflow-claude-code-boris-cherny-continuous-claude.md +2232 -0
- package/system/database/001_moneyclub_buyers.sql +160 -0
- package/system/database/002_premium_token.sql +97 -0
- package/system/database/apply-migration.mjs +129 -0
- package/system/docs/MEGA-BRAIN-DEMO-COMPLETA.md +1226 -0
- package/system/docs/MEGA-BRAIN-MANIFESTO-COMPLETO.md +1054 -0
- package/system/docs/MOGA-BRAIN-EXPLICACAO-COMPLETA.md +791 -0
- package/system/docs/STRATEGIC-INTEGRATION-GUIDE.md +725 -0
- package/system/docs/architecture/01-system-context.md +136 -0
- package/system/docs/architecture/02-components.md +225 -0
- package/system/docs/architecture/03-data-flow.md +235 -0
- package/system/docs/architecture/04-integrations.md +283 -0
- package/system/docs/architecture/README.md +71 -0
- package/system/docs/architecture/diagrams/component-diagram.mmd +50 -0
- package/system/docs/architecture/diagrams/data-flow.mmd +39 -0
- package/system/docs/architecture/diagrams/system-overview.mmd +68 -0
- package/system/protocols/AGENT-AUTHORITY.md +217 -0
- package/system/protocols/CONSTITUICAO-BASE.md +115 -0
- package/system/protocols/CONSTITUTION.md +231 -0
- package/system/protocols/GOVERNANCE-MAP.md +123 -0
- package/system/protocols/HOOK-SECURITY-THREAT-MODEL.md +152 -0
- package/system/protocols/ORQUESTRACAO-PROTOCOL.md +215 -0
- package/system/protocols/_archive/CHUNKING-PROTOCOL.md +207 -0
- package/system/protocols/_archive/ENTITY-RESOLUTION-PROTOCOL.md +269 -0
- package/system/protocols/_archive/INSIGHT-EXTRACTION-PROTOCOL.md +257 -0
- package/system/protocols/_archive/NARRATIVE-SYNTHESIS-PROTOCOL.md +290 -0
- package/system/protocols/agents/AGENT-INTERACTION.md +315 -0
- package/system/protocols/agents/CORTEX-PROTOCOL.md +520 -0
- package/system/protocols/agents/EPISTEMIC-PROTOCOL.md +465 -0
- package/system/protocols/agents/MEMORY-PROTOCOL.md +366 -0
- package/system/protocols/agents/WAR-ROOM.md +355 -0
- package/system/protocols/company/COMPANY-DOCUMENT-PROTOCOL.md +793 -0
- package/system/protocols/company/COMPANY-ENRICHMENT-PROTOCOL.md +679 -0
- package/system/protocols/conclave/CONCLAVE-LOG-TEMPLATE-v2.md +309 -0
- package/system/protocols/conclave/CONCLAVE-PROTOCOL.md +518 -0
- package/system/protocols/conclave/DEBATE-DYNAMICS-CONFIG.yaml +322 -0
- package/system/protocols/conclave/DEBATE-DYNAMICS-PROTOCOL.md +613 -0
- package/system/protocols/conclave/DEBATE-PROTOCOL.md +323 -0
- package/system/protocols/council/COUNCIL-LOG-TEMPLATE-v2.md +309 -0
- package/system/protocols/council/COUNCIL-PROTOCOL.md +518 -0
- package/system/protocols/council/DEBATE-DYNAMICS-CONFIG.yaml +322 -0
- package/system/protocols/council/DEBATE-DYNAMICS-PROTOCOL.md +613 -0
- package/system/protocols/council/DEBATE-PROTOCOL.md +323 -0
- package/system/protocols/dna/DNA-EXTRACTION-PROTOCOL.md +1214 -0
- package/system/protocols/dna/ENRICHMENT-PROTOCOL.md +408 -0
- package/system/protocols/dna/REASONING-MODEL-PROTOCOL.md +331 -0
- package/system/protocols/pipeline/DOSSIER-COMPILATION-PROTOCOL.md +790 -0
- package/system/protocols/pipeline/NARRATIVE-METABOLISM-PROTOCOL.md +292 -0
- package/system/protocols/pipeline/PIPELINE-JARVIS-v2.1.md +606 -0
- package/system/protocols/pipeline/PROMPT-1.1-CHUNKING.md +154 -0
- package/system/protocols/pipeline/PROMPT-1.2-ENTITY-RESOLUTION.md +186 -0
- package/system/protocols/pipeline/PROMPT-2.1-DNA-TAGS-INCREMENT.md +208 -0
- package/system/protocols/pipeline/PROMPT-2.1-INSIGHT-EXTRACTION.md +191 -0
- package/system/protocols/pipeline/PROMPT-3.1-NARRATIVE-SYNTHESIS.md +331 -0
- package/system/protocols/pipeline/SOURCES-COMPILATION-PROTOCOL.md +340 -0
- package/system/protocols/system/AUTO-LOG-PROTOCOL.md +369 -0
- package/system/protocols/system/CHECKPOINT-ENFORCEMENT.md +176 -0
- package/system/protocols/system/ENFORCEMENT.md +435 -0
- package/system/protocols/system/LOG-TEMPLATES.md +1068 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Regras de Gerenciamento de Estado
|
|
2
|
+
|
|
3
|
+
## 🔴 MISSION-STATE.json é SAGRADO
|
|
4
|
+
|
|
5
|
+
**Localização:** `/.claude/mission-control/MISSION-STATE.json`
|
|
6
|
+
|
|
7
|
+
## 📖 Ler ANTES de
|
|
8
|
+
|
|
9
|
+
- Qualquer resposta ao usuário
|
|
10
|
+
- Qualquer processamento
|
|
11
|
+
- Qualquer sugestão de próxima ação
|
|
12
|
+
- Qualquer estimativa de tempo/progresso
|
|
13
|
+
|
|
14
|
+
## ✏️ Atualizar APÓS
|
|
15
|
+
|
|
16
|
+
- Completar um batch
|
|
17
|
+
- Mudar de source
|
|
18
|
+
- Mudar de fase
|
|
19
|
+
- Iniciar sessão
|
|
20
|
+
- Encerrar sessão
|
|
21
|
+
- Qualquer ação significativa
|
|
22
|
+
|
|
23
|
+
## 📋 Campos críticos
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"current_state": {
|
|
28
|
+
"phase": 4, // 1-5
|
|
29
|
+
"phase_name": "Pipeline",
|
|
30
|
+
"status": "IN_PROGRESS", // NOT_STARTED, IN_PROGRESS, COMPLETE
|
|
31
|
+
"source_code": "CG",
|
|
32
|
+
"source_name": "Cole Gordon",
|
|
33
|
+
"batch_current": 3,
|
|
34
|
+
"batch_total": 8,
|
|
35
|
+
"percent_complete": 37.5
|
|
36
|
+
},
|
|
37
|
+
"session": {
|
|
38
|
+
"id": "SESSION-2026-01-08-001",
|
|
39
|
+
"started_at": "2026-01-08T14:00:00Z",
|
|
40
|
+
"last_action_at": "2026-01-08T14:35:00Z",
|
|
41
|
+
"is_active": true
|
|
42
|
+
},
|
|
43
|
+
"next_action": {
|
|
44
|
+
"description": "Processar BATCH-004 Cole Gordon",
|
|
45
|
+
"phase": 4,
|
|
46
|
+
"details": "Arquivos CG_sales-8.txt até CG_sales-15.txt"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 🎯 Posição EXATA sempre
|
|
52
|
+
|
|
53
|
+
❌ ERRADO: "Estamos na fase 4"
|
|
54
|
+
❌ ERRADO: "Processando Cole Gordon"
|
|
55
|
+
❌ ERRADO: "Quase terminando"
|
|
56
|
+
|
|
57
|
+
✅ CERTO: "Fase 4, Batch 3/8, Cole Gordon, arquivo 8/23"
|
|
58
|
+
✅ CERTO: "37.5% da fase 4 completa"
|
|
59
|
+
|
|
60
|
+
## 🔄 Ao iniciar sessão
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# 1. Ler estado
|
|
64
|
+
cat /.claude/mission-control/MISSION-STATE.json
|
|
65
|
+
|
|
66
|
+
# 2. Atualizar sessão
|
|
67
|
+
# session.id = novo ID
|
|
68
|
+
# session.started_at = agora
|
|
69
|
+
# session.is_active = true
|
|
70
|
+
|
|
71
|
+
# 3. Exibir status visual
|
|
72
|
+
# 4. Perguntar se continua
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 🔄 Ao encerrar sessão
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# 1. Atualizar estado
|
|
79
|
+
# session.last_action_at = agora
|
|
80
|
+
# session.is_active = false
|
|
81
|
+
|
|
82
|
+
# 2. Criar HANDOFF
|
|
83
|
+
# /logs/handoffs/HANDOFF-LATEST.md
|
|
84
|
+
|
|
85
|
+
# 3. Salvar estado
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## ⚠️ Nunca
|
|
89
|
+
|
|
90
|
+
- Modificar sem ler primeiro
|
|
91
|
+
- Deixar session.is_active = true ao sair
|
|
92
|
+
- Esquecer de atualizar next_action
|
|
93
|
+
- Deixar percent_complete desatualizado
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Apply Tags Script - Renames matched files with TAG prefix
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import json
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
def apply_tags(execute=False):
|
|
11
|
+
# Load matching results
|
|
12
|
+
with open('.claude/mission-control/COMPLETE-TAG-MATCHING.json') as f:
|
|
13
|
+
data = json.load(f)
|
|
14
|
+
|
|
15
|
+
matches = data['matches']
|
|
16
|
+
|
|
17
|
+
print("=" * 60)
|
|
18
|
+
print("APLICAÇÃO DE TAGS - DE-PARA COMPLETO")
|
|
19
|
+
print("=" * 60)
|
|
20
|
+
print(f"\nTotal arquivos com match: {len(matches)}")
|
|
21
|
+
print(f"Modo: {'EXECUTAR' if execute else 'PREVIEW (--execute para aplicar)'}")
|
|
22
|
+
print("=" * 60)
|
|
23
|
+
print()
|
|
24
|
+
|
|
25
|
+
success = 0
|
|
26
|
+
errors = 0
|
|
27
|
+
skipped = 0
|
|
28
|
+
|
|
29
|
+
for m in sorted(matches, key=lambda x: x['tag']):
|
|
30
|
+
old_path = m['full_path']
|
|
31
|
+
tag = m['tag']
|
|
32
|
+
filename = m['filename']
|
|
33
|
+
|
|
34
|
+
# Skip if file already has a tag
|
|
35
|
+
if filename.startswith('[') and ']' in filename:
|
|
36
|
+
print(f"⏭️ SKIP (já tem tag): {filename}")
|
|
37
|
+
skipped += 1
|
|
38
|
+
continue
|
|
39
|
+
|
|
40
|
+
# Build new filename with tag
|
|
41
|
+
new_filename = f"[{tag}] {filename}"
|
|
42
|
+
new_path = os.path.join(os.path.dirname(old_path), new_filename)
|
|
43
|
+
|
|
44
|
+
print(f"[{tag}] {m['rel_path']}")
|
|
45
|
+
print(f" → {new_filename}")
|
|
46
|
+
|
|
47
|
+
if execute:
|
|
48
|
+
try:
|
|
49
|
+
if os.path.exists(old_path):
|
|
50
|
+
os.rename(old_path, new_path)
|
|
51
|
+
print(f" ✓ RENOMEADO")
|
|
52
|
+
success += 1
|
|
53
|
+
else:
|
|
54
|
+
print(f" ✗ ERRO: Arquivo não encontrado")
|
|
55
|
+
errors += 1
|
|
56
|
+
except Exception as e:
|
|
57
|
+
print(f" ✗ ERRO: {e}")
|
|
58
|
+
errors += 1
|
|
59
|
+
print()
|
|
60
|
+
|
|
61
|
+
print("=" * 60)
|
|
62
|
+
print("RESUMO")
|
|
63
|
+
print("=" * 60)
|
|
64
|
+
if execute:
|
|
65
|
+
print(f"✓ Renomeados com sucesso: {success}")
|
|
66
|
+
print(f"⏭️ Pulados (já tem tag): {skipped}")
|
|
67
|
+
print(f"✗ Erros: {errors}")
|
|
68
|
+
else:
|
|
69
|
+
print(f"📋 Prontos para renomear: {len(matches) - skipped}")
|
|
70
|
+
print(f"⏭️ Já com tag: {skipped}")
|
|
71
|
+
print(f"\nExecute com: python3 apply-tags.py --execute")
|
|
72
|
+
|
|
73
|
+
return success, skipped, errors
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
execute = '--execute' in sys.argv
|
|
77
|
+
apply_tags(execute)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Batch Extraction Script for Mega Brain Transcriptions
|
|
4
|
+
------------------------------------------------------
|
|
5
|
+
Este script extrai transcrições de arquivos .docx no Google Drive
|
|
6
|
+
e salva como arquivos .txt com TAG no INBOX.
|
|
7
|
+
|
|
8
|
+
Uso:
|
|
9
|
+
python batch-extract-transcriptions.py <base64_file> <tag> <output_name> <output_dir>
|
|
10
|
+
|
|
11
|
+
O arquivo base64_file deve conter o conteúdo base64 puro do .docx
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import base64
|
|
15
|
+
import subprocess
|
|
16
|
+
import tempfile
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
import json
|
|
20
|
+
|
|
21
|
+
def decode_and_extract(base64_content: str) -> str:
|
|
22
|
+
"""
|
|
23
|
+
Decode base64 docx content and extract text using pandoc
|
|
24
|
+
"""
|
|
25
|
+
# Remove whitespace/newlines from base64
|
|
26
|
+
base64_clean = base64_content.strip().replace('\n', '').replace(' ', '')
|
|
27
|
+
|
|
28
|
+
# Decode base64
|
|
29
|
+
try:
|
|
30
|
+
docx_bytes = base64.b64decode(base64_clean)
|
|
31
|
+
except Exception as e:
|
|
32
|
+
return f"[ERROR] Base64 decode failed: {e}"
|
|
33
|
+
|
|
34
|
+
# Create temp file
|
|
35
|
+
with tempfile.NamedTemporaryFile(suffix='.docx', delete=False) as tmp:
|
|
36
|
+
tmp.write(docx_bytes)
|
|
37
|
+
tmp_path = tmp.name
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
# Check if pandoc is available
|
|
41
|
+
result = subprocess.run(
|
|
42
|
+
['which', 'pandoc'],
|
|
43
|
+
capture_output=True,
|
|
44
|
+
text=True
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
if result.returncode != 0:
|
|
48
|
+
# Try using unzip to extract document.xml directly
|
|
49
|
+
import zipfile
|
|
50
|
+
try:
|
|
51
|
+
with zipfile.ZipFile(tmp_path, 'r') as z:
|
|
52
|
+
if 'word/document.xml' in z.namelist():
|
|
53
|
+
xml_content = z.read('word/document.xml').decode('utf-8')
|
|
54
|
+
# Basic XML text extraction
|
|
55
|
+
import re
|
|
56
|
+
text = re.sub(r'<[^>]+>', '', xml_content)
|
|
57
|
+
text = re.sub(r'\s+', ' ', text)
|
|
58
|
+
return text.strip()
|
|
59
|
+
except Exception as e:
|
|
60
|
+
return f"[ERROR] ZIP extraction failed: {e}"
|
|
61
|
+
|
|
62
|
+
# Use pandoc to extract text
|
|
63
|
+
result = subprocess.run(
|
|
64
|
+
['pandoc', tmp_path, '-t', 'plain', '--wrap=none'],
|
|
65
|
+
capture_output=True,
|
|
66
|
+
text=True,
|
|
67
|
+
check=True
|
|
68
|
+
)
|
|
69
|
+
return result.stdout
|
|
70
|
+
|
|
71
|
+
except subprocess.CalledProcessError as e:
|
|
72
|
+
return f"[ERROR] Pandoc failed: {e.stderr}"
|
|
73
|
+
except Exception as e:
|
|
74
|
+
return f"[ERROR] Extraction failed: {e}"
|
|
75
|
+
finally:
|
|
76
|
+
# Clean up
|
|
77
|
+
try:
|
|
78
|
+
os.unlink(tmp_path)
|
|
79
|
+
except:
|
|
80
|
+
pass
|
|
81
|
+
|
|
82
|
+
def save_transcription(text: str, tag: str, name: str, output_dir: str) -> str:
|
|
83
|
+
"""
|
|
84
|
+
Save extracted text to file with proper naming
|
|
85
|
+
"""
|
|
86
|
+
# Clean filename
|
|
87
|
+
clean_name = name.replace('.docx', '').replace('.mp4', '').strip()
|
|
88
|
+
# Remove leading numbers and dashes if duplicated
|
|
89
|
+
clean_name = clean_name.strip(' -.')
|
|
90
|
+
|
|
91
|
+
filename = f"[{tag}] {clean_name}.txt"
|
|
92
|
+
filepath = os.path.join(output_dir, filename)
|
|
93
|
+
|
|
94
|
+
with open(filepath, 'w', encoding='utf-8') as f:
|
|
95
|
+
f.write(text)
|
|
96
|
+
|
|
97
|
+
return filepath
|
|
98
|
+
|
|
99
|
+
def process_from_file(base64_file: str, tag: str, name: str, output_dir: str) -> dict:
|
|
100
|
+
"""
|
|
101
|
+
Process a single file from base64 content file
|
|
102
|
+
"""
|
|
103
|
+
with open(base64_file, 'r') as f:
|
|
104
|
+
base64_content = f.read()
|
|
105
|
+
|
|
106
|
+
text = decode_and_extract(base64_content)
|
|
107
|
+
|
|
108
|
+
if text.startswith('[ERROR]'):
|
|
109
|
+
return {'success': False, 'error': text, 'tag': tag}
|
|
110
|
+
|
|
111
|
+
filepath = save_transcription(text, tag, name, output_dir)
|
|
112
|
+
return {
|
|
113
|
+
'success': True,
|
|
114
|
+
'filepath': filepath,
|
|
115
|
+
'tag': tag,
|
|
116
|
+
'chars': len(text),
|
|
117
|
+
'words': len(text.split())
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if __name__ == "__main__":
|
|
121
|
+
if len(sys.argv) < 5:
|
|
122
|
+
print("Usage: python batch-extract-transcriptions.py <base64_file> <tag> <output_name> <output_dir>")
|
|
123
|
+
print("Example: python batch-extract-transcriptions.py /tmp/content.b64 JM-0003 'Your Prospects Are Lying' ./INBOX/")
|
|
124
|
+
sys.exit(1)
|
|
125
|
+
|
|
126
|
+
base64_file = sys.argv[1]
|
|
127
|
+
tag = sys.argv[2]
|
|
128
|
+
name = sys.argv[3]
|
|
129
|
+
output_dir = sys.argv[4]
|
|
130
|
+
|
|
131
|
+
result = process_from_file(base64_file, tag, name, output_dir)
|
|
132
|
+
print(json.dumps(result, indent=2))
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
BUILD COMPLETE INDEX - Extrai dados de todos os JSONs da planilha
|
|
4
|
+
Mega Brain - Sistema de Inteligência de Negócios
|
|
5
|
+
|
|
6
|
+
Processa os arquivos JSON salvos das chamadas do Google Sheets API
|
|
7
|
+
e constrói o índice completo nome→TAG
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
12
|
+
import json
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
# Configurações
|
|
17
|
+
TOOL_RESULTS_PATH = "" # Set to your Claude tool-results path
|
|
18
|
+
OUTPUT_PATH = ".claude/mission-control/PLANILHA-INDEX.json"
|
|
19
|
+
SCHEMA_PATH = ".claude/mission-control/SPREADSHEET-SCHEMA.json"
|
|
20
|
+
|
|
21
|
+
# Mapeamento de sheet -> coluna da TAG (índice baseado em 0 da row)
|
|
22
|
+
SHEET_CONFIG = {
|
|
23
|
+
"Jeremy Haynes Sales Training": {"tag_col": -1, "prefix": "JH-ST"}, # última coluna
|
|
24
|
+
"Jeremy Haynes Inner Circle": {"tag_col": -1, "prefix": "JH-IC"},
|
|
25
|
+
"Inner Circle Weekly Group Call Recordings": {"tag_col": -1, "prefix": "JH-WK"},
|
|
26
|
+
"Agency Blueprint": {"tag_col": -1, "prefix": "AOBA"},
|
|
27
|
+
"Cold Video Pitch": {"tag_col": -1, "prefix": "PCVP"},
|
|
28
|
+
"Land Your First Agency Client": {"tag_col": -1, "prefix": "LYFC"},
|
|
29
|
+
"Marketer Mindset Masterclass": {"tag_col": -1, "prefix": "MMM"},
|
|
30
|
+
"30 Days Challenge": {"tag_col": -1, "prefix": "30DC"},
|
|
31
|
+
"Scale The Agency": {"tag_col": -1, "prefix": "STA"},
|
|
32
|
+
"Ultra High Ticket Closer": {"tag_col": -1, "prefix": "UHTC"},
|
|
33
|
+
"Jeremy Miner": {"tag_col": -1, "prefix": "JM"},
|
|
34
|
+
"The Scalable Company": {"tag_col": -1, "prefix": "TSC"},
|
|
35
|
+
"Sales Training BR": {"tag_col": -1, "prefix": "EDC"},
|
|
36
|
+
"Alex Hormozi": {"tag_col": -1, "prefix": "AH"},
|
|
37
|
+
"Jeremy Haynes Program": {"tag_col": -1, "prefix": "CA"},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def normalize_name(name):
|
|
41
|
+
"""Normaliza nome para matching."""
|
|
42
|
+
if not name:
|
|
43
|
+
return ""
|
|
44
|
+
# Lowercase
|
|
45
|
+
name = str(name).lower()
|
|
46
|
+
# Remove extensão
|
|
47
|
+
name = re.sub(r'\.(mp4|docx|txt|pdf)$', '', name, flags=re.IGNORECASE)
|
|
48
|
+
# Remove número inicial
|
|
49
|
+
name = re.sub(r'^\d+[\s\.\-]+', '', name)
|
|
50
|
+
# Remove (1), (2), etc
|
|
51
|
+
name = re.sub(r'\s*\(\d+\)\s*', '', name)
|
|
52
|
+
# Remove youtube references
|
|
53
|
+
name = re.sub(r'\[youtube\.com[^\]]*\]', '', name)
|
|
54
|
+
# Remove caracteres especiais
|
|
55
|
+
name = re.sub(r'[^\w\s]', ' ', name)
|
|
56
|
+
name = re.sub(r'\s+', ' ', name).strip()
|
|
57
|
+
return name
|
|
58
|
+
|
|
59
|
+
def is_valid_tag(tag, prefix=None):
|
|
60
|
+
"""Verifica se é uma TAG válida."""
|
|
61
|
+
if not tag:
|
|
62
|
+
return False
|
|
63
|
+
tag = str(tag).strip()
|
|
64
|
+
|
|
65
|
+
# Formato básico: XXX-NNNN ou XX-XXX-NNNN
|
|
66
|
+
if not re.match(r'^[\w-]+-\d{4}$', tag):
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
# Se prefix especificado, verificar
|
|
70
|
+
if prefix and not tag.startswith(prefix):
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
return True
|
|
74
|
+
|
|
75
|
+
def extract_from_row(row, sheet_name):
|
|
76
|
+
"""Extrai nome e TAG de uma row."""
|
|
77
|
+
if not row:
|
|
78
|
+
return None, None
|
|
79
|
+
|
|
80
|
+
# Extrair valores
|
|
81
|
+
values = []
|
|
82
|
+
for cell in row:
|
|
83
|
+
if isinstance(cell, dict):
|
|
84
|
+
values.append(cell.get('value', ''))
|
|
85
|
+
else:
|
|
86
|
+
values.append(str(cell) if cell else '')
|
|
87
|
+
|
|
88
|
+
if not values:
|
|
89
|
+
return None, None
|
|
90
|
+
|
|
91
|
+
# Nome está na primeira coluna
|
|
92
|
+
name = values[0] if values else None
|
|
93
|
+
|
|
94
|
+
# TAG está na última coluna (geralmente)
|
|
95
|
+
# Procurar TAG no formato correto de trás para frente
|
|
96
|
+
tag = None
|
|
97
|
+
for v in reversed(values):
|
|
98
|
+
if v and is_valid_tag(v):
|
|
99
|
+
tag = v
|
|
100
|
+
break
|
|
101
|
+
|
|
102
|
+
return name, tag
|
|
103
|
+
|
|
104
|
+
def process_json_file(filepath):
|
|
105
|
+
"""Processa um arquivo JSON do Google Sheets."""
|
|
106
|
+
entries = []
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
with open(filepath, 'r', encoding='utf-8') as f:
|
|
110
|
+
raw_data = json.load(f)
|
|
111
|
+
|
|
112
|
+
# Formato: [{type: text, text: JSON_STRING}]
|
|
113
|
+
if isinstance(raw_data, list) and raw_data:
|
|
114
|
+
if isinstance(raw_data[0], dict) and 'text' in raw_data[0]:
|
|
115
|
+
data = json.loads(raw_data[0]['text'])
|
|
116
|
+
else:
|
|
117
|
+
data = raw_data
|
|
118
|
+
else:
|
|
119
|
+
data = raw_data
|
|
120
|
+
|
|
121
|
+
# Processar dados
|
|
122
|
+
if isinstance(data, list):
|
|
123
|
+
# Lista de sheets
|
|
124
|
+
for sheet_data in data:
|
|
125
|
+
if isinstance(sheet_data, dict) and 'sheetName' in sheet_data:
|
|
126
|
+
sheet_name = sheet_data['sheetName']
|
|
127
|
+
rows = sheet_data.get('data', [])
|
|
128
|
+
|
|
129
|
+
for row in rows:
|
|
130
|
+
name, tag = extract_from_row(row, sheet_name)
|
|
131
|
+
if name and tag:
|
|
132
|
+
entries.append({
|
|
133
|
+
'original_name': name,
|
|
134
|
+
'normalized': normalize_name(name),
|
|
135
|
+
'tag': tag,
|
|
136
|
+
'sheet': sheet_name
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
elif isinstance(data, dict):
|
|
140
|
+
# Pode ser formato valueRanges ou outro
|
|
141
|
+
if 'valueRanges' in data:
|
|
142
|
+
for range_data in data.get('valueRanges', []):
|
|
143
|
+
# Extrair sheet name do range
|
|
144
|
+
range_str = range_data.get('range', '')
|
|
145
|
+
sheet_name = range_str.split('!')[0].strip("'")
|
|
146
|
+
|
|
147
|
+
for row in range_data.get('values', []):
|
|
148
|
+
name, tag = extract_from_row(row, sheet_name)
|
|
149
|
+
if name and tag:
|
|
150
|
+
entries.append({
|
|
151
|
+
'original_name': name,
|
|
152
|
+
'normalized': normalize_name(name),
|
|
153
|
+
'tag': tag,
|
|
154
|
+
'sheet': sheet_name
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
except Exception as e:
|
|
158
|
+
print(f" Erro processando {filepath}: {e}")
|
|
159
|
+
|
|
160
|
+
return entries
|
|
161
|
+
|
|
162
|
+
def main():
|
|
163
|
+
print("=" * 60)
|
|
164
|
+
print("BUILD COMPLETE INDEX")
|
|
165
|
+
print("=" * 60)
|
|
166
|
+
print()
|
|
167
|
+
|
|
168
|
+
all_entries = []
|
|
169
|
+
sheets_found = set()
|
|
170
|
+
|
|
171
|
+
# 1. Processar todos os arquivos JSON em tool-results
|
|
172
|
+
print("[1/3] Processando arquivos JSON...")
|
|
173
|
+
|
|
174
|
+
if os.path.exists(TOOL_RESULTS_PATH):
|
|
175
|
+
json_files = list(Path(TOOL_RESULTS_PATH).glob("mcp-gdrive*.txt"))
|
|
176
|
+
print(f" {len(json_files)} arquivos encontrados")
|
|
177
|
+
|
|
178
|
+
for filepath in json_files:
|
|
179
|
+
entries = process_json_file(filepath)
|
|
180
|
+
if entries:
|
|
181
|
+
print(f" {filepath.name}: {len(entries)} entradas")
|
|
182
|
+
all_entries.extend(entries)
|
|
183
|
+
sheets_found.update(e['sheet'] for e in entries)
|
|
184
|
+
else:
|
|
185
|
+
print(f" AVISO: Pasta não encontrada: {TOOL_RESULTS_PATH}")
|
|
186
|
+
|
|
187
|
+
# 2. Remover duplicatas (manter mais recente por tag)
|
|
188
|
+
print()
|
|
189
|
+
print("[2/3] Removendo duplicatas...")
|
|
190
|
+
|
|
191
|
+
seen_tags = {}
|
|
192
|
+
unique_entries = []
|
|
193
|
+
|
|
194
|
+
for entry in all_entries:
|
|
195
|
+
tag = entry['tag']
|
|
196
|
+
if tag not in seen_tags:
|
|
197
|
+
seen_tags[tag] = entry
|
|
198
|
+
unique_entries.append(entry)
|
|
199
|
+
else:
|
|
200
|
+
# Se mesma tag, manter a entrada com nome mais completo
|
|
201
|
+
existing = seen_tags[tag]
|
|
202
|
+
if len(entry['original_name']) > len(existing['original_name']):
|
|
203
|
+
seen_tags[tag] = entry
|
|
204
|
+
unique_entries = [e for e in unique_entries if e['tag'] != tag]
|
|
205
|
+
unique_entries.append(entry)
|
|
206
|
+
|
|
207
|
+
print(f" De {len(all_entries)} para {len(unique_entries)} entradas únicas")
|
|
208
|
+
|
|
209
|
+
# 3. Ordenar por sheet e tag
|
|
210
|
+
unique_entries.sort(key=lambda x: (x['sheet'], x['tag']))
|
|
211
|
+
|
|
212
|
+
# 4. Salvar índice
|
|
213
|
+
print()
|
|
214
|
+
print("[3/3] Salvando índice...")
|
|
215
|
+
|
|
216
|
+
index = {
|
|
217
|
+
'version': '2.0',
|
|
218
|
+
'timestamp': datetime.now().isoformat(),
|
|
219
|
+
'total_entries': len(unique_entries),
|
|
220
|
+
'sheets_processed': sorted(list(sheets_found)),
|
|
221
|
+
'entries': unique_entries
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
with open(OUTPUT_PATH, 'w', encoding='utf-8') as f:
|
|
225
|
+
json.dump(index, f, ensure_ascii=False, indent=2)
|
|
226
|
+
|
|
227
|
+
print(f" Salvo em: {OUTPUT_PATH}")
|
|
228
|
+
print()
|
|
229
|
+
|
|
230
|
+
# 5. Resumo por sheet
|
|
231
|
+
print("=" * 60)
|
|
232
|
+
print("RESUMO POR SHEET")
|
|
233
|
+
print("=" * 60)
|
|
234
|
+
|
|
235
|
+
sheet_counts = {}
|
|
236
|
+
for entry in unique_entries:
|
|
237
|
+
sheet = entry['sheet']
|
|
238
|
+
sheet_counts[sheet] = sheet_counts.get(sheet, 0) + 1
|
|
239
|
+
|
|
240
|
+
for sheet, count in sorted(sheet_counts.items()):
|
|
241
|
+
print(f" {sheet}: {count} TAGs")
|
|
242
|
+
|
|
243
|
+
print()
|
|
244
|
+
print(f"TOTAL: {len(unique_entries)} entradas")
|
|
245
|
+
print("=" * 60)
|
|
246
|
+
|
|
247
|
+
return index
|
|
248
|
+
|
|
249
|
+
if __name__ == '__main__':
|
|
250
|
+
main()
|