mega-brain-ai 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.antigravity/README.md +46 -0
- package/.antigravity/rules/.gitkeep +0 -0
- package/.antigravity/rules/mega-brain.md +39 -0
- package/.claude/CLAUDE.md +172 -0
- package/.claude/agents.yaml +44 -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 +196 -0
- package/.claude/commands/config.md +133 -0
- package/.claude/commands/create-agent.md +467 -0
- package/.claude/commands/debate.md +159 -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 +172 -0
- package/.claude/commands/extract-knowledge.md +507 -0
- package/.claude/commands/gsd/add-phase.md +43 -0
- package/.claude/commands/gsd/add-tests.md +41 -0
- package/.claude/commands/gsd/add-todo.md +47 -0
- package/.claude/commands/gsd/audit-milestone.md +36 -0
- package/.claude/commands/gsd/check-todos.md +45 -0
- package/.claude/commands/gsd/cleanup.md +18 -0
- package/.claude/commands/gsd/complete-milestone.md +136 -0
- package/.claude/commands/gsd/debug.md +167 -0
- package/.claude/commands/gsd/discuss-phase.md +83 -0
- package/.claude/commands/gsd/execute-phase.md +41 -0
- package/.claude/commands/gsd/health.md +22 -0
- package/.claude/commands/gsd/help.md +22 -0
- package/.claude/commands/gsd/insert-phase.md +32 -0
- package/.claude/commands/gsd/join-discord.md +18 -0
- package/.claude/commands/gsd/list-phase-assumptions.md +46 -0
- package/.claude/commands/gsd/map-codebase.md +71 -0
- package/.claude/commands/gsd/new-milestone.md +44 -0
- package/.claude/commands/gsd/new-project.md +42 -0
- package/.claude/commands/gsd/pause-work.md +38 -0
- package/.claude/commands/gsd/plan-milestone-gaps.md +34 -0
- package/.claude/commands/gsd/plan-phase.md +45 -0
- package/.claude/commands/gsd/progress.md +24 -0
- package/.claude/commands/gsd/quick.md +41 -0
- package/.claude/commands/gsd/reapply-patches.md +110 -0
- package/.claude/commands/gsd/remove-phase.md +31 -0
- package/.claude/commands/gsd/research-phase.md +189 -0
- package/.claude/commands/gsd/resume-work.md +40 -0
- package/.claude/commands/gsd/set-profile.md +34 -0
- package/.claude/commands/gsd/settings.md +36 -0
- package/.claude/commands/gsd/update.md +37 -0
- package/.claude/commands/gsd/verify-work.md +38 -0
- package/.claude/commands/inbox.md +296 -0
- package/.claude/commands/ingest-empresa.md +191 -0
- package/.claude/commands/ingest.md +183 -0
- package/.claude/commands/jarvis-briefing.md +67 -0
- package/.claude/commands/jarvis-control.md +169 -0
- package/.claude/commands/jarvis-full.md +182 -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/get-shit-done/VERSION +1 -0
- package/.claude/get-shit-done/bin/gsd-tools.cjs +588 -0
- package/.claude/get-shit-done/bin/lib/commands.cjs +553 -0
- package/.claude/get-shit-done/bin/lib/config.cjs +162 -0
- package/.claude/get-shit-done/bin/lib/core.cjs +411 -0
- package/.claude/get-shit-done/bin/lib/frontmatter.cjs +299 -0
- package/.claude/get-shit-done/bin/lib/init.cjs +710 -0
- package/.claude/get-shit-done/bin/lib/milestone.cjs +216 -0
- package/.claude/get-shit-done/bin/lib/phase.cjs +871 -0
- package/.claude/get-shit-done/bin/lib/roadmap.cjs +298 -0
- package/.claude/get-shit-done/bin/lib/state.cjs +679 -0
- package/.claude/get-shit-done/bin/lib/template.cjs +222 -0
- package/.claude/get-shit-done/bin/lib/verify.cjs +773 -0
- package/.claude/get-shit-done/references/checkpoints.md +776 -0
- package/.claude/get-shit-done/references/continuation-format.md +249 -0
- package/.claude/get-shit-done/references/decimal-phase-calculation.md +65 -0
- package/.claude/get-shit-done/references/git-integration.md +248 -0
- package/.claude/get-shit-done/references/git-planning-commit.md +38 -0
- package/.claude/get-shit-done/references/model-profile-resolution.md +34 -0
- package/.claude/get-shit-done/references/model-profiles.md +92 -0
- package/.claude/get-shit-done/references/phase-argument-parsing.md +61 -0
- package/.claude/get-shit-done/references/planning-config.md +196 -0
- package/.claude/get-shit-done/references/questioning.md +145 -0
- package/.claude/get-shit-done/references/tdd.md +263 -0
- package/.claude/get-shit-done/references/ui-brand.md +160 -0
- package/.claude/get-shit-done/references/verification-patterns.md +612 -0
- package/.claude/get-shit-done/templates/DEBUG.md +164 -0
- package/.claude/get-shit-done/templates/UAT.md +247 -0
- package/.claude/get-shit-done/templates/VALIDATION.md +76 -0
- package/.claude/get-shit-done/templates/codebase/architecture.md +255 -0
- package/.claude/get-shit-done/templates/codebase/concerns.md +310 -0
- package/.claude/get-shit-done/templates/codebase/conventions.md +307 -0
- package/.claude/get-shit-done/templates/codebase/integrations.md +280 -0
- package/.claude/get-shit-done/templates/codebase/stack.md +186 -0
- package/.claude/get-shit-done/templates/codebase/structure.md +285 -0
- package/.claude/get-shit-done/templates/codebase/testing.md +480 -0
- package/.claude/get-shit-done/templates/config.json +37 -0
- package/.claude/get-shit-done/templates/context.md +283 -0
- package/.claude/get-shit-done/templates/continue-here.md +78 -0
- package/.claude/get-shit-done/templates/debug-subagent-prompt.md +91 -0
- package/.claude/get-shit-done/templates/discovery.md +146 -0
- package/.claude/get-shit-done/templates/milestone-archive.md +123 -0
- package/.claude/get-shit-done/templates/milestone.md +115 -0
- package/.claude/get-shit-done/templates/phase-prompt.md +569 -0
- package/.claude/get-shit-done/templates/planner-subagent-prompt.md +117 -0
- package/.claude/get-shit-done/templates/project.md +184 -0
- package/.claude/get-shit-done/templates/requirements.md +231 -0
- package/.claude/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
- package/.claude/get-shit-done/templates/research-project/FEATURES.md +147 -0
- package/.claude/get-shit-done/templates/research-project/PITFALLS.md +200 -0
- package/.claude/get-shit-done/templates/research-project/STACK.md +120 -0
- package/.claude/get-shit-done/templates/research-project/SUMMARY.md +170 -0
- package/.claude/get-shit-done/templates/research.md +552 -0
- package/.claude/get-shit-done/templates/retrospective.md +54 -0
- package/.claude/get-shit-done/templates/roadmap.md +202 -0
- package/.claude/get-shit-done/templates/state.md +176 -0
- package/.claude/get-shit-done/templates/summary-complex.md +59 -0
- package/.claude/get-shit-done/templates/summary-minimal.md +41 -0
- package/.claude/get-shit-done/templates/summary-standard.md +48 -0
- package/.claude/get-shit-done/templates/summary.md +248 -0
- package/.claude/get-shit-done/templates/user-setup.md +311 -0
- package/.claude/get-shit-done/templates/verification-report.md +322 -0
- package/.claude/get-shit-done/workflows/add-phase.md +111 -0
- package/.claude/get-shit-done/workflows/add-tests.md +350 -0
- package/.claude/get-shit-done/workflows/add-todo.md +157 -0
- package/.claude/get-shit-done/workflows/audit-milestone.md +297 -0
- package/.claude/get-shit-done/workflows/check-todos.md +176 -0
- package/.claude/get-shit-done/workflows/cleanup.md +152 -0
- package/.claude/get-shit-done/workflows/complete-milestone.md +763 -0
- package/.claude/get-shit-done/workflows/diagnose-issues.md +219 -0
- package/.claude/get-shit-done/workflows/discovery-phase.md +289 -0
- package/.claude/get-shit-done/workflows/discuss-phase.md +542 -0
- package/.claude/get-shit-done/workflows/execute-phase.md +449 -0
- package/.claude/get-shit-done/workflows/execute-plan.md +448 -0
- package/.claude/get-shit-done/workflows/health.md +156 -0
- package/.claude/get-shit-done/workflows/help.md +489 -0
- package/.claude/get-shit-done/workflows/insert-phase.md +129 -0
- package/.claude/get-shit-done/workflows/list-phase-assumptions.md +178 -0
- package/.claude/get-shit-done/workflows/map-codebase.md +315 -0
- package/.claude/get-shit-done/workflows/new-milestone.md +382 -0
- package/.claude/get-shit-done/workflows/new-project.md +1116 -0
- package/.claude/get-shit-done/workflows/pause-work.md +122 -0
- package/.claude/get-shit-done/workflows/plan-milestone-gaps.md +274 -0
- package/.claude/get-shit-done/workflows/plan-phase.md +569 -0
- package/.claude/get-shit-done/workflows/progress.md +381 -0
- package/.claude/get-shit-done/workflows/quick.md +453 -0
- package/.claude/get-shit-done/workflows/remove-phase.md +154 -0
- package/.claude/get-shit-done/workflows/research-phase.md +73 -0
- package/.claude/get-shit-done/workflows/resume-project.md +306 -0
- package/.claude/get-shit-done/workflows/set-profile.md +80 -0
- package/.claude/get-shit-done/workflows/settings.md +213 -0
- package/.claude/get-shit-done/workflows/transition.md +544 -0
- package/.claude/get-shit-done/workflows/update.md +219 -0
- package/.claude/get-shit-done/workflows/verify-phase.md +242 -0
- package/.claude/get-shit-done/workflows/verify-work.md +569 -0
- package/.claude/gsd-file-manifest.json +144 -0
- package/.claude/hooks/agent_creation_trigger.py +168 -0
- package/.claude/hooks/agent_index_updater.py +255 -0
- package/.claude/hooks/agent_memory_persister.py +203 -0
- package/.claude/hooks/claude_md_agent_sync.py +162 -0
- package/.claude/hooks/claude_md_guard.py +154 -0
- package/.claude/hooks/continuous_save.py +414 -0
- package/.claude/hooks/creation_validator.py +360 -0
- package/.claude/hooks/enforce_dual_location.py +501 -0
- package/.claude/hooks/enforce_plan_mode.py +220 -0
- package/.claude/hooks/gsd-check-update.js +62 -0
- package/.claude/hooks/gsd-context-monitor.js +122 -0
- package/.claude/hooks/gsd-statusline.js +108 -0
- package/.claude/hooks/inbox_age_alert.py +367 -0
- package/.claude/hooks/ledger_updater.py +303 -0
- package/.claude/hooks/memory_hints_injector.py +251 -0
- package/.claude/hooks/memory_updater.py +202 -0
- package/.claude/hooks/notification_system.py +115 -0
- package/.claude/hooks/pending_tracker.py +188 -0
- package/.claude/hooks/pipeline_checkpoint.py +583 -0
- package/.claude/hooks/post_batch_cascading.py +1740 -0
- package/.claude/hooks/post_tool_use.py +120 -0
- package/.claude/hooks/quality_watchdog.py +394 -0
- package/.claude/hooks/ralph_wiggum.py +286 -0
- package/.claude/hooks/session-source-sync.py +223 -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 +187 -0
- package/.claude/hooks/user_prompt_submit.py +125 -0
- package/.claude/package.json +1 -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/RULE-GSD-MANDATORY.md +106 -0
- package/.claude/rules/agent-cognition.md +779 -0
- package/.claude/rules/agent-integrity.md +692 -0
- package/.claude/rules/epistemic-standards.md +333 -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/jarvis_orchestrator.py +5 -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/scripts/validate_cascading_integrity.py +409 -0
- package/.claude/settings.json +215 -0
- package/.claude/skills/DETECTION-PROTOCOL.md +217 -0
- package/.claude/skills/README.md +240 -0
- package/.claude/skills/SKILL-REGISTRY.md +283 -0
- package/.claude/skills/SKILL-SUGGESTIONS.md +114 -0
- package/.claude/skills/_TEMPLATES/SKILL-WRITER-GUIDE.md +385 -0
- package/.claude/skills/agent-creation/SKILL.md +374 -0
- package/.claude/skills/ask-company/SKILL.md +198 -0
- package/.claude/skills/brainstorming/SKILL.md +72 -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/convert-to-company-docs/SKILL.md +68 -0
- package/.claude/skills/convert-to-company-docs/convert.py +532 -0
- package/.claude/skills/dispatching-parallel-agents/SKILL.md +193 -0
- package/.claude/skills/docs-megabrain/SKILL.md +251 -0
- package/.claude/skills/executing-plans/SKILL.md +114 -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/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/knowledge-extraction/SKILL.md +318 -0
- package/.claude/skills/ler-planilha/SKILL.md +281 -0
- package/.claude/skills/pipeline-jarvis/SKILL.md +430 -0
- package/.claude/skills/plugin-dev/SKILL.md +176 -0
- package/.claude/skills/pr-review-toolkit/SKILL.md +178 -0
- package/.claude/skills/process-company-inbox/SKILL.md +183 -0
- package/.claude/skills/python-megabrain/SKILL.md +323 -0
- package/.claude/skills/resume/SKILL.md +61 -0
- package/.claude/skills/save/SKILL.md +87 -0
- package/.claude/skills/skill-creator-internal/SKILL.md +186 -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/using-superpowers/SKILL.md +105 -0
- package/.claude/skills/verification-before-completion/SKILL.md +130 -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/skills/writing-plans/SKILL.md +184 -0
- package/.claude/templates/BATCH-LOG-TEMPLATE.md +221 -0
- package/.claudeignore +9 -0
- package/.cursor/agents.yaml +44 -0
- package/.cursor/rules/mega-brain.md +39 -0
- package/.gitattributes +19 -0
- package/.github/CODEOWNERS +8 -0
- package/.github/ISSUE_TEMPLATE/agent.md +96 -0
- package/.github/ISSUE_TEMPLATE/bug.md +67 -0
- package/.github/ISSUE_TEMPLATE/feature.md +56 -0
- package/.github/ISSUE_TEMPLATE/pipeline.md +70 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +30 -0
- package/.github/assets/banner.svg +152 -0
- package/.github/assets/logo-dark.svg +79 -0
- package/.github/assets/social-preview.png +0 -0
- package/.github/layer1-allowlist.txt +196 -0
- package/.github/layer2-manifest.txt +42 -0
- package/.github/layer3-manifest.txt +94 -0
- package/.github/workflows/claude-code-pr.yml +198 -0
- package/.github/workflows/claude-code-review.yml +57 -0
- package/.github/workflows/claude.yml +76 -0
- package/.github/workflows/publish-pro.yml +72 -0
- package/.github/workflows/publish.yml +86 -0
- package/.github/workflows/verification.yml +251 -0
- package/.gitignore +244 -0
- package/.gitleaks.toml +118 -0
- package/.windsurf/agents.yaml +44 -0
- package/.windsurf/rules/mega-brain.md +39 -0
- package/CONTRIBUTING.md +62 -0
- package/QUICK-START.md +231 -0
- package/README.md +168 -0
- package/agents/AGENT-INDEX.yaml +107 -0
- package/agents/MASTER-AGENT.md +612 -0
- package/agents/README.md +48 -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/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/conclave/CRITIC.md +197 -0
- package/agents/conclave/DEVILS-ADVOCATE.md +274 -0
- package/agents/conclave/README.md +35 -0
- package/agents/conclave/SYNTHESIZER.md +293 -0
- package/agents/conclave/advogado-do-diabo/AGENT.md +502 -0
- package/agents/conclave/advogado-do-diabo/SOUL.md +100 -0
- package/agents/conclave/critico-metodologico/AGENT.md +683 -0
- package/agents/conclave/critico-metodologico/SOUL.md +107 -0
- package/agents/conclave/sintetizador/AGENT.md +571 -0
- package/agents/conclave/sintetizador/SOUL.md +94 -0
- package/agents/constitution/BASE-CONSTITUTION.md +254 -0
- package/agents/persona-registry.yaml +300 -0
- package/agents/sua-empresa/.gitkeep +0 -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/artifacts/README.md +11 -0
- package/artifacts/canonical/.gitkeep +0 -0
- package/artifacts/chunks/.gitkeep +0 -0
- package/artifacts/insights/.gitkeep +0 -0
- package/artifacts/narratives/.gitkeep +0 -0
- package/bin/cli.js +2 -0
- package/bin/lib/ascii-art.js +202 -0
- package/bin/lib/feature-gate.js +46 -0
- package/bin/lib/installer.js +593 -0
- package/bin/lib/license.js +59 -0
- package/bin/lib/pro-commands.js +75 -0
- package/bin/lib/setup-wizard.js +547 -0
- package/bin/lib/validate-email.js +113 -0
- package/bin/mega-brain.js +136 -0
- package/bin/pre-publish-gate.js +229 -0
- package/bin/push.js +1056 -0
- package/bin/templates/env.example +27 -0
- package/bin/utils/pro-detector.js +50 -0
- package/bin/validate-package.js +190 -0
- package/core/__init__.py +2 -0
- package/core/glossary/INDEX.md +63 -0
- package/core/glossary/digital.md +243 -0
- package/core/glossary/finance.md +49 -0
- package/core/glossary/marketing.md +69 -0
- package/core/glossary/operations.md +50 -0
- package/core/glossary/sales.md +690 -0
- package/core/intelligence/__init__.py +41 -0
- package/core/intelligence/agent_trigger.py +468 -0
- package/core/intelligence/audit_layers.py +491 -0
- package/core/intelligence/autonomous_processor.py +796 -0
- package/core/intelligence/bootstrap_registry.py +550 -0
- package/core/intelligence/business_model_detector.py +476 -0
- package/core/intelligence/dossier_trigger.py +336 -0
- package/core/intelligence/entity_normalizer.py +565 -0
- package/core/intelligence/org_chain_detector.py +411 -0
- package/core/intelligence/review_dashboard.py +338 -0
- package/core/intelligence/role_detector.py +855 -0
- package/core/intelligence/session_autosave.py +46 -0
- package/core/intelligence/skill_generator.py +601 -0
- package/core/intelligence/sow_generator.py +711 -0
- package/core/intelligence/sync_package_files.py +504 -0
- package/core/intelligence/task_orchestrator.py +780 -0
- package/core/intelligence/theme_analyzer.py +562 -0
- package/core/intelligence/tool_discovery.py +432 -0
- package/core/intelligence/validate_json_integrity.py +106 -0
- package/core/intelligence/validate_layers.py +310 -0
- package/core/intelligence/verify_classifications.py +94 -0
- package/core/intelligence/viability_scorer.py +592 -0
- package/core/jarvis/02-JARVIS-SOUL.md +390 -0
- package/core/jarvis/03-JARVIS-DNA.yaml +312 -0
- package/core/jarvis/AGENT.md +191 -0
- package/core/jarvis/agent-creator/AGENT.md +199 -0
- package/core/jarvis/agent-creator/SOUL.md +82 -0
- package/core/jarvis/agent-creator/tasks/create-agent.md +133 -0
- package/core/jarvis/agent-creator/tasks/sync-agents.md +100 -0
- package/core/jarvis/agent-creator/workflows/wf-create-agent.yaml +110 -0
- package/core/jarvis/agent-creator/workflows/wf-pipeline-trigger.yaml +111 -0
- package/core/jarvis/autonomous/benchmark/AGENT.md +347 -0
- package/core/jarvis/autonomous/benchmark/SOUL.md +78 -0
- package/core/jarvis/autonomous/critic/AGENT.md +324 -0
- package/core/jarvis/autonomous/critic/SOUL.md +78 -0
- package/core/jarvis/autonomous/evolver/AGENT.md +294 -0
- package/core/jarvis/autonomous/evolver/SOUL.md +85 -0
- package/core/jarvis/autonomous/playbook-generator/AGENT.md +399 -0
- package/core/jarvis/autonomous/playbook-generator/SOUL.md +80 -0
- package/core/patterns/_ROLE_PATTERNS.yaml +547 -0
- package/core/patterns/quality_gates.yaml +259 -0
- package/core/patterns/trigger_config.yaml +193 -0
- package/core/schemas/SCHEMA-INDEX.md +94 -0
- package/core/schemas/canonical-map.schema.json +98 -0
- package/core/schemas/chunks-state.schema.json +131 -0
- package/core/schemas/decisions-registry.schema.json +120 -0
- package/core/schemas/file-registry.schema.json +69 -0
- package/core/schemas/insights-state.schema.json +111 -0
- package/core/schemas/narratives-state.schema.json +150 -0
- package/core/tasks/CHANGELOG.md +55 -0
- package/core/tasks/TASK-REGISTRY.md +113 -0
- package/core/tasks/_templates/task-tmpl.md +105 -0
- package/core/tasks/analyze-themes.md +84 -0
- package/core/tasks/detect-role.md +82 -0
- package/core/tasks/extract-dna.md +114 -0
- package/core/tasks/normalize-entities.md +82 -0
- package/core/tasks/process-batch.md +111 -0
- package/core/tasks/validate-cascade.md +105 -0
- package/core/templates/README.md +27 -0
- package/core/templates/agents/dna-config-template.yaml +181 -0
- package/core/templates/agents/enrichment-protocol.md +408 -0
- package/core/templates/agents/memory-template.md +567 -0
- package/core/templates/agents/reasoning-model.md +331 -0
- package/core/templates/agents/soul-template.md +416 -0
- package/core/templates/agents/template-evolution.md +544 -0
- package/core/templates/debates/CONCLAVE-LOG-TEMPLATE-v2.md +309 -0
- package/core/templates/debates/conclave-log-template.md +309 -0
- package/core/templates/debates/conclave-protocol.md +518 -0
- package/core/templates/debates/debate-dynamics-config.yaml +322 -0
- package/core/templates/debates/debate-dynamics.md +613 -0
- package/core/templates/debates/debate-protocol.md +323 -0
- package/core/templates/logs/LOG-TEMPLATES.md +1068 -0
- package/core/templates/logs/batch-visual-template.md +841 -0
- package/core/templates/logs/log-structure.md +65 -0
- package/core/templates/logs/visual-diff.md +159 -0
- package/core/templates/phases/dossier-compilation.md +790 -0
- package/core/templates/phases/narrative-metabolism.md +292 -0
- package/core/templates/phases/narrative-synthesis.md +278 -0
- package/core/templates/phases/phase4-checkpoint.md +146 -0
- package/core/templates/phases/prompt-1.1-chunking.md +154 -0
- package/core/templates/phases/prompt-1.2-entity-resolution.md +186 -0
- package/core/templates/phases/prompt-2.1-dna-tags.md +208 -0
- package/core/templates/phases/prompt-2.1-insight-extraction.md +191 -0
- package/core/templates/phases/prompt-3.1-narrative.md +331 -0
- package/core/templates/phases/sources-compilation.md +340 -0
- package/core/workflows/PIPELINE-JARVIS-DOCS.md +606 -0
- package/core/workflows/wf-conclave.yaml +139 -0
- package/core/workflows/wf-extract-dna.yaml +158 -0
- package/core/workflows/wf-ingest.yaml +88 -0
- package/core/workflows/wf-pipeline-full.yaml +138 -0
- package/docs/API-KEYS-GUIDE.md +372 -0
- package/docs/INTEGRATION-POINTS.md +501 -0
- package/docs/LAYERS.md +403 -0
- package/docs/PLAN-MODE-PROTOCOL.md +388 -0
- package/docs/RESTORE-AND-INDEX.md +203 -0
- package/docs/TAG-RESOLVER-IMPLEMENTATION.md +597 -0
- package/docs/conselho.md +337 -0
- package/docs/context7-readme.md +28 -0
- package/docs/jarvis-logging-protocol.md +380 -0
- package/docs/pipeline-completa-v4.md +1315 -0
- package/docs/prompts/meta_agente_mapeamento_processos.md +297 -0
- package/docs/quick-start.md +197 -0
- package/docs/readme-ralph-cascateamento.md +207 -0
- package/docs/template-master.md +727 -0
- package/docs/templates/phase5/IMPLEMENTATION-GUIDE.md +355 -0
- package/docs/templates/phase5/MOGA-BRAIN-PHASE5-TEMPLATES.md +1284 -0
- package/docs/templates/phase5/README.md +165 -0
- package/docs/workflow-continuous-claude.md +2232 -0
- package/inbox/.gitkeep +0 -0
- package/inbox/README.md +15 -0
- package/knowledge/NAVIGATION-MAP.json +292 -0
- package/knowledge/README.md +11 -0
- package/knowledge/dna/.gitkeep +0 -0
- package/knowledge/dossiers/persons/.gitkeep +0 -0
- package/knowledge/dossiers/system/.gitkeep +0 -0
- package/knowledge/dossiers/themes/.gitkeep +0 -0
- package/knowledge/playbooks/.gitkeep +0 -0
- package/knowledge/sources/.gitkeep +0 -0
- package/logs/.gitkeep +0 -0
- package/logs/README.md +11 -0
- package/package.json +180 -0
- package/requirements.txt +4 -0
package/bin/push.js
ADDED
|
@@ -0,0 +1,1056 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mega Brain - Smart Multi-Layer Push System v2.0
|
|
5
|
+
*
|
|
6
|
+
* Pushes content to the appropriate git remote based on layer selection:
|
|
7
|
+
* Layer 1 (public) → Community content, respects .gitignore → remote "origin"
|
|
8
|
+
* Layer 2 (premium) → Layer 1 + premium manifest paths → remote "premium"
|
|
9
|
+
* Layer 3 (backup) → Everything, no filtering → remote "backup"
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* mega-brain push Interactive layer selection
|
|
13
|
+
* mega-brain push --layer 1 Direct push to Layer 1
|
|
14
|
+
* mega-brain push --layer 2 Direct push to Layer 2
|
|
15
|
+
* mega-brain push --layer 3 Direct push to Layer 3
|
|
16
|
+
* mega-brain push --dry-run Show what would happen without executing
|
|
17
|
+
* mega-brain push --message "x" Commit message (skips prompt)
|
|
18
|
+
*
|
|
19
|
+
* Remotes (configure via git remote):
|
|
20
|
+
* origin → <your-github>/mega-brain.git
|
|
21
|
+
* premium → <your-github>/mega-brain-premium.git
|
|
22
|
+
* backup → <your-github>/mega-brain-full.git
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { readFileSync, existsSync } from 'fs';
|
|
26
|
+
import { resolve, dirname } from 'path';
|
|
27
|
+
import { fileURLToPath } from 'url';
|
|
28
|
+
import { execSync } from 'child_process';
|
|
29
|
+
import inquirer from 'inquirer';
|
|
30
|
+
import chalk from 'chalk';
|
|
31
|
+
import ora from 'ora';
|
|
32
|
+
import boxen from 'boxen';
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Constants
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
39
|
+
const __dirname = dirname(__filename);
|
|
40
|
+
const PROJECT_ROOT = resolve(__dirname, '..');
|
|
41
|
+
|
|
42
|
+
const LAYER_CONFIG = {
|
|
43
|
+
1: {
|
|
44
|
+
name: 'Community',
|
|
45
|
+
label: 'Layer 1 — Community (publico, npm)',
|
|
46
|
+
remote: 'origin',
|
|
47
|
+
remoteUrl: 'https://github.com/<your-username>/mega-brain.git',
|
|
48
|
+
color: '#6366f1',
|
|
49
|
+
},
|
|
50
|
+
2: {
|
|
51
|
+
name: 'Premium',
|
|
52
|
+
label: 'Layer 2 — Premium (MoneyClub, privado)',
|
|
53
|
+
remote: 'premium',
|
|
54
|
+
remoteUrl: 'https://github.com/<your-username>/mega-brain-premium.git',
|
|
55
|
+
color: '#f59e0b',
|
|
56
|
+
},
|
|
57
|
+
3: {
|
|
58
|
+
name: 'Full Backup',
|
|
59
|
+
label: 'Layer 3 — Full Backup (tudo, privado)',
|
|
60
|
+
remote: 'backup',
|
|
61
|
+
remoteUrl: 'https://github.com/<your-username>/mega-brain-full.git',
|
|
62
|
+
color: '#ef4444',
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const SENSITIVE_PATTERNS = [
|
|
67
|
+
/github_pat_[A-Za-z0-9_]{20,}/,
|
|
68
|
+
/ghp_[A-Za-z0-9]{20,}/,
|
|
69
|
+
/gho_[A-Za-z0-9]{20,}/,
|
|
70
|
+
/ghs_[A-Za-z0-9]{20,}/,
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
// sk-ant- check: match the prefix but NOT the known placeholder
|
|
74
|
+
const SK_ANT_REAL = /sk-ant-(?!api03-sua-chave-aqui)[A-Za-z0-9_-]+/;
|
|
75
|
+
|
|
76
|
+
// Excluded personas — add names of persona directories that should NOT go to Layer 2
|
|
77
|
+
const LAYER2_EXCLUDED_PERSONAS = ['example-persona-1', 'example-persona-2'];
|
|
78
|
+
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Git helpers
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
function git(cmd, opts = {}) {
|
|
84
|
+
try {
|
|
85
|
+
// Signal pre-push hook that push.js already validated this push
|
|
86
|
+
const env = cmd.startsWith('push ')
|
|
87
|
+
? { ...process.env, MEGA_BRAIN_PUSH_VALIDATED: 'true', ...opts.env }
|
|
88
|
+
: { ...process.env, ...opts.env };
|
|
89
|
+
|
|
90
|
+
return execSync(`git ${cmd}`, {
|
|
91
|
+
cwd: PROJECT_ROOT,
|
|
92
|
+
encoding: 'utf-8',
|
|
93
|
+
stdio: opts.silent ? 'pipe' : 'inherit',
|
|
94
|
+
env,
|
|
95
|
+
...opts,
|
|
96
|
+
});
|
|
97
|
+
} catch (err) {
|
|
98
|
+
if (opts.silent) return '';
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function gitSilent(cmd) {
|
|
104
|
+
return git(cmd, { silent: true, stdio: 'pipe' }).trim();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function getRemotes() {
|
|
108
|
+
const output = gitSilent('remote -v');
|
|
109
|
+
const remotes = {};
|
|
110
|
+
for (const line of output.split('\n')) {
|
|
111
|
+
const match = line.match(/^(\S+)\s+(\S+)\s+\(push\)/);
|
|
112
|
+
if (match) remotes[match[1]] = match[2];
|
|
113
|
+
}
|
|
114
|
+
return remotes;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function getCurrentBranch() {
|
|
118
|
+
return gitSilent('rev-parse --abbrev-ref HEAD') || 'main';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function hasUncommittedChanges() {
|
|
122
|
+
return gitSilent('status --porcelain').length > 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function getStatusSummary() {
|
|
126
|
+
const status = gitSilent('status --porcelain');
|
|
127
|
+
if (!status) return null;
|
|
128
|
+
const lines = status.split('\n').filter(Boolean);
|
|
129
|
+
return {
|
|
130
|
+
total: lines.length,
|
|
131
|
+
preview: lines.slice(0, 8),
|
|
132
|
+
hasMore: lines.length > 8,
|
|
133
|
+
remaining: Math.max(0, lines.length - 8),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
// CLI argument parsing
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
|
|
141
|
+
function parseArgs(argv) {
|
|
142
|
+
const args = argv.slice(2).filter((a) => a !== 'push');
|
|
143
|
+
const result = { layer: null, dryRun: false, message: null };
|
|
144
|
+
|
|
145
|
+
for (let i = 0; i < args.length; i++) {
|
|
146
|
+
if (args[i] === '--layer' && args[i + 1]) {
|
|
147
|
+
const num = parseInt(args[i + 1], 10);
|
|
148
|
+
if ([1, 2, 3].includes(num)) result.layer = num;
|
|
149
|
+
i++;
|
|
150
|
+
} else if (args[i] === '--dry-run') {
|
|
151
|
+
result.dryRun = true;
|
|
152
|
+
} else if ((args[i] === '--message' || args[i] === '-m') && args[i + 1]) {
|
|
153
|
+
result.message = args[i + 1];
|
|
154
|
+
i++;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
// Layer 2 manifest parsing
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
|
|
165
|
+
function loadLayer2ManifestPaths() {
|
|
166
|
+
const manifestPath = resolve(PROJECT_ROOT, '.github', 'layer2-manifest.txt');
|
|
167
|
+
if (!existsSync(manifestPath)) return [];
|
|
168
|
+
|
|
169
|
+
const content = readFileSync(manifestPath, 'utf-8');
|
|
170
|
+
const paths = [];
|
|
171
|
+
let inExclusions = false;
|
|
172
|
+
|
|
173
|
+
for (const raw of content.split('\n')) {
|
|
174
|
+
const line = raw.trim();
|
|
175
|
+
if (line.includes('LAYER 3 EXCLUSIONS')) {
|
|
176
|
+
inExclusions = true;
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (inExclusions) continue;
|
|
180
|
+
if (!line || line.startsWith('#')) continue;
|
|
181
|
+
paths.push(line.replace(/\/+$/, ''));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return paths;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function loadLayer3ManifestPaths() {
|
|
188
|
+
const manifestPath = resolve(PROJECT_ROOT, '.github', 'layer3-manifest.txt');
|
|
189
|
+
if (!existsSync(manifestPath)) return [];
|
|
190
|
+
|
|
191
|
+
const content = readFileSync(manifestPath, 'utf-8');
|
|
192
|
+
const paths = [];
|
|
193
|
+
|
|
194
|
+
for (const raw of content.split('\n')) {
|
|
195
|
+
const line = raw.trim();
|
|
196
|
+
if (line.includes('ALWAYS EXCLUDED')) break;
|
|
197
|
+
if (!line || line.startsWith('#')) continue;
|
|
198
|
+
paths.push(line.replace(/\/+$/, ''));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return paths;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Load Layer 1 allowlist paths.
|
|
206
|
+
* Layer 2 needs these to be complete (Layer 2 = Layer 1 + Premium).
|
|
207
|
+
*/
|
|
208
|
+
function loadLayer1AllowlistPaths() {
|
|
209
|
+
const allowlistPath = resolve(PROJECT_ROOT, '.github', 'layer1-allowlist.txt');
|
|
210
|
+
if (!existsSync(allowlistPath)) return [];
|
|
211
|
+
|
|
212
|
+
const content = readFileSync(allowlistPath, 'utf-8');
|
|
213
|
+
const paths = [];
|
|
214
|
+
|
|
215
|
+
for (const raw of content.split('\n')) {
|
|
216
|
+
const line = raw.trim();
|
|
217
|
+
if (!line || line.startsWith('#')) continue;
|
|
218
|
+
// Skip .gitkeep entries - they're just placeholders
|
|
219
|
+
if (line.endsWith('.gitkeep')) continue;
|
|
220
|
+
paths.push(line.replace(/\/+$/, ''));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return paths;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Files that must NEVER be pushed to any remote
|
|
227
|
+
const SECRET_FILES = [
|
|
228
|
+
'.env', '.env.local', '.env.production', '.env.development',
|
|
229
|
+
'.mcp.json', 'credentials.json', 'token.json', 'token_write.json',
|
|
230
|
+
'settings.local.json', '.claude/settings.local.json',
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
// ---------------------------------------------------------------------------
|
|
234
|
+
// Pre-push validation
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Validate the repository state for the target layer.
|
|
239
|
+
* Returns { ok: boolean, warnings: string[], errors: string[] }
|
|
240
|
+
*/
|
|
241
|
+
function validateForLayer(layer) {
|
|
242
|
+
const warnings = [];
|
|
243
|
+
const errors = [];
|
|
244
|
+
|
|
245
|
+
if (layer === 1) {
|
|
246
|
+
// --- Check phantom tracked files (files tracked but should be ignored) ---
|
|
247
|
+
const phantoms = gitSilent('ls-files -ci --exclude-standard');
|
|
248
|
+
if (phantoms) {
|
|
249
|
+
const phantomList = phantoms.split('\n').filter(Boolean);
|
|
250
|
+
warnings.push(
|
|
251
|
+
`${phantomList.length} arquivo(s) fantasma encontrado(s) (tracked mas deveria ser ignorado):\n` +
|
|
252
|
+
phantomList.slice(0, 5).map((f) => ` ${chalk.dim(f)}`).join('\n') +
|
|
253
|
+
(phantomList.length > 5 ? `\n ${chalk.dim(`... e mais ${phantomList.length - 5}`)}` : '')
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// --- Check for real API keys in tracked files ---
|
|
258
|
+
const trackedFiles = gitSilent('ls-files').split('\n').filter(Boolean);
|
|
259
|
+
const keyFindings = [];
|
|
260
|
+
|
|
261
|
+
for (const file of trackedFiles) {
|
|
262
|
+
// Skip binary-like extensions
|
|
263
|
+
if (/\.(png|jpg|jpeg|gif|ico|svg|woff2?|ttf|eot|pdf|zip|tar|gz)$/i.test(file)) continue;
|
|
264
|
+
|
|
265
|
+
const filePath = resolve(PROJECT_ROOT, file);
|
|
266
|
+
if (!existsSync(filePath)) continue;
|
|
267
|
+
|
|
268
|
+
let content;
|
|
269
|
+
try {
|
|
270
|
+
content = readFileSync(filePath, 'utf-8');
|
|
271
|
+
} catch {
|
|
272
|
+
continue; // skip unreadable files
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
for (const pattern of SENSITIVE_PATTERNS) {
|
|
276
|
+
if (pattern.test(content)) {
|
|
277
|
+
keyFindings.push(`${file} contém token sensível (${pattern.source.slice(0, 15)}...)`);
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (SK_ANT_REAL.test(content)) {
|
|
283
|
+
keyFindings.push(`${file} contém chave Anthropic real (sk-ant-...)`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (keyFindings.length > 0) {
|
|
288
|
+
errors.push(
|
|
289
|
+
`Chaves/tokens sensíveis detectados em arquivos tracked:\n` +
|
|
290
|
+
keyFindings.map((f) => ` ${chalk.red(f)}`).join('\n')
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// --- Check no .env is tracked (exclude .env.example which is OK) ---
|
|
295
|
+
const trackedEnv = trackedFiles.filter((f) =>
|
|
296
|
+
(f === '.env' || f.match(/^\.env\.\w/)) && !f.endsWith('.example')
|
|
297
|
+
);
|
|
298
|
+
if (trackedEnv.length > 0) {
|
|
299
|
+
errors.push(
|
|
300
|
+
`Arquivo .env está tracked:\n` +
|
|
301
|
+
trackedEnv.map((f) => ` ${chalk.red(f)}`).join('\n')
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (layer === 2) {
|
|
307
|
+
const manifestPaths = loadLayer2ManifestPaths();
|
|
308
|
+
|
|
309
|
+
// --- Check excluded personas are not in manifest paths ---
|
|
310
|
+
for (const persona of LAYER2_EXCLUDED_PERSONAS) {
|
|
311
|
+
const found = manifestPaths.filter((p) => p.includes(persona));
|
|
312
|
+
if (found.length > 0) {
|
|
313
|
+
errors.push(
|
|
314
|
+
`Persona excluída "${persona}" encontrada nos caminhos do manifest:\n` +
|
|
315
|
+
found.map((f) => ` ${chalk.red(f)}`).join('\n')
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// --- Check no .env or .claude/agent-memory/ in manifest paths ---
|
|
321
|
+
for (const mp of manifestPaths) {
|
|
322
|
+
if (mp.includes('.env')) {
|
|
323
|
+
errors.push(`Caminho do manifest contém .env: ${mp}`);
|
|
324
|
+
}
|
|
325
|
+
if (mp.includes('.claude/agent-memory')) {
|
|
326
|
+
errors.push(`Caminho do manifest contém agent-memory: ${mp}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// --- Check on-disk files: no excluded personas in premium content ---
|
|
331
|
+
for (const mp of manifestPaths) {
|
|
332
|
+
const fullPath = resolve(PROJECT_ROOT, mp);
|
|
333
|
+
if (!existsSync(fullPath)) continue;
|
|
334
|
+
|
|
335
|
+
for (const persona of LAYER2_EXCLUDED_PERSONAS) {
|
|
336
|
+
// Check if any file inside the manifest path contains excluded persona name
|
|
337
|
+
try {
|
|
338
|
+
const checkOutput = execSync(
|
|
339
|
+
`git ls-files "${mp}"`,
|
|
340
|
+
{ cwd: PROJECT_ROOT, encoding: 'utf-8', stdio: 'pipe' }
|
|
341
|
+
).trim();
|
|
342
|
+
const matchingFiles = checkOutput.split('\n').filter((f) => f && f.includes(persona));
|
|
343
|
+
if (matchingFiles.length > 0) {
|
|
344
|
+
warnings.push(
|
|
345
|
+
`Conteúdo Layer 3 "${persona}" encontrado em ${mp}:\n` +
|
|
346
|
+
matchingFiles.slice(0, 3).map((f) => ` ${chalk.dim(f)}`).join('\n')
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
} catch {
|
|
350
|
+
// Ignore errors
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Layer 3: no validation needed
|
|
357
|
+
|
|
358
|
+
return {
|
|
359
|
+
ok: errors.length === 0,
|
|
360
|
+
warnings,
|
|
361
|
+
errors,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// ---------------------------------------------------------------------------
|
|
366
|
+
// Interactive layer selection
|
|
367
|
+
// ---------------------------------------------------------------------------
|
|
368
|
+
|
|
369
|
+
async function selectLayerInteractive() {
|
|
370
|
+
console.log();
|
|
371
|
+
|
|
372
|
+
const { layer } = await inquirer.prompt([
|
|
373
|
+
{
|
|
374
|
+
type: 'list',
|
|
375
|
+
name: 'layer',
|
|
376
|
+
message: chalk.cyan('Para qual layer deseja publicar?'),
|
|
377
|
+
choices: [
|
|
378
|
+
{
|
|
379
|
+
name:
|
|
380
|
+
chalk.bold.hex('#6366f1')('Layer 1') +
|
|
381
|
+
chalk.white(' — Community ') +
|
|
382
|
+
chalk.dim('(publico, npm)'),
|
|
383
|
+
value: 1,
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
name:
|
|
387
|
+
chalk.bold.hex('#f59e0b')('Layer 2') +
|
|
388
|
+
chalk.white(' — Premium ') +
|
|
389
|
+
chalk.dim('(MoneyClub, privado)'),
|
|
390
|
+
value: 2,
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
name:
|
|
394
|
+
chalk.bold.hex('#ef4444')('Layer 3') +
|
|
395
|
+
chalk.white(' — Full Backup ') +
|
|
396
|
+
chalk.dim('(tudo, privado)'),
|
|
397
|
+
value: 3,
|
|
398
|
+
},
|
|
399
|
+
],
|
|
400
|
+
loop: false,
|
|
401
|
+
},
|
|
402
|
+
]);
|
|
403
|
+
|
|
404
|
+
return layer;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// ---------------------------------------------------------------------------
|
|
408
|
+
// Commit message prompt
|
|
409
|
+
// ---------------------------------------------------------------------------
|
|
410
|
+
|
|
411
|
+
async function promptCommitMessage(defaultPrefix) {
|
|
412
|
+
const { message } = await inquirer.prompt([
|
|
413
|
+
{
|
|
414
|
+
type: 'input',
|
|
415
|
+
name: 'message',
|
|
416
|
+
message: chalk.cyan('Mensagem do commit:'),
|
|
417
|
+
default: defaultPrefix,
|
|
418
|
+
validate: (input) => (input.trim() ? true : chalk.red('Mensagem nao pode estar vazia.')),
|
|
419
|
+
},
|
|
420
|
+
]);
|
|
421
|
+
return message.trim();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// ---------------------------------------------------------------------------
|
|
425
|
+
// Confirmation prompt
|
|
426
|
+
// ---------------------------------------------------------------------------
|
|
427
|
+
|
|
428
|
+
async function confirmAction(question) {
|
|
429
|
+
const { confirmed } = await inquirer.prompt([
|
|
430
|
+
{
|
|
431
|
+
type: 'confirm',
|
|
432
|
+
name: 'confirmed',
|
|
433
|
+
message: chalk.cyan(question),
|
|
434
|
+
default: true,
|
|
435
|
+
},
|
|
436
|
+
]);
|
|
437
|
+
return confirmed;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// ---------------------------------------------------------------------------
|
|
441
|
+
// Layer 1 Push Flow
|
|
442
|
+
// ---------------------------------------------------------------------------
|
|
443
|
+
|
|
444
|
+
async function pushLayer1({ dryRun, message }) {
|
|
445
|
+
const config = LAYER_CONFIG[1];
|
|
446
|
+
const branch = getCurrentBranch();
|
|
447
|
+
|
|
448
|
+
// Step 1: Validate
|
|
449
|
+
const spinner = ora({ text: 'Validando para Layer 1...', color: 'cyan' }).start();
|
|
450
|
+
const validation = validateForLayer(1);
|
|
451
|
+
|
|
452
|
+
if (validation.warnings.length > 0) {
|
|
453
|
+
spinner.warn(chalk.yellow('Avisos de validacao:'));
|
|
454
|
+
for (const w of validation.warnings) {
|
|
455
|
+
console.log(` ${chalk.yellow('!')} ${w}`);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (!validation.ok) {
|
|
460
|
+
spinner.fail(chalk.red('Validacao falhou com erros:'));
|
|
461
|
+
for (const e of validation.errors) {
|
|
462
|
+
console.log(` ${chalk.red('x')} ${e}`);
|
|
463
|
+
}
|
|
464
|
+
console.log();
|
|
465
|
+
console.log(chalk.dim(' Corrija os erros acima antes de fazer push para Layer 1.'));
|
|
466
|
+
console.log(chalk.dim(' Para remover arquivos do tracking: git rm --cached <arquivo>'));
|
|
467
|
+
console.log();
|
|
468
|
+
process.exit(1);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (validation.warnings.length === 0) {
|
|
472
|
+
spinner.succeed(chalk.green('Validacao OK'));
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (dryRun) {
|
|
476
|
+
showDryRun(1, config, branch);
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Step 2: git add -A (respects .gitignore)
|
|
481
|
+
const addSpinner = ora({ text: 'Staging arquivos (respeitando .gitignore)...', color: 'cyan' }).start();
|
|
482
|
+
try {
|
|
483
|
+
git('add -A', { silent: true, stdio: 'pipe' });
|
|
484
|
+
addSpinner.succeed(chalk.green('Arquivos staged'));
|
|
485
|
+
} catch (err) {
|
|
486
|
+
addSpinner.fail(chalk.red(`Falha ao fazer staging: ${err.message}`));
|
|
487
|
+
process.exit(1);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// Check if there's anything to commit
|
|
491
|
+
const staged = gitSilent('diff --cached --stat');
|
|
492
|
+
if (!staged) {
|
|
493
|
+
console.log(chalk.dim('\n Nenhuma mudanca para commit. Verificando se existe algo para push...\n'));
|
|
494
|
+
|
|
495
|
+
// Still try to push in case there are local commits not yet pushed
|
|
496
|
+
const pushSpinner = ora({ text: `Pushing para ${config.remote}/${branch}...`, color: 'cyan' }).start();
|
|
497
|
+
try {
|
|
498
|
+
git(`push ${config.remote} ${branch}`, { silent: true, stdio: 'pipe' });
|
|
499
|
+
pushSpinner.succeed(chalk.green(`Push concluido para ${config.remote}/${branch}`));
|
|
500
|
+
} catch (err) {
|
|
501
|
+
if (err.stderr && err.stderr.includes('Everything up-to-date')) {
|
|
502
|
+
pushSpinner.info(chalk.dim('Ja esta atualizado.'));
|
|
503
|
+
} else {
|
|
504
|
+
pushSpinner.fail(chalk.red(`Falha no push: ${err.message}`));
|
|
505
|
+
process.exit(1);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
await autoSyncToBackup(branch);
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Step 3: Commit message
|
|
514
|
+
const commitMsg = message || (await promptCommitMessage('feat: update Layer 1 content'));
|
|
515
|
+
|
|
516
|
+
// Step 4: git commit
|
|
517
|
+
const commitSpinner = ora({ text: 'Criando commit...', color: 'cyan' }).start();
|
|
518
|
+
try {
|
|
519
|
+
git(`commit -m "${commitMsg.replace(/"/g, '\\"')}"`, { silent: true, stdio: 'pipe' });
|
|
520
|
+
commitSpinner.succeed(chalk.green('Commit criado'));
|
|
521
|
+
} catch (err) {
|
|
522
|
+
const output = err.stdout || err.stderr || '';
|
|
523
|
+
if (output.includes('nothing to commit')) {
|
|
524
|
+
commitSpinner.info(chalk.dim('Nada para commitar.'));
|
|
525
|
+
} else {
|
|
526
|
+
commitSpinner.fail(chalk.red(`Falha no commit: ${err.message}`));
|
|
527
|
+
process.exit(1);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// Step 5: git push public main
|
|
532
|
+
const pushSpinner = ora({ text: `Pushing para ${config.remote}/${branch}...`, color: 'cyan' }).start();
|
|
533
|
+
try {
|
|
534
|
+
git(`push ${config.remote} ${branch}`);
|
|
535
|
+
pushSpinner.succeed(chalk.green(`Push concluido para ${config.remote}/${branch}`));
|
|
536
|
+
} catch (err) {
|
|
537
|
+
pushSpinner.fail(chalk.red(`Falha no push: ${err.message}`));
|
|
538
|
+
process.exit(1);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Step 6: Ask about npm publish
|
|
542
|
+
const publishNpm = await confirmAction('Publicar no npm tambem?');
|
|
543
|
+
if (publishNpm) {
|
|
544
|
+
const npmSpinner = ora({ text: 'Publicando no npm...', color: 'cyan' }).start();
|
|
545
|
+
try {
|
|
546
|
+
execSync('npm publish', { cwd: PROJECT_ROOT, stdio: 'inherit' });
|
|
547
|
+
npmSpinner.succeed(chalk.green('Publicado no npm!'));
|
|
548
|
+
} catch (err) {
|
|
549
|
+
npmSpinner.fail(chalk.red(`Falha ao publicar no npm: ${err.message}`));
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Step 7: Auto-sync to backup (Layer 3)
|
|
554
|
+
await autoSyncToBackup(branch);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// ---------------------------------------------------------------------------
|
|
558
|
+
// Layer 2 Push Flow
|
|
559
|
+
// ---------------------------------------------------------------------------
|
|
560
|
+
|
|
561
|
+
async function pushLayer2({ dryRun, message }) {
|
|
562
|
+
const config = LAYER_CONFIG[2];
|
|
563
|
+
const branch = getCurrentBranch();
|
|
564
|
+
|
|
565
|
+
// Step 1: Validate
|
|
566
|
+
const spinner = ora({ text: 'Validando para Layer 2...', color: 'yellow' }).start();
|
|
567
|
+
const validation = validateForLayer(2);
|
|
568
|
+
|
|
569
|
+
if (validation.warnings.length > 0) {
|
|
570
|
+
spinner.warn(chalk.yellow('Avisos de validacao:'));
|
|
571
|
+
for (const w of validation.warnings) {
|
|
572
|
+
console.log(` ${chalk.yellow('!')} ${w}`);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if (!validation.ok) {
|
|
577
|
+
spinner.fail(chalk.red('Validacao falhou com erros:'));
|
|
578
|
+
for (const e of validation.errors) {
|
|
579
|
+
console.log(` ${chalk.red('x')} ${e}`);
|
|
580
|
+
}
|
|
581
|
+
console.log();
|
|
582
|
+
process.exit(1);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
if (validation.warnings.length === 0) {
|
|
586
|
+
spinner.succeed(chalk.green('Validacao OK'));
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// Step 2: Read layer1-allowlist.txt AND layer2-manifest.txt
|
|
590
|
+
// Layer 2 = Layer 1 (base) + Premium (manifest)
|
|
591
|
+
const layer1Paths = loadLayer1AllowlistPaths();
|
|
592
|
+
const layer2Paths = loadLayer2ManifestPaths();
|
|
593
|
+
|
|
594
|
+
if (layer1Paths.length === 0) {
|
|
595
|
+
console.log(chalk.red('\n Erro: layer1-allowlist.txt vazio ou nao encontrado.'));
|
|
596
|
+
console.log(chalk.dim(' Verifique: .github/layer1-allowlist.txt\n'));
|
|
597
|
+
process.exit(1);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (layer2Paths.length === 0) {
|
|
601
|
+
console.log(chalk.red('\n Erro: layer2-manifest.txt vazio ou nao encontrado.'));
|
|
602
|
+
console.log(chalk.dim(' Verifique: .github/layer2-manifest.txt\n'));
|
|
603
|
+
process.exit(1);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// Combine Layer 1 + Layer 2 (deduplicated)
|
|
607
|
+
const allPaths = [...new Set([...layer1Paths, ...layer2Paths])];
|
|
608
|
+
|
|
609
|
+
console.log(chalk.dim(`\n Layer 1 (base): ${layer1Paths.length} caminhos`));
|
|
610
|
+
console.log(chalk.dim(` Layer 2 (premium): ${layer2Paths.length} caminhos`));
|
|
611
|
+
console.log(chalk.dim(` Total combinado: ${allPaths.length} caminhos\n`));
|
|
612
|
+
|
|
613
|
+
// Show Layer 1 paths
|
|
614
|
+
console.log(chalk.hex('#6366f1')(' Layer 1 (Community):'));
|
|
615
|
+
for (const p of layer1Paths.slice(0, 5)) {
|
|
616
|
+
console.log(chalk.dim(` + ${p}`));
|
|
617
|
+
}
|
|
618
|
+
if (layer1Paths.length > 5) {
|
|
619
|
+
console.log(chalk.dim(` ... e mais ${layer1Paths.length - 5} caminhos`));
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// Show Layer 2 paths
|
|
623
|
+
console.log(chalk.hex('#f59e0b')('\n Layer 2 (Premium):'));
|
|
624
|
+
for (const p of layer2Paths) {
|
|
625
|
+
console.log(chalk.dim(` + ${p}`));
|
|
626
|
+
}
|
|
627
|
+
console.log();
|
|
628
|
+
|
|
629
|
+
// Use combined paths for the rest of the function
|
|
630
|
+
const manifestPaths = allPaths;
|
|
631
|
+
|
|
632
|
+
if (dryRun) {
|
|
633
|
+
showDryRun(2, config, branch);
|
|
634
|
+
console.log(chalk.dim(' Caminhos (Layer 1 + Layer 2) que seriam adicionados com git add -f:'));
|
|
635
|
+
for (const p of manifestPaths.slice(0, 15)) {
|
|
636
|
+
const exists = existsSync(resolve(PROJECT_ROOT, p));
|
|
637
|
+
console.log(` ${exists ? chalk.green('+') : chalk.red('x')} ${p} ${!exists ? chalk.dim('(nao existe)') : ''}`);
|
|
638
|
+
}
|
|
639
|
+
if (manifestPaths.length > 15) {
|
|
640
|
+
console.log(chalk.dim(` ... e mais ${manifestPaths.length - 15} caminhos`));
|
|
641
|
+
}
|
|
642
|
+
console.log();
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Step 3: git add -f each path (Layer 1 + Layer 2) that exists on disk
|
|
647
|
+
const addSpinner = ora({ text: 'Staging caminhos Layer 1 + Layer 2 (force add)...', color: 'yellow' }).start();
|
|
648
|
+
let addedCount = 0;
|
|
649
|
+
let layer1Added = 0;
|
|
650
|
+
let layer2Added = 0;
|
|
651
|
+
|
|
652
|
+
for (const path of manifestPaths) {
|
|
653
|
+
const fullPath = resolve(PROJECT_ROOT, path);
|
|
654
|
+
if (!existsSync(fullPath)) continue;
|
|
655
|
+
|
|
656
|
+
try {
|
|
657
|
+
git(`add -f "${path}"`, { silent: true, stdio: 'pipe' });
|
|
658
|
+
addedCount++;
|
|
659
|
+
// Track which layer this path belongs to
|
|
660
|
+
if (layer1Paths.includes(path)) layer1Added++;
|
|
661
|
+
if (layer2Paths.includes(path)) layer2Added++;
|
|
662
|
+
} catch {
|
|
663
|
+
// Some paths may fail — that's ok
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
if (addedCount === 0) {
|
|
668
|
+
addSpinner.warn(chalk.yellow('Nenhum caminho encontrado no disco.'));
|
|
669
|
+
console.log(chalk.dim(' Verifique se o conteudo existe localmente.\n'));
|
|
670
|
+
process.exit(1);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
addSpinner.succeed(chalk.green(`${addedCount} caminhos staged (L1: ${layer1Added}, L2: ${layer2Added})`));
|
|
674
|
+
|
|
675
|
+
// Step 4: Commit (bypass pre-commit hook via env var — this is a temporary commit)
|
|
676
|
+
const commitMsg = message || 'feat(premium): update Layer 2 (Layer 1 + Premium content)';
|
|
677
|
+
const commitSpinner = ora({ text: 'Criando commit premium...', color: 'yellow' }).start();
|
|
678
|
+
try {
|
|
679
|
+
git(`commit -m "${commitMsg.replace(/"/g, '\\"')}"`, { silent: true, stdio: 'pipe', env: { MEGA_BRAIN_LAYER_PUSH: 'true' } });
|
|
680
|
+
commitSpinner.succeed(chalk.green('Commit premium criado'));
|
|
681
|
+
} catch (err) {
|
|
682
|
+
const output = (err.stdout || '') + (err.stderr || '');
|
|
683
|
+
if (output.includes('nothing to commit')) {
|
|
684
|
+
commitSpinner.info(chalk.dim('Nada de novo para commitar no premium.'));
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
commitSpinner.fail(chalk.red(`Falha no commit: ${err.message}`));
|
|
688
|
+
process.exit(1);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// Step 5: git push premium main --force
|
|
692
|
+
const pushSpinner = ora({ text: `Pushing para ${config.remote}/${branch} (force)...`, color: 'yellow' }).start();
|
|
693
|
+
try {
|
|
694
|
+
git(`push ${config.remote} ${branch} --force`);
|
|
695
|
+
pushSpinner.succeed(chalk.green(`Push concluido para ${config.remote}/${branch}`));
|
|
696
|
+
} catch (err) {
|
|
697
|
+
pushSpinner.fail(chalk.red(`Falha no push: ${err.message}`));
|
|
698
|
+
// Still try to reset even if push fails
|
|
699
|
+
resetLastCommit();
|
|
700
|
+
process.exit(1);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Step 6: git reset HEAD~1 (remove Layer 2 commit from local, keep files)
|
|
704
|
+
resetLastCommit();
|
|
705
|
+
|
|
706
|
+
// Step 7: Auto-sync to backup (Layer 3)
|
|
707
|
+
await autoSyncToBackup(branch);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// ---------------------------------------------------------------------------
|
|
711
|
+
// Layer 3 Push Flow
|
|
712
|
+
// ---------------------------------------------------------------------------
|
|
713
|
+
|
|
714
|
+
async function pushLayer3({ dryRun, message }) {
|
|
715
|
+
const config = LAYER_CONFIG[3];
|
|
716
|
+
const branch = getCurrentBranch();
|
|
717
|
+
|
|
718
|
+
// No validation for Layer 3
|
|
719
|
+
|
|
720
|
+
// Read Layer 3 manifest
|
|
721
|
+
const layer3Paths = loadLayer3ManifestPaths();
|
|
722
|
+
if (layer3Paths.length === 0) {
|
|
723
|
+
console.log(chalk.red('\n Erro: layer3-manifest.txt vazio ou nao encontrado.'));
|
|
724
|
+
console.log(chalk.dim(' Verifique: .github/layer3-manifest.txt\n'));
|
|
725
|
+
process.exit(1);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
if (dryRun) {
|
|
729
|
+
showDryRun(3, config, branch);
|
|
730
|
+
console.log(chalk.dim(' Caminhos do manifest que seriam adicionados com git add -f:'));
|
|
731
|
+
for (const p of layer3Paths) {
|
|
732
|
+
const exists = existsSync(resolve(PROJECT_ROOT, p));
|
|
733
|
+
console.log(` ${exists ? chalk.green('+') : chalk.red('x')} ${p} ${!exists ? chalk.dim('(nao existe)') : ''}`);
|
|
734
|
+
}
|
|
735
|
+
console.log();
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// Step 1: Stage tracked files normally
|
|
740
|
+
const addSpinner = ora({ text: 'Staging arquivos tracked...', color: 'red' }).start();
|
|
741
|
+
try {
|
|
742
|
+
git('add -A', { silent: true, stdio: 'pipe' });
|
|
743
|
+
addSpinner.succeed(chalk.green('Arquivos tracked staged'));
|
|
744
|
+
} catch (err) {
|
|
745
|
+
addSpinner.fail(chalk.red(`Falha ao fazer staging: ${err.message}`));
|
|
746
|
+
process.exit(1);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// Step 2: Force-add Layer 3 content (gitignored but needed for backup)
|
|
750
|
+
const forceSpinner = ora({ text: 'Staging conteudo de backup (force add)...', color: 'red' }).start();
|
|
751
|
+
let addedCount = 0;
|
|
752
|
+
|
|
753
|
+
for (const manifestPath of layer3Paths) {
|
|
754
|
+
const fullPath = resolve(PROJECT_ROOT, manifestPath);
|
|
755
|
+
if (!existsSync(fullPath)) continue;
|
|
756
|
+
|
|
757
|
+
try {
|
|
758
|
+
git(`add -f "${manifestPath}"`, { silent: true, stdio: 'pipe' });
|
|
759
|
+
addedCount++;
|
|
760
|
+
} catch {
|
|
761
|
+
// Some paths may fail — that's ok
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
forceSpinner.succeed(chalk.green(`${addedCount} caminhos de backup staged`));
|
|
766
|
+
|
|
767
|
+
// Step 3: Safety — unstage secrets that may have been caught
|
|
768
|
+
for (const secretFile of SECRET_FILES) {
|
|
769
|
+
try {
|
|
770
|
+
git(`reset HEAD -- "${secretFile}"`, { silent: true, stdio: 'pipe' });
|
|
771
|
+
} catch {
|
|
772
|
+
// File may not exist or not be staged
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// Check if there's anything to commit
|
|
777
|
+
const staged = gitSilent('diff --cached --stat');
|
|
778
|
+
if (!staged) {
|
|
779
|
+
console.log(chalk.dim('\n Nenhuma mudanca para commit. Pushing estado atual...\n'));
|
|
780
|
+
|
|
781
|
+
const pushSpinner = ora({ text: `Pushing para ${config.remote}/${branch} (force)...`, color: 'red' }).start();
|
|
782
|
+
try {
|
|
783
|
+
git(`push ${config.remote} ${branch} --force`);
|
|
784
|
+
pushSpinner.succeed(chalk.green(`Push concluido para ${config.remote}/${branch}`));
|
|
785
|
+
} catch (err) {
|
|
786
|
+
pushSpinner.fail(chalk.red(`Falha no push: ${err.message}`));
|
|
787
|
+
process.exit(1);
|
|
788
|
+
}
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// Step 4: Commit message
|
|
793
|
+
const commitMsg = message || (await promptCommitMessage('backup: full state sync'));
|
|
794
|
+
|
|
795
|
+
// Step 5: git commit (bypass pre-commit hook via env var — this is a temporary commit)
|
|
796
|
+
const commitSpinner = ora({ text: 'Criando commit de backup...', color: 'red' }).start();
|
|
797
|
+
try {
|
|
798
|
+
git(`commit -m "${commitMsg.replace(/"/g, '\\"')}"`, { silent: true, stdio: 'pipe', env: { MEGA_BRAIN_LAYER_PUSH: 'true' } });
|
|
799
|
+
commitSpinner.succeed(chalk.green('Commit criado'));
|
|
800
|
+
} catch (err) {
|
|
801
|
+
const output = (err.stdout || '') + (err.stderr || '');
|
|
802
|
+
if (output.includes('nothing to commit')) {
|
|
803
|
+
commitSpinner.info(chalk.dim('Nada para commitar.'));
|
|
804
|
+
} else {
|
|
805
|
+
commitSpinner.fail(chalk.red(`Falha no commit: ${err.message}`));
|
|
806
|
+
process.exit(1);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// Step 6: git push backup main --force
|
|
811
|
+
const pushSpinner = ora({ text: `Pushing para ${config.remote}/${branch} (force)...`, color: 'red' }).start();
|
|
812
|
+
try {
|
|
813
|
+
git(`push ${config.remote} ${branch} --force`);
|
|
814
|
+
pushSpinner.succeed(chalk.green(`Push concluido para ${config.remote}/${branch}`));
|
|
815
|
+
} catch (err) {
|
|
816
|
+
pushSpinner.fail(chalk.red(`Falha no push: ${err.message}`));
|
|
817
|
+
// Still try to reset
|
|
818
|
+
resetLastCommit();
|
|
819
|
+
process.exit(1);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Step 7: git reset HEAD~1 (Layer 3 commit doesn't stay on local main)
|
|
823
|
+
resetLastCommit();
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// ---------------------------------------------------------------------------
|
|
827
|
+
// Helpers
|
|
828
|
+
// ---------------------------------------------------------------------------
|
|
829
|
+
|
|
830
|
+
/**
|
|
831
|
+
* Reset the last commit but keep files (mixed reset).
|
|
832
|
+
* Used by Layer 2 and Layer 3 to avoid polluting local main.
|
|
833
|
+
*/
|
|
834
|
+
function resetLastCommit() {
|
|
835
|
+
const resetSpinner = ora({ text: 'Limpando commit local (reset HEAD~1)...', color: 'gray' }).start();
|
|
836
|
+
try {
|
|
837
|
+
git('reset HEAD~1', { silent: true, stdio: 'pipe' });
|
|
838
|
+
resetSpinner.succeed(chalk.dim('Commit local removido (arquivos preservados)'));
|
|
839
|
+
} catch (err) {
|
|
840
|
+
resetSpinner.warn(chalk.yellow(`Nao foi possivel fazer reset: ${err.message}`));
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Auto-sync current main to backup remote (Layer 3).
|
|
846
|
+
*/
|
|
847
|
+
async function autoSyncToBackup(branch) {
|
|
848
|
+
const remotes = getRemotes();
|
|
849
|
+
if (!remotes.backup) {
|
|
850
|
+
console.log(chalk.dim('\n Remote "backup" nao configurado. Pulando auto-sync.\n'));
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
const syncSpinner = ora({ text: 'Auto-sync para backup (Layer 3)...', color: 'gray' }).start();
|
|
855
|
+
try {
|
|
856
|
+
git(`push backup ${branch} --force`, { silent: true, stdio: 'pipe' });
|
|
857
|
+
syncSpinner.succeed(chalk.dim('Auto-sync para backup concluido'));
|
|
858
|
+
} catch {
|
|
859
|
+
syncSpinner.warn(chalk.dim('Auto-sync para backup falhou (nao critico)'));
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Show dry-run summary without executing.
|
|
865
|
+
*/
|
|
866
|
+
function showDryRun(layer, config, branch) {
|
|
867
|
+
console.log();
|
|
868
|
+
console.log(
|
|
869
|
+
boxen(
|
|
870
|
+
chalk.bold.yellow(' DRY RUN ') +
|
|
871
|
+
chalk.white(' — Nenhuma acao sera executada\n\n') +
|
|
872
|
+
chalk.white(` Layer: ${config.label}\n`) +
|
|
873
|
+
chalk.white(` Remote: ${config.remote} → ${config.remoteUrl}\n`) +
|
|
874
|
+
chalk.white(` Branch: ${branch}\n`) +
|
|
875
|
+
chalk.white(` Comando: git push ${config.remote} ${branch}`) +
|
|
876
|
+
(layer !== 1 ? chalk.white(' --force') : ''),
|
|
877
|
+
{
|
|
878
|
+
padding: 1,
|
|
879
|
+
margin: { left: 2 },
|
|
880
|
+
borderStyle: 'round',
|
|
881
|
+
borderColor: 'yellow',
|
|
882
|
+
}
|
|
883
|
+
)
|
|
884
|
+
);
|
|
885
|
+
|
|
886
|
+
if (layer === 1) {
|
|
887
|
+
console.log(chalk.dim('\n Fluxo Layer 1:'));
|
|
888
|
+
console.log(chalk.dim(' 1. Validar (phantom files, API keys, .env)'));
|
|
889
|
+
console.log(chalk.dim(' 2. git add -A (respeita .gitignore)'));
|
|
890
|
+
console.log(chalk.dim(' 3. Prompt para commit message'));
|
|
891
|
+
console.log(chalk.dim(' 4. git commit'));
|
|
892
|
+
console.log(chalk.dim(' 5. git push origin main'));
|
|
893
|
+
console.log(chalk.dim(' 6. Perguntar sobre npm publish'));
|
|
894
|
+
console.log(chalk.dim(' 7. Auto-sync para backup (Layer 3)'));
|
|
895
|
+
} else if (layer === 2) {
|
|
896
|
+
console.log(chalk.dim('\n Fluxo Layer 2 (Layer 1 + Premium):'));
|
|
897
|
+
console.log(chalk.dim(' 1. Validar (personas excluidas, .env)'));
|
|
898
|
+
console.log(chalk.dim(' 2. Ler layer1-allowlist.txt + layer2-manifest.txt'));
|
|
899
|
+
console.log(chalk.dim(' 3. git add -f para cada caminho (L1 + L2 combinados)'));
|
|
900
|
+
console.log(chalk.dim(' 4. git commit'));
|
|
901
|
+
console.log(chalk.dim(' 5. git push premium main --force'));
|
|
902
|
+
console.log(chalk.dim(' 6. git reset HEAD~1 (limpar commit local)'));
|
|
903
|
+
console.log(chalk.dim(' 7. Auto-sync para backup (Layer 3)'));
|
|
904
|
+
} else {
|
|
905
|
+
console.log(chalk.dim('\n Fluxo Layer 3:'));
|
|
906
|
+
console.log(chalk.dim(' 1. Sem validacao (tudo vai)'));
|
|
907
|
+
console.log(chalk.dim(' 2. git add -A (tracked files)'));
|
|
908
|
+
console.log(chalk.dim(' 3. git add -f para caminhos do layer3-manifest.txt'));
|
|
909
|
+
console.log(chalk.dim(' 4. git reset HEAD -- secrets (safety net)'));
|
|
910
|
+
console.log(chalk.dim(' 5. Prompt para commit message'));
|
|
911
|
+
console.log(chalk.dim(' 6. git commit'));
|
|
912
|
+
console.log(chalk.dim(' 7. git push backup main --force'));
|
|
913
|
+
console.log(chalk.dim(' 8. git reset HEAD~1 (limpar commit local)'));
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
console.log();
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Verify that a remote exists and show helpful error if not.
|
|
921
|
+
*/
|
|
922
|
+
function ensureRemoteExists(layer) {
|
|
923
|
+
const config = LAYER_CONFIG[layer];
|
|
924
|
+
const remotes = getRemotes();
|
|
925
|
+
|
|
926
|
+
if (!remotes[config.remote]) {
|
|
927
|
+
console.log();
|
|
928
|
+
console.log(chalk.red(` Erro: Remote "${config.remote}" nao esta configurado.`));
|
|
929
|
+
console.log();
|
|
930
|
+
console.log(chalk.white(' Para adicionar:'));
|
|
931
|
+
console.log(chalk.cyan(` git remote add ${config.remote} ${config.remoteUrl}`));
|
|
932
|
+
console.log();
|
|
933
|
+
console.log(chalk.dim(' Remotes atuais:'));
|
|
934
|
+
for (const [name, url] of Object.entries(remotes)) {
|
|
935
|
+
console.log(chalk.dim(` ${name} → ${url}`));
|
|
936
|
+
}
|
|
937
|
+
console.log();
|
|
938
|
+
process.exit(1);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// ---------------------------------------------------------------------------
|
|
943
|
+
// Banner
|
|
944
|
+
// ---------------------------------------------------------------------------
|
|
945
|
+
|
|
946
|
+
function showBanner() {
|
|
947
|
+
console.log();
|
|
948
|
+
console.log(
|
|
949
|
+
boxen(chalk.bold.hex('#a855f7')(' Mega Brain Push '), {
|
|
950
|
+
padding: { left: 2, right: 2, top: 0, bottom: 0 },
|
|
951
|
+
margin: { left: 2 },
|
|
952
|
+
borderStyle: 'round',
|
|
953
|
+
borderColor: '#a855f7',
|
|
954
|
+
})
|
|
955
|
+
);
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
function showSuccess(layer, branch) {
|
|
959
|
+
const config = LAYER_CONFIG[layer];
|
|
960
|
+
console.log();
|
|
961
|
+
console.log(
|
|
962
|
+
boxen(
|
|
963
|
+
chalk.bold.hex(config.color)(` Push concluido! `) +
|
|
964
|
+
'\n\n' +
|
|
965
|
+
chalk.white(` Layer: ${config.label}\n`) +
|
|
966
|
+
chalk.white(` Remote: ${config.remote}/${branch}`),
|
|
967
|
+
{
|
|
968
|
+
padding: 1,
|
|
969
|
+
margin: { left: 2 },
|
|
970
|
+
borderStyle: 'round',
|
|
971
|
+
borderColor: config.color,
|
|
972
|
+
}
|
|
973
|
+
)
|
|
974
|
+
);
|
|
975
|
+
console.log();
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// ---------------------------------------------------------------------------
|
|
979
|
+
// Main
|
|
980
|
+
// ---------------------------------------------------------------------------
|
|
981
|
+
|
|
982
|
+
async function main() {
|
|
983
|
+
const opts = parseArgs(process.argv);
|
|
984
|
+
|
|
985
|
+
showBanner();
|
|
986
|
+
|
|
987
|
+
// Select layer
|
|
988
|
+
const layer = opts.layer || (await selectLayerInteractive());
|
|
989
|
+
const config = LAYER_CONFIG[layer];
|
|
990
|
+
const branch = getCurrentBranch();
|
|
991
|
+
|
|
992
|
+
// Verify remote exists (unless dry-run)
|
|
993
|
+
if (!opts.dryRun) {
|
|
994
|
+
ensureRemoteExists(layer);
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// Show current state
|
|
998
|
+
console.log();
|
|
999
|
+
console.log(chalk.white(` Layer: `) + chalk.bold.hex(config.color)(config.label));
|
|
1000
|
+
console.log(chalk.white(` Remote: `) + chalk.dim(`${config.remote}/${branch}`));
|
|
1001
|
+
|
|
1002
|
+
// Show uncommitted changes warning
|
|
1003
|
+
const status = getStatusSummary();
|
|
1004
|
+
if (status) {
|
|
1005
|
+
console.log();
|
|
1006
|
+
console.log(chalk.yellow(` ${status.total} arquivo(s) com mudancas pendentes:`));
|
|
1007
|
+
for (const line of status.preview) {
|
|
1008
|
+
console.log(chalk.dim(` ${line}`));
|
|
1009
|
+
}
|
|
1010
|
+
if (status.hasMore) {
|
|
1011
|
+
console.log(chalk.dim(` ... e mais ${status.remaining} arquivo(s)`));
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
console.log();
|
|
1016
|
+
|
|
1017
|
+
// Confirm (unless dry-run or --layer was explicit)
|
|
1018
|
+
if (!opts.dryRun && !opts.layer) {
|
|
1019
|
+
const confirmed = await confirmAction('Confirmar push?');
|
|
1020
|
+
if (!confirmed) {
|
|
1021
|
+
console.log(chalk.dim('\n Push cancelado.\n'));
|
|
1022
|
+
process.exit(0);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
// Execute the appropriate push flow
|
|
1027
|
+
switch (layer) {
|
|
1028
|
+
case 1:
|
|
1029
|
+
await pushLayer1(opts);
|
|
1030
|
+
break;
|
|
1031
|
+
case 2:
|
|
1032
|
+
await pushLayer2(opts);
|
|
1033
|
+
break;
|
|
1034
|
+
case 3:
|
|
1035
|
+
await pushLayer3(opts);
|
|
1036
|
+
break;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
showSuccess(layer, branch);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// ---------------------------------------------------------------------------
|
|
1043
|
+
// Entry point — works as standalone binary AND as module import
|
|
1044
|
+
// ---------------------------------------------------------------------------
|
|
1045
|
+
|
|
1046
|
+
export { pushLayer1, pushLayer2, pushLayer3, validateForLayer, loadLayer1AllowlistPaths, loadLayer2ManifestPaths, loadLayer3ManifestPaths };
|
|
1047
|
+
|
|
1048
|
+
main().catch((err) => {
|
|
1049
|
+
console.error();
|
|
1050
|
+
console.error(chalk.red(` Erro fatal: ${err.message}`));
|
|
1051
|
+
if (process.env.DEBUG) {
|
|
1052
|
+
console.error(err.stack);
|
|
1053
|
+
}
|
|
1054
|
+
console.error();
|
|
1055
|
+
process.exit(1);
|
|
1056
|
+
});
|