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
|
@@ -0,0 +1,796 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Autonomous Processor - Unattended file processing engine for Mega Brain pipeline.
|
|
4
|
+
|
|
5
|
+
Provides Queue, Loop, Recovery, and Timeout systems for autonomous operation.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from core.intelligence import AutonomousProcessor
|
|
9
|
+
|
|
10
|
+
processor = AutonomousProcessor('wf-pipeline-full')
|
|
11
|
+
processor.queue.add('/path/to/file.txt', priority=1)
|
|
12
|
+
result = processor.run()
|
|
13
|
+
|
|
14
|
+
# Or via CLI:
|
|
15
|
+
python3 autonomous_processor.py queue add /path/to/file.txt 1
|
|
16
|
+
python3 autonomous_processor.py run --timeout=600
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
import signal
|
|
22
|
+
import sys
|
|
23
|
+
import time
|
|
24
|
+
from dataclasses import dataclass, field, asdict
|
|
25
|
+
from datetime import datetime
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from typing import Dict, List, Optional, Any
|
|
28
|
+
|
|
29
|
+
# Import TaskOrchestrator from same package
|
|
30
|
+
from core.intelligence.task_orchestrator import TaskOrchestrator
|
|
31
|
+
|
|
32
|
+
# ============================================================================
|
|
33
|
+
# Configuration and Constants
|
|
34
|
+
# ============================================================================
|
|
35
|
+
|
|
36
|
+
PROJECT_DIR = Path(os.getenv('CLAUDE_PROJECT_DIR', '.')).resolve()
|
|
37
|
+
QUEUE_STATE_PATH = PROJECT_DIR / '.claude' / 'mission-control' / 'QUEUE-STATE.json'
|
|
38
|
+
STOP_SIGNAL_PATH = PROJECT_DIR / '.claude' / 'mission-control' / 'STOP-AUTONOMOUS'
|
|
39
|
+
PROCESSOR_STATE_PATH = PROJECT_DIR / '.claude' / 'mission-control' / 'AUTONOMOUS-STATE.json'
|
|
40
|
+
MONITOR_PATH = PROJECT_DIR / '.claude' / 'mission-control' / 'AUTONOMOUS-MONITOR.json'
|
|
41
|
+
CHECKPOINT_PATH = PROJECT_DIR / '.claude' / 'mission-control' / 'AUTONOMOUS-CHECKPOINT.json'
|
|
42
|
+
LOG_PATH = PROJECT_DIR / 'logs' / 'autonomous-processing.jsonl'
|
|
43
|
+
|
|
44
|
+
DEFAULT_TIMEOUT_SECONDS = 300 # 5 minutes
|
|
45
|
+
DEFAULT_CHECKPOINT_INTERVAL = 5 # Save checkpoint every N files
|
|
46
|
+
MAX_RETRIES = 3
|
|
47
|
+
BACKOFF_BASE = 2 # Exponential: 2^attempt seconds
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# ============================================================================
|
|
51
|
+
# Data Classes
|
|
52
|
+
# ============================================================================
|
|
53
|
+
|
|
54
|
+
@dataclass
|
|
55
|
+
class QueueItem:
|
|
56
|
+
"""Represents a file in the processing queue."""
|
|
57
|
+
file_path: str
|
|
58
|
+
priority: int = 0 # Higher = more priority
|
|
59
|
+
added_at: str = ""
|
|
60
|
+
attempts: int = 0
|
|
61
|
+
last_attempt: Optional[str] = None
|
|
62
|
+
status: str = "pending" # pending, processing, completed, failed, timeout
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass
|
|
66
|
+
class ProcessingResult:
|
|
67
|
+
"""Result of processing a single file."""
|
|
68
|
+
file_path: str
|
|
69
|
+
success: bool
|
|
70
|
+
error: Optional[str] = None
|
|
71
|
+
duration_seconds: float = 0
|
|
72
|
+
attempts: int = 1
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass
|
|
76
|
+
class ProcessorState:
|
|
77
|
+
"""Tracks the autonomous processor state."""
|
|
78
|
+
status: str = "idle" # idle, running, stopped, completed
|
|
79
|
+
started_at: Optional[str] = None
|
|
80
|
+
stopped_at: Optional[str] = None
|
|
81
|
+
files_processed: int = 0
|
|
82
|
+
files_failed: int = 0
|
|
83
|
+
current_file: Optional[str] = None
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@dataclass
|
|
87
|
+
class MonitoringStatus:
|
|
88
|
+
"""Real-time status for external monitoring."""
|
|
89
|
+
status: str # idle, running, stopped, completed
|
|
90
|
+
current_file: Optional[str]
|
|
91
|
+
files_in_queue: int
|
|
92
|
+
files_processed: int
|
|
93
|
+
files_failed: int
|
|
94
|
+
started_at: Optional[str]
|
|
95
|
+
last_updated: str
|
|
96
|
+
current_file_started: Optional[str]
|
|
97
|
+
estimated_remaining_files: int
|
|
98
|
+
avg_file_duration_seconds: float
|
|
99
|
+
error_rate_percent: float
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@dataclass
|
|
103
|
+
class Checkpoint:
|
|
104
|
+
"""Checkpoint for crash recovery."""
|
|
105
|
+
version: str = "1.0.0"
|
|
106
|
+
created_at: str = ""
|
|
107
|
+
queue_snapshot: List[Dict[str, Any]] = field(default_factory=list)
|
|
108
|
+
processor_state: Dict[str, Any] = field(default_factory=dict)
|
|
109
|
+
files_processed_since_start: int = 0
|
|
110
|
+
last_completed_file: Optional[str] = None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# ============================================================================
|
|
114
|
+
# FileQueue: FIFO Queue with Priority and Persistence
|
|
115
|
+
# ============================================================================
|
|
116
|
+
|
|
117
|
+
class FileQueue:
|
|
118
|
+
"""FIFO queue with priority support and persistence."""
|
|
119
|
+
|
|
120
|
+
def __init__(self):
|
|
121
|
+
self.items: List[QueueItem] = []
|
|
122
|
+
self._load()
|
|
123
|
+
|
|
124
|
+
def add(self, file_path: str, priority: int = 0) -> None:
|
|
125
|
+
"""Add file to queue. Higher priority = processed first."""
|
|
126
|
+
# Check if already in queue
|
|
127
|
+
for item in self.items:
|
|
128
|
+
if item.file_path == file_path and item.status in ['pending', 'processing']:
|
|
129
|
+
# Update priority if higher
|
|
130
|
+
if priority > item.priority:
|
|
131
|
+
item.priority = priority
|
|
132
|
+
self._save()
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
# Add new item
|
|
136
|
+
item = QueueItem(
|
|
137
|
+
file_path=file_path,
|
|
138
|
+
priority=priority,
|
|
139
|
+
added_at=datetime.utcnow().isoformat() + 'Z'
|
|
140
|
+
)
|
|
141
|
+
self.items.append(item)
|
|
142
|
+
self._save()
|
|
143
|
+
|
|
144
|
+
def pop(self) -> Optional[QueueItem]:
|
|
145
|
+
"""Get next file (highest priority first, then FIFO)."""
|
|
146
|
+
pending = [item for item in self.items if item.status == 'pending']
|
|
147
|
+
if not pending:
|
|
148
|
+
return None
|
|
149
|
+
|
|
150
|
+
# Sort by priority (desc) then added_at (asc)
|
|
151
|
+
pending.sort(key=lambda x: (-x.priority, x.added_at))
|
|
152
|
+
next_item = pending[0]
|
|
153
|
+
next_item.status = 'processing'
|
|
154
|
+
self._save()
|
|
155
|
+
return next_item
|
|
156
|
+
|
|
157
|
+
def peek(self) -> Optional[QueueItem]:
|
|
158
|
+
"""Preview next file without removing."""
|
|
159
|
+
pending = [item for item in self.items if item.status == 'pending']
|
|
160
|
+
if not pending:
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
pending.sort(key=lambda x: (-x.priority, x.added_at))
|
|
164
|
+
return pending[0]
|
|
165
|
+
|
|
166
|
+
def mark_complete(self, file_path: str, success: bool) -> None:
|
|
167
|
+
"""Mark file as completed or failed."""
|
|
168
|
+
for item in self.items:
|
|
169
|
+
if item.file_path == file_path:
|
|
170
|
+
item.status = 'completed' if success else 'failed'
|
|
171
|
+
item.last_attempt = datetime.utcnow().isoformat() + 'Z'
|
|
172
|
+
self._save()
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
def mark_timeout(self, file_path: str) -> None:
|
|
176
|
+
"""Mark file as timed out."""
|
|
177
|
+
for item in self.items:
|
|
178
|
+
if item.file_path == file_path:
|
|
179
|
+
item.status = 'timeout'
|
|
180
|
+
item.last_attempt = datetime.utcnow().isoformat() + 'Z'
|
|
181
|
+
self._save()
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
def get_pending(self) -> List[QueueItem]:
|
|
185
|
+
"""Get all pending items."""
|
|
186
|
+
return [item for item in self.items if item.status == 'pending']
|
|
187
|
+
|
|
188
|
+
def get_failed(self) -> List[QueueItem]:
|
|
189
|
+
"""Get all failed items (for retry consideration)."""
|
|
190
|
+
return [item for item in self.items if item.status in ['failed', 'timeout']]
|
|
191
|
+
|
|
192
|
+
def is_empty(self) -> bool:
|
|
193
|
+
"""Check if queue has no pending items."""
|
|
194
|
+
return len(self.get_pending()) == 0
|
|
195
|
+
|
|
196
|
+
def size(self) -> int:
|
|
197
|
+
"""Return count of pending items."""
|
|
198
|
+
return len(self.get_pending())
|
|
199
|
+
|
|
200
|
+
def _load(self) -> None:
|
|
201
|
+
"""Load queue from disk."""
|
|
202
|
+
if not QUEUE_STATE_PATH.exists():
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
with open(QUEUE_STATE_PATH, 'r') as f:
|
|
207
|
+
data = json.load(f)
|
|
208
|
+
|
|
209
|
+
self.items = [
|
|
210
|
+
QueueItem(**item) for item in data.get('items', [])
|
|
211
|
+
]
|
|
212
|
+
except Exception as e:
|
|
213
|
+
print(f"Warning: Failed to load queue state: {e}", file=sys.stderr)
|
|
214
|
+
|
|
215
|
+
def _save(self) -> None:
|
|
216
|
+
"""Persist queue to disk."""
|
|
217
|
+
QUEUE_STATE_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
218
|
+
|
|
219
|
+
data = {
|
|
220
|
+
'version': '1.0.0',
|
|
221
|
+
'updated_at': datetime.utcnow().isoformat() + 'Z',
|
|
222
|
+
'items': [asdict(item) for item in self.items]
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
with open(QUEUE_STATE_PATH, 'w') as f:
|
|
226
|
+
json.dump(data, f, indent=2)
|
|
227
|
+
|
|
228
|
+
def clear(self) -> None:
|
|
229
|
+
"""Clear all items."""
|
|
230
|
+
self.items = []
|
|
231
|
+
self._save()
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# ============================================================================
|
|
235
|
+
# AutonomousProcessor: Main Processing Engine
|
|
236
|
+
# ============================================================================
|
|
237
|
+
|
|
238
|
+
class TimeoutException(Exception):
|
|
239
|
+
"""Raised when file processing times out."""
|
|
240
|
+
pass
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _timeout_handler(signum, frame):
|
|
244
|
+
"""Signal handler for timeout."""
|
|
245
|
+
raise TimeoutException("Processing timeout exceeded")
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class AutonomousProcessor:
|
|
249
|
+
"""Main autonomous processing engine."""
|
|
250
|
+
|
|
251
|
+
def __init__(self, workflow_id: str = "wf-pipeline-full", checkpoint_interval: int = DEFAULT_CHECKPOINT_INTERVAL):
|
|
252
|
+
self.queue = FileQueue()
|
|
253
|
+
self.orchestrator = TaskOrchestrator(workflow_id)
|
|
254
|
+
self.state = self._load_state()
|
|
255
|
+
self.timeout_seconds = DEFAULT_TIMEOUT_SECONDS
|
|
256
|
+
self.checkpoint_interval = checkpoint_interval
|
|
257
|
+
self._files_since_checkpoint = 0
|
|
258
|
+
self._durations: List[float] = []
|
|
259
|
+
self._current_file_started: Optional[str] = None
|
|
260
|
+
self._last_completed_file: Optional[str] = None
|
|
261
|
+
|
|
262
|
+
def run(self, timeout_seconds: Optional[int] = None) -> Dict[str, Any]:
|
|
263
|
+
"""
|
|
264
|
+
Process files until queue empty or stop signal received.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
timeout_seconds: Override default timeout per file
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
Dict with stats: processed, failed, stopped_by
|
|
271
|
+
"""
|
|
272
|
+
if timeout_seconds:
|
|
273
|
+
self.timeout_seconds = timeout_seconds
|
|
274
|
+
|
|
275
|
+
# Clear stop signal if exists from previous run
|
|
276
|
+
self._clear_stop_signal()
|
|
277
|
+
|
|
278
|
+
# Initialize state
|
|
279
|
+
self.state.status = 'running'
|
|
280
|
+
self.state.started_at = datetime.utcnow().isoformat() + 'Z'
|
|
281
|
+
self.state.files_processed = 0
|
|
282
|
+
self.state.files_failed = 0
|
|
283
|
+
self._save_state()
|
|
284
|
+
|
|
285
|
+
# Update monitor at start
|
|
286
|
+
self._update_monitor()
|
|
287
|
+
|
|
288
|
+
stopped_by = None
|
|
289
|
+
|
|
290
|
+
try:
|
|
291
|
+
while not self.queue.is_empty() and not self._should_stop():
|
|
292
|
+
# Get next file
|
|
293
|
+
item = self.queue.pop()
|
|
294
|
+
if not item:
|
|
295
|
+
break
|
|
296
|
+
|
|
297
|
+
self.state.current_file = item.file_path
|
|
298
|
+
self._current_file_started = datetime.utcnow().isoformat() + 'Z'
|
|
299
|
+
self._save_state()
|
|
300
|
+
|
|
301
|
+
# Update monitor before processing
|
|
302
|
+
self._update_monitor()
|
|
303
|
+
|
|
304
|
+
# Log start
|
|
305
|
+
self._log_event({
|
|
306
|
+
'event': 'file_started',
|
|
307
|
+
'file': item.file_path,
|
|
308
|
+
'attempt': item.attempts + 1,
|
|
309
|
+
'priority': item.priority
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
# Process file
|
|
313
|
+
result = self._process_file(item)
|
|
314
|
+
|
|
315
|
+
# Track duration
|
|
316
|
+
self._durations.append(result.duration_seconds)
|
|
317
|
+
|
|
318
|
+
# Handle result
|
|
319
|
+
if result.success:
|
|
320
|
+
self.queue.mark_complete(item.file_path, True)
|
|
321
|
+
self.state.files_processed += 1
|
|
322
|
+
self._last_completed_file = item.file_path
|
|
323
|
+
self._log_event({
|
|
324
|
+
'event': 'file_completed',
|
|
325
|
+
'file': item.file_path,
|
|
326
|
+
'duration': result.duration_seconds
|
|
327
|
+
})
|
|
328
|
+
else:
|
|
329
|
+
# Check if should retry
|
|
330
|
+
item.attempts += 1
|
|
331
|
+
if self._should_retry(item):
|
|
332
|
+
# Re-queue with backoff
|
|
333
|
+
self._requeue_with_backoff(item)
|
|
334
|
+
self._log_event({
|
|
335
|
+
'event': 'file_requeued',
|
|
336
|
+
'file': item.file_path,
|
|
337
|
+
'attempt': item.attempts,
|
|
338
|
+
'backoff': self._calculate_backoff(item.attempts),
|
|
339
|
+
'error': result.error
|
|
340
|
+
})
|
|
341
|
+
else:
|
|
342
|
+
# Max retries exceeded
|
|
343
|
+
self.queue.mark_complete(item.file_path, False)
|
|
344
|
+
self.state.files_failed += 1
|
|
345
|
+
self._log_event({
|
|
346
|
+
'event': 'file_failed',
|
|
347
|
+
'file': item.file_path,
|
|
348
|
+
'attempts': item.attempts,
|
|
349
|
+
'error': result.error
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
self._save_state()
|
|
353
|
+
|
|
354
|
+
# Update monitor after processing
|
|
355
|
+
self._update_monitor()
|
|
356
|
+
|
|
357
|
+
# Checkpoint management
|
|
358
|
+
self._files_since_checkpoint += 1
|
|
359
|
+
if self._should_checkpoint():
|
|
360
|
+
self._save_checkpoint()
|
|
361
|
+
self._files_since_checkpoint = 0
|
|
362
|
+
|
|
363
|
+
# Determine why we stopped
|
|
364
|
+
if self._should_stop():
|
|
365
|
+
stopped_by = 'stop_signal'
|
|
366
|
+
self.state.status = 'stopped'
|
|
367
|
+
else:
|
|
368
|
+
stopped_by = 'queue_empty'
|
|
369
|
+
self.state.status = 'completed'
|
|
370
|
+
|
|
371
|
+
except Exception as e:
|
|
372
|
+
self.state.status = 'failed'
|
|
373
|
+
self._log_event({
|
|
374
|
+
'event': 'processor_error',
|
|
375
|
+
'error': str(e)
|
|
376
|
+
})
|
|
377
|
+
raise
|
|
378
|
+
|
|
379
|
+
finally:
|
|
380
|
+
self.state.stopped_at = datetime.utcnow().isoformat() + 'Z'
|
|
381
|
+
self.state.current_file = None
|
|
382
|
+
self._save_state()
|
|
383
|
+
|
|
384
|
+
# Final monitor update
|
|
385
|
+
self._update_monitor()
|
|
386
|
+
|
|
387
|
+
return {
|
|
388
|
+
'processed': self.state.files_processed,
|
|
389
|
+
'failed': self.state.files_failed,
|
|
390
|
+
'stopped_by': stopped_by,
|
|
391
|
+
'status': self.state.status
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
def stop(self) -> None:
|
|
395
|
+
"""Create stop signal file."""
|
|
396
|
+
STOP_SIGNAL_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
397
|
+
STOP_SIGNAL_PATH.touch()
|
|
398
|
+
|
|
399
|
+
def _should_stop(self) -> bool:
|
|
400
|
+
"""Check if stop signal exists."""
|
|
401
|
+
return STOP_SIGNAL_PATH.exists()
|
|
402
|
+
|
|
403
|
+
def _clear_stop_signal(self) -> None:
|
|
404
|
+
"""Remove stop signal file."""
|
|
405
|
+
if STOP_SIGNAL_PATH.exists():
|
|
406
|
+
STOP_SIGNAL_PATH.unlink()
|
|
407
|
+
|
|
408
|
+
def _process_file(self, item: QueueItem) -> ProcessingResult:
|
|
409
|
+
"""
|
|
410
|
+
Process a single file with timeout.
|
|
411
|
+
|
|
412
|
+
Uses signal.alarm() for timeout on Unix.
|
|
413
|
+
Wraps orchestrator.execute() call.
|
|
414
|
+
"""
|
|
415
|
+
start_time = time.time()
|
|
416
|
+
error = None
|
|
417
|
+
success = False
|
|
418
|
+
|
|
419
|
+
# Set up timeout (Unix only)
|
|
420
|
+
old_handler = None
|
|
421
|
+
try:
|
|
422
|
+
# Try to use signal (Unix/Linux/Mac)
|
|
423
|
+
if hasattr(signal, 'SIGALRM'):
|
|
424
|
+
old_handler = signal.signal(signal.SIGALRM, _timeout_handler)
|
|
425
|
+
signal.alarm(self.timeout_seconds)
|
|
426
|
+
|
|
427
|
+
# Execute via orchestrator
|
|
428
|
+
try:
|
|
429
|
+
result = self.orchestrator.execute({'files': [item.file_path]})
|
|
430
|
+
success = True
|
|
431
|
+
except TimeoutException:
|
|
432
|
+
error = f"Timeout after {self.timeout_seconds}s"
|
|
433
|
+
self.queue.mark_timeout(item.file_path)
|
|
434
|
+
except Exception as e:
|
|
435
|
+
error = str(e)
|
|
436
|
+
|
|
437
|
+
finally:
|
|
438
|
+
# Cancel timeout
|
|
439
|
+
if hasattr(signal, 'SIGALRM'):
|
|
440
|
+
signal.alarm(0)
|
|
441
|
+
if old_handler:
|
|
442
|
+
signal.signal(signal.SIGALRM, old_handler)
|
|
443
|
+
|
|
444
|
+
duration = time.time() - start_time
|
|
445
|
+
|
|
446
|
+
return ProcessingResult(
|
|
447
|
+
file_path=item.file_path,
|
|
448
|
+
success=success,
|
|
449
|
+
error=error,
|
|
450
|
+
duration_seconds=duration,
|
|
451
|
+
attempts=item.attempts + 1
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
def _should_retry(self, item: QueueItem) -> bool:
|
|
455
|
+
"""Check if item should be retried (attempts < MAX_RETRIES)."""
|
|
456
|
+
return item.attempts < MAX_RETRIES
|
|
457
|
+
|
|
458
|
+
def _calculate_backoff(self, attempts: int) -> float:
|
|
459
|
+
"""Calculate exponential backoff: 2^attempts seconds."""
|
|
460
|
+
return BACKOFF_BASE ** attempts
|
|
461
|
+
|
|
462
|
+
def _requeue_with_backoff(self, item: QueueItem) -> None:
|
|
463
|
+
"""Re-add item to queue after backoff delay."""
|
|
464
|
+
# Update item status and re-add
|
|
465
|
+
item.status = 'pending'
|
|
466
|
+
item.last_attempt = datetime.utcnow().isoformat() + 'Z'
|
|
467
|
+
# Note: Backoff is tracked but not enforced with sleep
|
|
468
|
+
# Caller can decide to delay processing if needed
|
|
469
|
+
|
|
470
|
+
def _load_state(self) -> ProcessorState:
|
|
471
|
+
"""Load processor state from disk."""
|
|
472
|
+
if not PROCESSOR_STATE_PATH.exists():
|
|
473
|
+
return ProcessorState()
|
|
474
|
+
|
|
475
|
+
try:
|
|
476
|
+
with open(PROCESSOR_STATE_PATH, 'r') as f:
|
|
477
|
+
data = json.load(f)
|
|
478
|
+
return ProcessorState(**data.get('state', {}))
|
|
479
|
+
except Exception as e:
|
|
480
|
+
print(f"Warning: Failed to load processor state: {e}", file=sys.stderr)
|
|
481
|
+
return ProcessorState()
|
|
482
|
+
|
|
483
|
+
def _save_state(self) -> None:
|
|
484
|
+
"""Persist processor state."""
|
|
485
|
+
PROCESSOR_STATE_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
486
|
+
|
|
487
|
+
data = {
|
|
488
|
+
'version': '1.0.0',
|
|
489
|
+
'updated_at': datetime.utcnow().isoformat() + 'Z',
|
|
490
|
+
'state': asdict(self.state)
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
with open(PROCESSOR_STATE_PATH, 'w') as f:
|
|
494
|
+
json.dump(data, f, indent=2)
|
|
495
|
+
|
|
496
|
+
def _log_event(self, event: Dict[str, Any]) -> None:
|
|
497
|
+
"""Append event to JSONL log."""
|
|
498
|
+
LOG_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
499
|
+
|
|
500
|
+
event['timestamp'] = datetime.utcnow().isoformat() + 'Z'
|
|
501
|
+
|
|
502
|
+
with open(LOG_PATH, 'a') as f:
|
|
503
|
+
f.write(json.dumps(event) + '\n')
|
|
504
|
+
|
|
505
|
+
def get_status(self) -> Dict[str, Any]:
|
|
506
|
+
"""Return current processor status."""
|
|
507
|
+
return {
|
|
508
|
+
'status': self.state.status,
|
|
509
|
+
'started_at': self.state.started_at,
|
|
510
|
+
'stopped_at': self.state.stopped_at,
|
|
511
|
+
'files_processed': self.state.files_processed,
|
|
512
|
+
'files_failed': self.state.files_failed,
|
|
513
|
+
'current_file': self.state.current_file,
|
|
514
|
+
'queue_size': self.queue.size(),
|
|
515
|
+
'queue_pending': len(self.queue.get_pending()),
|
|
516
|
+
'queue_failed': len(self.queue.get_failed())
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
def _calculate_avg_duration(self) -> float:
|
|
520
|
+
"""Calculate average file processing duration."""
|
|
521
|
+
if not self._durations:
|
|
522
|
+
return 0.0
|
|
523
|
+
return sum(self._durations) / len(self._durations)
|
|
524
|
+
|
|
525
|
+
def _update_monitor(self) -> None:
|
|
526
|
+
"""Update monitoring JSON file with current status."""
|
|
527
|
+
total_completed = self.state.files_processed + self.state.files_failed
|
|
528
|
+
error_rate = (self.state.files_failed / total_completed * 100) if total_completed > 0 else 0
|
|
529
|
+
avg_duration = self._calculate_avg_duration()
|
|
530
|
+
|
|
531
|
+
status = MonitoringStatus(
|
|
532
|
+
status=self.state.status,
|
|
533
|
+
current_file=self.state.current_file,
|
|
534
|
+
files_in_queue=self.queue.size(),
|
|
535
|
+
files_processed=self.state.files_processed,
|
|
536
|
+
files_failed=self.state.files_failed,
|
|
537
|
+
started_at=self.state.started_at,
|
|
538
|
+
last_updated=datetime.utcnow().isoformat() + 'Z',
|
|
539
|
+
current_file_started=self._current_file_started,
|
|
540
|
+
estimated_remaining_files=self.queue.size(),
|
|
541
|
+
avg_file_duration_seconds=avg_duration,
|
|
542
|
+
error_rate_percent=round(error_rate, 1)
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
MONITOR_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
546
|
+
with open(MONITOR_PATH, 'w') as f:
|
|
547
|
+
json.dump(asdict(status), f, indent=2)
|
|
548
|
+
|
|
549
|
+
def _save_checkpoint(self) -> None:
|
|
550
|
+
"""Save checkpoint for crash recovery."""
|
|
551
|
+
checkpoint = Checkpoint(
|
|
552
|
+
version="1.0.0",
|
|
553
|
+
created_at=datetime.utcnow().isoformat() + 'Z',
|
|
554
|
+
queue_snapshot=[asdict(item) for item in self.queue.items],
|
|
555
|
+
processor_state=asdict(self.state),
|
|
556
|
+
files_processed_since_start=self.state.files_processed,
|
|
557
|
+
last_completed_file=self._last_completed_file
|
|
558
|
+
)
|
|
559
|
+
|
|
560
|
+
CHECKPOINT_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
561
|
+
with open(CHECKPOINT_PATH, 'w') as f:
|
|
562
|
+
json.dump(asdict(checkpoint), f, indent=2)
|
|
563
|
+
|
|
564
|
+
self._log_event({
|
|
565
|
+
'event': 'checkpoint_saved',
|
|
566
|
+
'files_processed': self.state.files_processed,
|
|
567
|
+
'queue_size': self.queue.size()
|
|
568
|
+
})
|
|
569
|
+
|
|
570
|
+
def _should_checkpoint(self) -> bool:
|
|
571
|
+
"""Check if checkpoint should be saved (every N files)."""
|
|
572
|
+
return self._files_since_checkpoint >= self.checkpoint_interval
|
|
573
|
+
|
|
574
|
+
def _restore_from_checkpoint(self) -> bool:
|
|
575
|
+
"""Restore state from checkpoint if available."""
|
|
576
|
+
if not CHECKPOINT_PATH.exists():
|
|
577
|
+
return False
|
|
578
|
+
|
|
579
|
+
try:
|
|
580
|
+
with open(CHECKPOINT_PATH) as f:
|
|
581
|
+
data = json.load(f)
|
|
582
|
+
|
|
583
|
+
self.queue.items = [QueueItem(**item) for item in data['queue_snapshot']]
|
|
584
|
+
self.queue._save()
|
|
585
|
+
|
|
586
|
+
state_data = data['processor_state']
|
|
587
|
+
self.state = ProcessorState(**state_data)
|
|
588
|
+
|
|
589
|
+
self._log_event({
|
|
590
|
+
'event': 'checkpoint_restored',
|
|
591
|
+
'from_checkpoint': data['created_at'],
|
|
592
|
+
'queue_size': len(self.queue.items)
|
|
593
|
+
})
|
|
594
|
+
return True
|
|
595
|
+
except Exception as e:
|
|
596
|
+
self._log_event({'event': 'checkpoint_restore_failed', 'error': str(e)})
|
|
597
|
+
return False
|
|
598
|
+
|
|
599
|
+
def resume(self) -> Dict[str, Any]:
|
|
600
|
+
"""Resume processing from last checkpoint."""
|
|
601
|
+
restored = self._restore_from_checkpoint()
|
|
602
|
+
if not restored:
|
|
603
|
+
return {'success': False, 'error': 'No checkpoint found'}
|
|
604
|
+
return self.run()
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
# ============================================================================
|
|
608
|
+
# CLI Interface
|
|
609
|
+
# ============================================================================
|
|
610
|
+
|
|
611
|
+
def print_usage():
|
|
612
|
+
print("""
|
|
613
|
+
Autonomous Processor - Mega Brain Pipeline
|
|
614
|
+
===========================================
|
|
615
|
+
|
|
616
|
+
Usage:
|
|
617
|
+
python3 autonomous_processor.py <command> [args]
|
|
618
|
+
|
|
619
|
+
Commands:
|
|
620
|
+
queue add <file> [priority] Add file to queue
|
|
621
|
+
queue list List pending files
|
|
622
|
+
queue clear Clear queue
|
|
623
|
+
queue size Show queue size
|
|
624
|
+
run [--timeout=300] [--checkpoint=N] Start processing (checkpoint every N files, default=5)
|
|
625
|
+
stop Send stop signal
|
|
626
|
+
status Show processor status
|
|
627
|
+
monitor Show real-time monitoring status
|
|
628
|
+
checkpoint show Display current checkpoint
|
|
629
|
+
checkpoint clear Remove checkpoint file
|
|
630
|
+
resume Resume from last checkpoint
|
|
631
|
+
retry-failed Re-queue all failed files
|
|
632
|
+
|
|
633
|
+
Examples:
|
|
634
|
+
python3 autonomous_processor.py queue add inbox/file.txt 1
|
|
635
|
+
python3 autonomous_processor.py run --timeout=600 --checkpoint=10
|
|
636
|
+
python3 autonomous_processor.py monitor
|
|
637
|
+
python3 autonomous_processor.py resume
|
|
638
|
+
python3 autonomous_processor.py stop
|
|
639
|
+
""")
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
def main():
|
|
643
|
+
if len(sys.argv) < 2:
|
|
644
|
+
print_usage()
|
|
645
|
+
sys.exit(1)
|
|
646
|
+
|
|
647
|
+
command = sys.argv[1].lower()
|
|
648
|
+
|
|
649
|
+
if command == 'queue':
|
|
650
|
+
if len(sys.argv) < 3:
|
|
651
|
+
print_usage()
|
|
652
|
+
sys.exit(1)
|
|
653
|
+
|
|
654
|
+
subcommand = sys.argv[2].lower()
|
|
655
|
+
queue = FileQueue()
|
|
656
|
+
|
|
657
|
+
if subcommand == 'add':
|
|
658
|
+
if len(sys.argv) < 4:
|
|
659
|
+
print("Error: Missing file path")
|
|
660
|
+
sys.exit(1)
|
|
661
|
+
file_path = sys.argv[3]
|
|
662
|
+
priority = int(sys.argv[4]) if len(sys.argv) > 4 else 0
|
|
663
|
+
queue.add(file_path, priority)
|
|
664
|
+
print(f"Added: {file_path} (priority={priority})")
|
|
665
|
+
|
|
666
|
+
elif subcommand == 'list':
|
|
667
|
+
pending = queue.get_pending()
|
|
668
|
+
if not pending:
|
|
669
|
+
print("Queue is empty")
|
|
670
|
+
else:
|
|
671
|
+
print(f"Pending files ({len(pending)}):")
|
|
672
|
+
for item in pending:
|
|
673
|
+
print(f" [{item.priority}] {item.file_path}")
|
|
674
|
+
|
|
675
|
+
elif subcommand == 'clear':
|
|
676
|
+
queue.clear()
|
|
677
|
+
print("Queue cleared")
|
|
678
|
+
|
|
679
|
+
elif subcommand == 'size':
|
|
680
|
+
print(f"Queue size: {queue.size()}")
|
|
681
|
+
|
|
682
|
+
else:
|
|
683
|
+
print(f"Unknown queue command: {subcommand}")
|
|
684
|
+
sys.exit(1)
|
|
685
|
+
|
|
686
|
+
elif command == 'run':
|
|
687
|
+
timeout = DEFAULT_TIMEOUT_SECONDS
|
|
688
|
+
checkpoint_interval = DEFAULT_CHECKPOINT_INTERVAL
|
|
689
|
+
for arg in sys.argv[2:]:
|
|
690
|
+
if arg.startswith('--timeout='):
|
|
691
|
+
timeout = int(arg.split('=')[1])
|
|
692
|
+
elif arg.startswith('--checkpoint='):
|
|
693
|
+
checkpoint_interval = int(arg.split('=')[1])
|
|
694
|
+
|
|
695
|
+
processor = AutonomousProcessor(checkpoint_interval=checkpoint_interval)
|
|
696
|
+
print(f"Starting autonomous processing (timeout={timeout}s, checkpoint every {checkpoint_interval} files)...")
|
|
697
|
+
result = processor.run(timeout_seconds=timeout)
|
|
698
|
+
print(f"\nCompleted:")
|
|
699
|
+
print(f" Processed: {result['processed']}")
|
|
700
|
+
print(f" Failed: {result['failed']}")
|
|
701
|
+
print(f" Stopped by: {result['stopped_by']}")
|
|
702
|
+
|
|
703
|
+
elif command == 'stop':
|
|
704
|
+
processor = AutonomousProcessor()
|
|
705
|
+
processor.stop()
|
|
706
|
+
print("Stop signal sent")
|
|
707
|
+
|
|
708
|
+
elif command == 'status':
|
|
709
|
+
processor = AutonomousProcessor()
|
|
710
|
+
status = processor.get_status()
|
|
711
|
+
print("Processor Status:")
|
|
712
|
+
for key, value in status.items():
|
|
713
|
+
print(f" {key}: {value}")
|
|
714
|
+
|
|
715
|
+
elif command == 'monitor':
|
|
716
|
+
if not MONITOR_PATH.exists():
|
|
717
|
+
print("No monitoring data available")
|
|
718
|
+
else:
|
|
719
|
+
with open(MONITOR_PATH) as f:
|
|
720
|
+
data = json.load(f)
|
|
721
|
+
print("Real-time Monitoring:")
|
|
722
|
+
for key, value in data.items():
|
|
723
|
+
print(f" {key}: {value}")
|
|
724
|
+
|
|
725
|
+
elif command == 'checkpoint':
|
|
726
|
+
if len(sys.argv) < 3:
|
|
727
|
+
print("Usage: checkpoint [show|clear]")
|
|
728
|
+
sys.exit(1)
|
|
729
|
+
|
|
730
|
+
subcommand = sys.argv[2].lower()
|
|
731
|
+
if subcommand == 'show':
|
|
732
|
+
if not CHECKPOINT_PATH.exists():
|
|
733
|
+
print("No checkpoint available")
|
|
734
|
+
else:
|
|
735
|
+
with open(CHECKPOINT_PATH) as f:
|
|
736
|
+
data = json.load(f)
|
|
737
|
+
print("Checkpoint:")
|
|
738
|
+
print(f" Created: {data['created_at']}")
|
|
739
|
+
print(f" Files processed: {data['files_processed_since_start']}")
|
|
740
|
+
print(f" Queue items: {len(data['queue_snapshot'])}")
|
|
741
|
+
print(f" Last file: {data['last_completed_file']}")
|
|
742
|
+
elif subcommand == 'clear':
|
|
743
|
+
if CHECKPOINT_PATH.exists():
|
|
744
|
+
CHECKPOINT_PATH.unlink()
|
|
745
|
+
print("Checkpoint cleared")
|
|
746
|
+
else:
|
|
747
|
+
print("No checkpoint to clear")
|
|
748
|
+
else:
|
|
749
|
+
print(f"Unknown checkpoint command: {subcommand}")
|
|
750
|
+
|
|
751
|
+
elif command == 'resume':
|
|
752
|
+
processor = AutonomousProcessor()
|
|
753
|
+
print("Resuming from checkpoint...")
|
|
754
|
+
result = processor.resume()
|
|
755
|
+
if not result.get('success', True):
|
|
756
|
+
print(f"Resume failed: {result.get('error')}")
|
|
757
|
+
else:
|
|
758
|
+
print(f"\nCompleted:")
|
|
759
|
+
print(f" Processed: {result.get('processed', 0)}")
|
|
760
|
+
print(f" Failed: {result.get('failed', 0)}")
|
|
761
|
+
|
|
762
|
+
elif command == 'retry-failed':
|
|
763
|
+
queue = FileQueue()
|
|
764
|
+
failed = queue.get_failed()
|
|
765
|
+
if not failed:
|
|
766
|
+
print("No failed files to retry")
|
|
767
|
+
else:
|
|
768
|
+
for item in failed:
|
|
769
|
+
item.status = 'pending'
|
|
770
|
+
item.attempts = 0
|
|
771
|
+
queue._save()
|
|
772
|
+
print(f"Re-queued {len(failed)} failed files")
|
|
773
|
+
|
|
774
|
+
else:
|
|
775
|
+
print(f"Unknown command: {command}")
|
|
776
|
+
print_usage()
|
|
777
|
+
sys.exit(1)
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
if __name__ == '__main__':
|
|
781
|
+
main()
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
# ============================================================================
|
|
785
|
+
# Module Exports
|
|
786
|
+
# ============================================================================
|
|
787
|
+
|
|
788
|
+
__all__ = [
|
|
789
|
+
'AutonomousProcessor',
|
|
790
|
+
'FileQueue',
|
|
791
|
+
'QueueItem',
|
|
792
|
+
'ProcessingResult',
|
|
793
|
+
'ProcessorState',
|
|
794
|
+
'MonitoringStatus',
|
|
795
|
+
'Checkpoint',
|
|
796
|
+
]
|