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,220 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
ENFORCE PLAN MODE HOOK v1.0.0
|
|
4
|
+
=============================
|
|
5
|
+
|
|
6
|
+
Hook: UserPromptSubmit
|
|
7
|
+
Propósito: Detecta quando o usuário solicita modificação de arquivos e
|
|
8
|
+
avisa se Plan Mode não foi ativado.
|
|
9
|
+
|
|
10
|
+
REGRA #13: PLAN MODE OBRIGATÓRIO PARA MODIFICAÇÃO DE ARQUIVOS
|
|
11
|
+
REGRA #29: WARN, NOT BLOCK (avisa, não bloqueia)
|
|
12
|
+
|
|
13
|
+
Criado: 2026-01-14
|
|
14
|
+
Autor: JARVIS
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import sys
|
|
19
|
+
import re
|
|
20
|
+
from datetime import datetime
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
# Keywords que indicam intenção de modificar arquivos
|
|
24
|
+
MODIFYING_KEYWORDS = [
|
|
25
|
+
# Português
|
|
26
|
+
"criar", "crie", "criando", "criação",
|
|
27
|
+
"atualizar", "atualize", "atualizando", "atualização",
|
|
28
|
+
"modificar", "modifique", "modificando", "modificação",
|
|
29
|
+
"implementar", "implemente", "implementando", "implementação",
|
|
30
|
+
"adicionar", "adicione", "adicionando", "adição",
|
|
31
|
+
"remover", "remova", "removendo", "remoção",
|
|
32
|
+
"deletar", "delete", "deletando",
|
|
33
|
+
"refatorar", "refatore", "refatorando", "refatoração",
|
|
34
|
+
"corrigir", "corrija", "corrigindo", "correção",
|
|
35
|
+
"fix", "fixing", "fixed",
|
|
36
|
+
"editar", "edite", "editando", "edição",
|
|
37
|
+
"escrever", "escreva", "escrevendo",
|
|
38
|
+
"gerar", "gere", "gerando", "geração",
|
|
39
|
+
"mudar", "mude", "mudando", "mudança",
|
|
40
|
+
|
|
41
|
+
# Inglês
|
|
42
|
+
"create", "creating", "creation",
|
|
43
|
+
"update", "updating",
|
|
44
|
+
"modify", "modifying", "modification",
|
|
45
|
+
"implement", "implementing", "implementation",
|
|
46
|
+
"add", "adding",
|
|
47
|
+
"remove", "removing", "removal",
|
|
48
|
+
"delete", "deleting", "deletion",
|
|
49
|
+
"refactor", "refactoring",
|
|
50
|
+
"edit", "editing",
|
|
51
|
+
"write", "writing",
|
|
52
|
+
"generate", "generating",
|
|
53
|
+
"change", "changing",
|
|
54
|
+
|
|
55
|
+
# Comandos específicos
|
|
56
|
+
"novo arquivo", "new file",
|
|
57
|
+
"nova feature", "new feature",
|
|
58
|
+
"novo hook", "new hook",
|
|
59
|
+
"nova skill", "new skill",
|
|
60
|
+
"novo agente", "new agent",
|
|
61
|
+
"bug fix", "bugfix",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
# Keywords que indicam exceções (não precisa Plan Mode)
|
|
65
|
+
EXCEPTION_KEYWORDS = [
|
|
66
|
+
# Leitura/consulta
|
|
67
|
+
"mostrar", "show", "exibir", "display",
|
|
68
|
+
"ler", "read", "leia",
|
|
69
|
+
"buscar", "search", "find", "procurar",
|
|
70
|
+
"verificar", "check", "verify",
|
|
71
|
+
"status", "estado",
|
|
72
|
+
"listar", "list",
|
|
73
|
+
"onde estamos", "where are we",
|
|
74
|
+
"o que é", "what is",
|
|
75
|
+
"como funciona", "how does",
|
|
76
|
+
"explique", "explain",
|
|
77
|
+
"descreva", "describe",
|
|
78
|
+
|
|
79
|
+
# Comandos slash (já são skills)
|
|
80
|
+
"/jarvis", "/status", "/save", "/resume",
|
|
81
|
+
"/conclave", "/verify", "/config",
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
# Log file
|
|
85
|
+
LOG_FILE = Path(__file__).parent.parent / "mission-control" / "plan_mode_warnings.jsonl"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def check_plan_mode_required(prompt: str) -> dict:
|
|
89
|
+
"""
|
|
90
|
+
Analisa o prompt para determinar se Plan Mode é necessário.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
dict com:
|
|
94
|
+
- required: bool (se Plan Mode é necessário)
|
|
95
|
+
- keywords_found: list (keywords de modificação encontradas)
|
|
96
|
+
- exception_found: str|None (exceção que foi encontrada)
|
|
97
|
+
- confidence: str (HIGH, MEDIUM, LOW)
|
|
98
|
+
"""
|
|
99
|
+
prompt_lower = prompt.lower()
|
|
100
|
+
|
|
101
|
+
# Verificar exceções primeiro
|
|
102
|
+
for exc in EXCEPTION_KEYWORDS:
|
|
103
|
+
if exc in prompt_lower:
|
|
104
|
+
return {
|
|
105
|
+
"required": False,
|
|
106
|
+
"keywords_found": [],
|
|
107
|
+
"exception_found": exc,
|
|
108
|
+
"confidence": "HIGH"
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
# Verificar keywords de modificação
|
|
112
|
+
found_keywords = []
|
|
113
|
+
for kw in MODIFYING_KEYWORDS:
|
|
114
|
+
# Usar word boundary para evitar falsos positivos
|
|
115
|
+
pattern = r'\b' + re.escape(kw) + r'\b'
|
|
116
|
+
if re.search(pattern, prompt_lower):
|
|
117
|
+
found_keywords.append(kw)
|
|
118
|
+
|
|
119
|
+
if not found_keywords:
|
|
120
|
+
return {
|
|
121
|
+
"required": False,
|
|
122
|
+
"keywords_found": [],
|
|
123
|
+
"exception_found": None,
|
|
124
|
+
"confidence": "HIGH"
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
# Determinar confiança baseado em quantidade de keywords
|
|
128
|
+
if len(found_keywords) >= 3:
|
|
129
|
+
confidence = "HIGH"
|
|
130
|
+
elif len(found_keywords) >= 2:
|
|
131
|
+
confidence = "MEDIUM"
|
|
132
|
+
else:
|
|
133
|
+
confidence = "LOW"
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
"required": True,
|
|
137
|
+
"keywords_found": found_keywords,
|
|
138
|
+
"exception_found": None,
|
|
139
|
+
"confidence": confidence
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def log_warning(prompt: str, analysis: dict):
|
|
144
|
+
"""Loga warning para auditoria."""
|
|
145
|
+
try:
|
|
146
|
+
LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
147
|
+
|
|
148
|
+
entry = {
|
|
149
|
+
"timestamp": datetime.now().isoformat(),
|
|
150
|
+
"hook": "enforce_plan_mode",
|
|
151
|
+
"prompt_preview": prompt[:200] + "..." if len(prompt) > 200 else prompt,
|
|
152
|
+
"keywords_found": analysis["keywords_found"],
|
|
153
|
+
"confidence": analysis["confidence"],
|
|
154
|
+
"action": "WARNING_ISSUED"
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
|
158
|
+
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
|
|
159
|
+
except Exception:
|
|
160
|
+
# Não falhar por erro de log
|
|
161
|
+
pass
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def main():
|
|
165
|
+
try:
|
|
166
|
+
# Ler input do hook
|
|
167
|
+
input_data = json.loads(sys.stdin.read())
|
|
168
|
+
|
|
169
|
+
# Extrair prompt do usuário
|
|
170
|
+
prompt = input_data.get("prompt", "")
|
|
171
|
+
|
|
172
|
+
if not prompt:
|
|
173
|
+
# Sem prompt, não há o que analisar
|
|
174
|
+
print(json.dumps({"continue": True}))
|
|
175
|
+
sys.exit(0)
|
|
176
|
+
|
|
177
|
+
# Analisar se Plan Mode é necessário
|
|
178
|
+
analysis = check_plan_mode_required(prompt)
|
|
179
|
+
|
|
180
|
+
if not analysis["required"]:
|
|
181
|
+
# Não precisa de Plan Mode
|
|
182
|
+
print(json.dumps({"continue": True}))
|
|
183
|
+
sys.exit(0)
|
|
184
|
+
|
|
185
|
+
# Plan Mode é necessário - emitir WARNING (não bloquear)
|
|
186
|
+
# REGRA #29: WARN, NOT BLOCK
|
|
187
|
+
|
|
188
|
+
log_warning(prompt, analysis)
|
|
189
|
+
|
|
190
|
+
# Construir mensagem de aviso
|
|
191
|
+
warning_msg = (
|
|
192
|
+
f"[PLAN MODE WARNING] Detectada intenção de modificação de arquivos. "
|
|
193
|
+
f"Keywords: {', '.join(analysis['keywords_found'][:5])}. "
|
|
194
|
+
f"Confiança: {analysis['confidence']}. "
|
|
195
|
+
f"REGRA #13 recomenda Plan Mode para modificações. "
|
|
196
|
+
f"Use Shift+Tab 2x para ativar ou digite 'plan mode'."
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
# Retornar com aviso (não bloqueia - exit 0)
|
|
200
|
+
print(json.dumps({
|
|
201
|
+
"continue": True,
|
|
202
|
+
"feedback": warning_msg
|
|
203
|
+
}))
|
|
204
|
+
sys.exit(0)
|
|
205
|
+
|
|
206
|
+
except json.JSONDecodeError:
|
|
207
|
+
# Input inválido - continuar silenciosamente
|
|
208
|
+
print(json.dumps({"continue": True}))
|
|
209
|
+
sys.exit(0)
|
|
210
|
+
except Exception as e:
|
|
211
|
+
# Erro inesperado - logar e continuar (não bloquear)
|
|
212
|
+
print(json.dumps({
|
|
213
|
+
"continue": True,
|
|
214
|
+
"warning": f"enforce_plan_mode hook error: {str(e)}"
|
|
215
|
+
}))
|
|
216
|
+
sys.exit(0) # Don't block on internal errors
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
if __name__ == "__main__":
|
|
220
|
+
main()
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
INBOX AGE ALERT HOOK - REGRA #7 ENFORCEMENT
|
|
4
|
+
============================================
|
|
5
|
+
|
|
6
|
+
Alerta sobre arquivos antigos no INBOX no inicio de cada sessao.
|
|
7
|
+
|
|
8
|
+
REGRA #7: INBOX E TEMPORARIO
|
|
9
|
+
- NAO PODE deixar arquivos no INBOX indefinidamente
|
|
10
|
+
- NAO PODE mover para INBOX sem plano de organizacao
|
|
11
|
+
- DEVE organizar cada arquivo que entra no INBOX
|
|
12
|
+
|
|
13
|
+
Este hook:
|
|
14
|
+
1. Executa no inicio de cada sessao (session_start hook)
|
|
15
|
+
2. Verifica arquivos no INBOX com mais de 3 dias
|
|
16
|
+
3. Se encontrar, gera alerta formatado para o JARVIS exibir
|
|
17
|
+
4. Loga em /logs/inbox_alerts.jsonl
|
|
18
|
+
|
|
19
|
+
Autor: JARVIS Autonomous System
|
|
20
|
+
Data: 2026-01-11
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import os
|
|
24
|
+
import json
|
|
25
|
+
import sys
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from datetime import datetime, timedelta
|
|
28
|
+
from typing import List, Dict, Optional
|
|
29
|
+
|
|
30
|
+
# ==============================================================================
|
|
31
|
+
# CONFIGURACAO
|
|
32
|
+
# ==============================================================================
|
|
33
|
+
|
|
34
|
+
PROJECT_ROOT = Path(os.environ.get('CLAUDE_PROJECT_DIR', '.'))
|
|
35
|
+
INBOX_PATH = PROJECT_ROOT / "inbox"
|
|
36
|
+
MAX_AGE_DAYS = 3
|
|
37
|
+
ALERT_LOG = PROJECT_ROOT / "logs" / "inbox_alerts.jsonl"
|
|
38
|
+
|
|
39
|
+
# Extensoes de arquivos para monitorar
|
|
40
|
+
MONITORED_EXTENSIONS = {".txt", ".md", ".docx", ".pdf", ".json", ".yaml", ".yml"}
|
|
41
|
+
|
|
42
|
+
# Pastas/prefixos a ignorar
|
|
43
|
+
IGNORE_PREFIXES = {"_", ".", "__"}
|
|
44
|
+
IGNORE_FOLDERS = {"_BACKUP", "_OLD", "_ARCHIVE", "__pycache__"}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# ==============================================================================
|
|
48
|
+
# FUNCOES PRINCIPAIS
|
|
49
|
+
# ==============================================================================
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_old_files(max_age_days: int = MAX_AGE_DAYS) -> List[Dict]:
|
|
53
|
+
"""
|
|
54
|
+
Retorna lista de arquivos mais velhos que max_age_days.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
max_age_days: Numero maximo de dias que um arquivo pode ficar no INBOX
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Lista de dicts com informacoes dos arquivos antigos
|
|
61
|
+
"""
|
|
62
|
+
old_files = []
|
|
63
|
+
cutoff = datetime.now() - timedelta(days=max_age_days)
|
|
64
|
+
|
|
65
|
+
if not INBOX_PATH.exists():
|
|
66
|
+
return []
|
|
67
|
+
|
|
68
|
+
for root, dirs, files in os.walk(INBOX_PATH):
|
|
69
|
+
# Ignorar pastas de backup e ocultas
|
|
70
|
+
dirs[:] = [
|
|
71
|
+
d
|
|
72
|
+
for d in dirs
|
|
73
|
+
if not any(d.startswith(p) for p in IGNORE_PREFIXES)
|
|
74
|
+
and d not in IGNORE_FOLDERS
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
for f in files:
|
|
78
|
+
# Ignorar arquivos ocultos
|
|
79
|
+
if any(f.startswith(p) for p in IGNORE_PREFIXES):
|
|
80
|
+
continue
|
|
81
|
+
|
|
82
|
+
# Verificar extensao
|
|
83
|
+
ext = Path(f).suffix.lower()
|
|
84
|
+
if ext not in MONITORED_EXTENSIONS:
|
|
85
|
+
continue
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
fpath = Path(root) / f
|
|
89
|
+
mtime = datetime.fromtimestamp(fpath.stat().st_mtime)
|
|
90
|
+
|
|
91
|
+
if mtime < cutoff:
|
|
92
|
+
# Calcular caminho relativo ao INBOX
|
|
93
|
+
rel_path = fpath.relative_to(INBOX_PATH)
|
|
94
|
+
folder = rel_path.parent if rel_path.parent != Path(".") else "ROOT"
|
|
95
|
+
|
|
96
|
+
old_files.append(
|
|
97
|
+
{
|
|
98
|
+
"path": str(fpath),
|
|
99
|
+
"relative_path": str(rel_path),
|
|
100
|
+
"name": f,
|
|
101
|
+
"age_days": (datetime.now() - mtime).days,
|
|
102
|
+
"folder": str(folder),
|
|
103
|
+
"size_kb": round(fpath.stat().st_size / 1024, 2),
|
|
104
|
+
"modified_at": mtime.isoformat(),
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
except (OSError, PermissionError) as e:
|
|
108
|
+
# Ignorar arquivos inacessiveis
|
|
109
|
+
continue
|
|
110
|
+
|
|
111
|
+
return sorted(old_files, key=lambda x: x["age_days"], reverse=True)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def count_by_folder(old_files: List[Dict]) -> Dict[str, int]:
|
|
115
|
+
"""Agrupa arquivos antigos por pasta."""
|
|
116
|
+
folder_counts = {}
|
|
117
|
+
for f in old_files:
|
|
118
|
+
folder = f["folder"]
|
|
119
|
+
folder_counts[folder] = folder_counts.get(folder, 0) + 1
|
|
120
|
+
return dict(sorted(folder_counts.items(), key=lambda x: x[1], reverse=True))
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def generate_alert(old_files: List[Dict]) -> str:
|
|
124
|
+
"""
|
|
125
|
+
Gera mensagem de alerta formatada no estilo JARVIS.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
old_files: Lista de arquivos antigos
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
String formatada com o alerta
|
|
132
|
+
"""
|
|
133
|
+
if not old_files:
|
|
134
|
+
return ""
|
|
135
|
+
|
|
136
|
+
folder_counts = count_by_folder(old_files)
|
|
137
|
+
total_size = sum(f["size_kb"] for f in old_files)
|
|
138
|
+
|
|
139
|
+
# Construir alerta visual
|
|
140
|
+
alert = f"""
|
|
141
|
+
+==============================================================================+
|
|
142
|
+
| REGRA #7 ALERTA - INBOX TEMPORARIO |
|
|
143
|
+
+==============================================================================+
|
|
144
|
+
|
|
145
|
+
ATENCAO, senhor. {len(old_files)} arquivo(s) no INBOX com mais de {MAX_AGE_DAYS} dias.
|
|
146
|
+
|
|
147
|
+
+------------------------------------------------------------------------------+
|
|
148
|
+
| METRICAS |
|
|
149
|
+
+------------------------------------------------------------------------------+
|
|
150
|
+
| Total de arquivos antigos: {len(old_files):>4} |
|
|
151
|
+
| Tamanho total: {total_size:>8.1f} KB |
|
|
152
|
+
| Arquivo mais antigo: {old_files[0]["age_days"]:>4} dias |
|
|
153
|
+
+------------------------------------------------------------------------------+
|
|
154
|
+
|
|
155
|
+
+------------------------------------------------------------------------------+
|
|
156
|
+
| POR PASTA |
|
|
157
|
+
+------------------------------------------------------------------------------+
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
for folder, count in list(folder_counts.items())[:8]:
|
|
161
|
+
folder_display = folder[:40] if len(folder) <= 40 else folder[:37] + "..."
|
|
162
|
+
alert += f"| {folder_display:<42} {count:>3} arquivo(s) |\n"
|
|
163
|
+
|
|
164
|
+
if len(folder_counts) > 8:
|
|
165
|
+
alert += f"| ... e mais {len(folder_counts) - 8} pastas |\n"
|
|
166
|
+
|
|
167
|
+
alert += """+------------------------------------------------------------------------------+
|
|
168
|
+
|
|
169
|
+
+------------------------------------------------------------------------------+
|
|
170
|
+
| ARQUIVOS MAIS ANTIGOS |
|
|
171
|
+
+------------------------------------------------------------------------------+
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
for f in old_files[:10]:
|
|
175
|
+
name_display = (
|
|
176
|
+
f["name"][:50] if len(f["name"]) <= 50 else f["name"][:47] + "..."
|
|
177
|
+
)
|
|
178
|
+
alert += f"| [{f['age_days']:>3}d] {name_display:<50} |\n"
|
|
179
|
+
|
|
180
|
+
if len(old_files) > 10:
|
|
181
|
+
alert += f"| ... e mais {len(old_files) - 10} arquivos |\n"
|
|
182
|
+
|
|
183
|
+
alert += """+------------------------------------------------------------------------------+
|
|
184
|
+
|
|
185
|
+
+------------------------------------------------------------------------------+
|
|
186
|
+
| ACAO RECOMENDADA |
|
|
187
|
+
+------------------------------------------------------------------------------+
|
|
188
|
+
| Executar: python3 SCRIPTS/organize_inbox_to_knowledge.py --execute |
|
|
189
|
+
| Ou: /inbox para ver lista completa |
|
|
190
|
+
+------------------------------------------------------------------------------+
|
|
191
|
+
|
|
192
|
+
REGRA #7: INBOX E TEMPORARIO - Organizar, nao acumular.
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
return alert
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def generate_summary(old_files: List[Dict]) -> str:
|
|
199
|
+
"""Gera resumo curto para o contexto do JARVIS."""
|
|
200
|
+
if not old_files:
|
|
201
|
+
return ""
|
|
202
|
+
|
|
203
|
+
return f"REGRA #7: {len(old_files)} arquivo(s) antigos no INBOX (>{MAX_AGE_DAYS} dias). Mais antigo: {old_files[0]['age_days']} dias."
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def log_alert(old_files: List[Dict]) -> bool:
|
|
207
|
+
"""
|
|
208
|
+
Loga alerta em jsonl para historico.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
old_files: Lista de arquivos antigos
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
True se logou com sucesso
|
|
215
|
+
"""
|
|
216
|
+
try:
|
|
217
|
+
# Garantir que diretorio existe
|
|
218
|
+
ALERT_LOG.parent.mkdir(parents=True, exist_ok=True)
|
|
219
|
+
|
|
220
|
+
log_entry = {
|
|
221
|
+
"timestamp": datetime.now().isoformat(),
|
|
222
|
+
"alert_type": "inbox_age",
|
|
223
|
+
"rule": "REGRA_7",
|
|
224
|
+
"total_files": len(old_files),
|
|
225
|
+
"max_age_days_threshold": MAX_AGE_DAYS,
|
|
226
|
+
"oldest_file_days": old_files[0]["age_days"] if old_files else 0,
|
|
227
|
+
"folders_affected": count_by_folder(old_files),
|
|
228
|
+
"files": old_files[:20], # Limitar a 20 arquivos no log
|
|
229
|
+
"action_suggested": "python3 SCRIPTS/organize_inbox_to_knowledge.py --execute",
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
with open(ALERT_LOG, "a", encoding="utf-8") as f:
|
|
233
|
+
f.write(json.dumps(log_entry, ensure_ascii=False) + "\n")
|
|
234
|
+
|
|
235
|
+
return True
|
|
236
|
+
|
|
237
|
+
except Exception as e:
|
|
238
|
+
# Nao bloquear execucao por falha de log
|
|
239
|
+
sys.stderr.write(f"[INBOX_ALERT] Erro ao logar: {e}\n")
|
|
240
|
+
return False
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def check_inbox_health() -> Dict:
|
|
244
|
+
"""
|
|
245
|
+
Verifica saude geral do INBOX.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
Dict com metricas de saude
|
|
249
|
+
"""
|
|
250
|
+
if not INBOX_PATH.exists():
|
|
251
|
+
return {"status": "error", "message": "INBOX path not found"}
|
|
252
|
+
|
|
253
|
+
total_files = 0
|
|
254
|
+
total_size = 0
|
|
255
|
+
|
|
256
|
+
for root, dirs, files in os.walk(INBOX_PATH):
|
|
257
|
+
# Ignorar pastas de backup
|
|
258
|
+
dirs[:] = [
|
|
259
|
+
d
|
|
260
|
+
for d in dirs
|
|
261
|
+
if not any(d.startswith(p) for p in IGNORE_PREFIXES)
|
|
262
|
+
and d not in IGNORE_FOLDERS
|
|
263
|
+
]
|
|
264
|
+
|
|
265
|
+
for f in files:
|
|
266
|
+
if any(f.startswith(p) for p in IGNORE_PREFIXES):
|
|
267
|
+
continue
|
|
268
|
+
try:
|
|
269
|
+
fpath = Path(root) / f
|
|
270
|
+
total_files += 1
|
|
271
|
+
total_size += fpath.stat().st_size
|
|
272
|
+
except:
|
|
273
|
+
continue
|
|
274
|
+
|
|
275
|
+
old_files = get_old_files()
|
|
276
|
+
|
|
277
|
+
# Determinar status
|
|
278
|
+
if len(old_files) == 0:
|
|
279
|
+
status = "healthy"
|
|
280
|
+
elif len(old_files) < 10:
|
|
281
|
+
status = "warning"
|
|
282
|
+
else:
|
|
283
|
+
status = "critical"
|
|
284
|
+
|
|
285
|
+
return {
|
|
286
|
+
"status": status,
|
|
287
|
+
"total_files": total_files,
|
|
288
|
+
"total_size_mb": round(total_size / (1024 * 1024), 2),
|
|
289
|
+
"old_files_count": len(old_files),
|
|
290
|
+
"oldest_file_days": old_files[0]["age_days"] if old_files else 0,
|
|
291
|
+
"threshold_days": MAX_AGE_DAYS,
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
# ==============================================================================
|
|
296
|
+
# INTEGRACAO COM SESSION_START
|
|
297
|
+
# ==============================================================================
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def get_session_context(old_files: List[Dict]) -> Dict:
|
|
301
|
+
"""
|
|
302
|
+
Retorna contexto para integracao com session_start.
|
|
303
|
+
|
|
304
|
+
Args:
|
|
305
|
+
old_files: Lista de arquivos antigos
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
Dict com contexto para o JARVIS
|
|
309
|
+
"""
|
|
310
|
+
if not old_files:
|
|
311
|
+
return {"has_alert": False, "summary": "", "alert": ""}
|
|
312
|
+
|
|
313
|
+
return {
|
|
314
|
+
"has_alert": True,
|
|
315
|
+
"summary": generate_summary(old_files),
|
|
316
|
+
"alert": generate_alert(old_files),
|
|
317
|
+
"file_count": len(old_files),
|
|
318
|
+
"oldest_days": old_files[0]["age_days"],
|
|
319
|
+
"health": check_inbox_health(),
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
# ==============================================================================
|
|
324
|
+
# MAIN
|
|
325
|
+
# ==============================================================================
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def main():
|
|
329
|
+
"""
|
|
330
|
+
Hook entry point for Claude Code SessionStart event.
|
|
331
|
+
Reads JSON from stdin, outputs JSON to stdout.
|
|
332
|
+
"""
|
|
333
|
+
try:
|
|
334
|
+
input_data = sys.stdin.read()
|
|
335
|
+
hook_input = json.loads(input_data) if input_data else {}
|
|
336
|
+
|
|
337
|
+
old_files = get_old_files()
|
|
338
|
+
|
|
339
|
+
if old_files:
|
|
340
|
+
log_alert(old_files)
|
|
341
|
+
summary = generate_summary(old_files)
|
|
342
|
+
print(json.dumps({'continue': True, 'feedback': summary}))
|
|
343
|
+
else:
|
|
344
|
+
print(json.dumps({'continue': True}))
|
|
345
|
+
|
|
346
|
+
except Exception:
|
|
347
|
+
print(json.dumps({'continue': True}))
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def cli_test():
|
|
351
|
+
"""CLI test mode - run directly for debugging."""
|
|
352
|
+
old_files = get_old_files()
|
|
353
|
+
if old_files:
|
|
354
|
+
alert = generate_alert(old_files)
|
|
355
|
+
print(alert)
|
|
356
|
+
else:
|
|
357
|
+
print("[INBOX_ALERT] No old files found. INBOX is clean.")
|
|
358
|
+
|
|
359
|
+
health = check_inbox_health()
|
|
360
|
+
print(f"\nHealth: {json.dumps(health, indent=2)}")
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
if __name__ == "__main__":
|
|
364
|
+
if len(sys.argv) > 1 and sys.argv[1] == '--test':
|
|
365
|
+
cli_test()
|
|
366
|
+
else:
|
|
367
|
+
main()
|