@agentikos/omega-os 0.1.0 → 0.19.5
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/README.md +56 -14
- package/bootstrap/lib/__pycache__/claude-code-settings.cpython-313.pyc +0 -0
- package/bootstrap/lib/__pycache__/llm-clis.cpython-313.pyc +0 -0
- package/bootstrap/lib/__pycache__/manifest-helpers.cpython-313.pyc +0 -0
- package/bootstrap/lib/claude-code-settings.py +176 -0
- package/bootstrap/lib/common.sh +457 -1
- package/bootstrap/lib/llm-clis.py +341 -0
- package/bootstrap/lib/manifest-helpers.py +384 -0
- package/bootstrap/lib/steps.sh +1000 -26
- package/bootstrap/manifest.example.yaml +93 -2
- package/bootstrap/templates/aisb/CLAUDE.md +305 -0
- package/bootstrap/templates/aisb/architect.md +204 -0
- package/bootstrap/templates/aisb/checkers/CLAUDE.md +9 -0
- package/bootstrap/templates/aisb/checkers/checker-architect.md +151 -0
- package/bootstrap/templates/aisb/checkers/checker-common.md +171 -0
- package/bootstrap/templates/aisb/checkers/checker-construct.md +129 -0
- package/bootstrap/templates/aisb/checkers/checker-keymaker.md +204 -0
- package/bootstrap/templates/aisb/checkers/checker-link.md +205 -0
- package/bootstrap/templates/aisb/checkers/checker-merovingian.md +219 -0
- package/bootstrap/templates/aisb/checkers/checker-morpheus.md +211 -0
- package/bootstrap/templates/aisb/checkers/checker-neo.md +177 -0
- package/bootstrap/templates/aisb/checkers/checker-niobe.md +156 -0
- package/bootstrap/templates/aisb/checkers/checker-oracle.md +164 -0
- package/bootstrap/templates/aisb/checkers/checker-seraph.md +187 -0
- package/bootstrap/templates/aisb/checkers/checker-smith.md +195 -0
- package/bootstrap/templates/aisb/checkers/checker-zion.md +113 -0
- package/bootstrap/templates/aisb/construct.md +135 -0
- package/bootstrap/templates/aisb/keymaker.md +227 -0
- package/bootstrap/templates/aisb/link.md +170 -0
- package/bootstrap/templates/aisb/lmc-protocol.md +57 -0
- package/bootstrap/templates/aisb/merovingian.md +159 -0
- package/bootstrap/templates/aisb/morpheus.md +243 -0
- package/bootstrap/templates/aisb/neo.md +147 -0
- package/bootstrap/templates/aisb/niobe.md +197 -0
- package/bootstrap/templates/aisb/oracle.md +244 -0
- package/bootstrap/templates/aisb/protocols/handoff-templates.md +204 -0
- package/bootstrap/templates/aisb/protocols/shared-protocol.md +248 -0
- package/bootstrap/templates/aisb/pythia.md +153 -0
- package/bootstrap/templates/aisb/seraph.md +315 -0
- package/bootstrap/templates/aisb/smith.md +202 -0
- package/bootstrap/templates/aisb/zion.md +172 -0
- package/bootstrap/templates/autonomous/audit-patrol.yaml +41 -0
- package/bootstrap/templates/autonomous/smith-reflect.yaml +43 -0
- package/bootstrap/templates/autonomous/ssh-key-rotate.yaml +46 -0
- package/bootstrap/templates/autonomous/support-agent.yaml +38 -0
- package/docs/AUDITS.md +85 -0
- package/docs/COMPLETION-PLAN.md +48 -0
- package/docs/GAP-ANALYSIS.md +214 -0
- package/docs/INSTALL.md +47 -9
- package/docs/MCP-AND-PLUGINS.md +31 -4
- package/docs/SIMULATION.md +171 -0
- package/docs/simulate.sh +211 -0
- package/install.sh +164 -17
- package/omega/Agentik_Engine/README.md +27 -10
- package/omega/Agentik_Engine/omega_engine/__init__.py +212 -2
- package/omega/Agentik_Engine/omega_engine/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/account.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/agent_messages.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/aisb_chat.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/audit_diff.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/audit_gate.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/auto_update.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/autonomous.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/backup.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/cadence.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/classifier.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/cleanup.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/cli.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/completions.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/costs.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/done_signal.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/envelope.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/executor.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/handoff.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/hermes.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/hermes_bootstrap.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/hermes_desktop.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/learning.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/managed_agent.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/memory.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/menu.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/mission.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/plan.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/project.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/prompts.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/provider.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/prune.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/pursue.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/reducer.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/router.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/skill_routing.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/smoke.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/store.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/sync.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/telegram_history.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/tmux.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/tools.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/understand_anything.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/updater.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/validate.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/vault.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/webhooks.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/__pycache__/worker.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/account.py +502 -0
- package/omega/Agentik_Engine/omega_engine/agent_messages.py +167 -0
- package/omega/Agentik_Engine/omega_engine/aisb_chat.py +128 -0
- package/omega/Agentik_Engine/omega_engine/audit_diff.py +99 -0
- package/omega/Agentik_Engine/omega_engine/audit_gate.py +149 -0
- package/omega/Agentik_Engine/omega_engine/audits/__init__.py +60 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/batcher.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/dispatcher.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/generator.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/history.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/__pycache__/pipeline.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/audits/batcher.py +218 -0
- package/omega/Agentik_Engine/omega_engine/audits/dispatcher.py +92 -0
- package/omega/Agentik_Engine/omega_engine/audits/generator.py +234 -0
- package/omega/Agentik_Engine/omega_engine/audits/history.py +168 -0
- package/omega/Agentik_Engine/omega_engine/audits/pipeline.py +198 -0
- package/omega/Agentik_Engine/omega_engine/auto_update.py +339 -0
- package/omega/Agentik_Engine/omega_engine/autonomous.py +538 -0
- package/omega/Agentik_Engine/omega_engine/backup.py +215 -0
- package/omega/Agentik_Engine/omega_engine/cadence.py +158 -0
- package/omega/Agentik_Engine/omega_engine/classifier.py +215 -0
- package/omega/Agentik_Engine/omega_engine/cleanup.py +673 -0
- package/omega/Agentik_Engine/omega_engine/cli.py +4564 -56
- package/omega/Agentik_Engine/omega_engine/completions.py +260 -0
- package/omega/Agentik_Engine/omega_engine/costs.py +100 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__init__.py +14 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/autonomous.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/engine.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/daemons/__pycache__/telegram.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/daemons/autonomous.py +56 -0
- package/omega/Agentik_Engine/omega_engine/daemons/engine.py +236 -0
- package/omega/Agentik_Engine/omega_engine/daemons/telegram.py +315 -0
- package/omega/Agentik_Engine/omega_engine/done_signal.py +154 -0
- package/omega/Agentik_Engine/omega_engine/educators/__init__.py +51 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/artifact.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/automation.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/base.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/claudecode.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/connection.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/coworker.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/loop.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/prompt.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/__pycache__/skill.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/educators/artifact.py +65 -0
- package/omega/Agentik_Engine/omega_engine/educators/automation.py +76 -0
- package/omega/Agentik_Engine/omega_engine/educators/base.py +327 -0
- package/omega/Agentik_Engine/omega_engine/educators/claudecode.py +71 -0
- package/omega/Agentik_Engine/omega_engine/educators/connection.py +75 -0
- package/omega/Agentik_Engine/omega_engine/educators/coworker.py +68 -0
- package/omega/Agentik_Engine/omega_engine/educators/loop.py +82 -0
- package/omega/Agentik_Engine/omega_engine/educators/prompt.py +68 -0
- package/omega/Agentik_Engine/omega_engine/educators/skill.py +69 -0
- package/omega/Agentik_Engine/omega_engine/envelope.py +219 -0
- package/omega/Agentik_Engine/omega_engine/executor.py +195 -16
- package/omega/Agentik_Engine/omega_engine/genesis/__init__.py +134 -0
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/orchestrator.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/phases.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/stack.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/__pycache__/state.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/genesis/orchestrator.py +262 -0
- package/omega/Agentik_Engine/omega_engine/genesis/phases.py +950 -0
- package/omega/Agentik_Engine/omega_engine/genesis/stack.py +324 -0
- package/omega/Agentik_Engine/omega_engine/genesis/state.py +353 -0
- package/omega/Agentik_Engine/omega_engine/handoff.py +459 -0
- package/omega/Agentik_Engine/omega_engine/hermes.py +426 -0
- package/omega/Agentik_Engine/omega_engine/hermes_bootstrap.py +382 -0
- package/omega/Agentik_Engine/omega_engine/hermes_desktop.py +469 -0
- package/omega/Agentik_Engine/omega_engine/integrations/__init__.py +30 -0
- package/omega/Agentik_Engine/omega_engine/integrations/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/integrations/__pycache__/graphify.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/integrations/graphify.py +234 -0
- package/omega/Agentik_Engine/omega_engine/learning.py +268 -0
- package/omega/Agentik_Engine/omega_engine/managed_agent.py +467 -0
- package/omega/Agentik_Engine/omega_engine/memory.py +271 -0
- package/omega/Agentik_Engine/omega_engine/menu.py +1065 -0
- package/omega/Agentik_Engine/omega_engine/migrations/__init__.py +144 -0
- package/omega/Agentik_Engine/omega_engine/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/migrations/__pycache__/v0_14_0.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/migrations/v0_14_0.py +29 -0
- package/omega/Agentik_Engine/omega_engine/mission.py +29 -14
- package/omega/Agentik_Engine/omega_engine/plan.py +846 -0
- package/omega/Agentik_Engine/omega_engine/prompts.py +158 -0
- package/omega/Agentik_Engine/omega_engine/provider.py +408 -13
- package/omega/Agentik_Engine/omega_engine/prune.py +151 -0
- package/omega/Agentik_Engine/omega_engine/pursue.py +205 -0
- package/omega/Agentik_Engine/omega_engine/rag/__init__.py +21 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/agentic.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/base.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/corrective.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/graph.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/hybrid.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/multimodal.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/__pycache__/router.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/rag/agentic.py +83 -0
- package/omega/Agentik_Engine/omega_engine/rag/base.py +42 -0
- package/omega/Agentik_Engine/omega_engine/rag/corrective.py +119 -0
- package/omega/Agentik_Engine/omega_engine/rag/graph.py +169 -0
- package/omega/Agentik_Engine/omega_engine/rag/hybrid.py +205 -0
- package/omega/Agentik_Engine/omega_engine/rag/multimodal.py +136 -0
- package/omega/Agentik_Engine/omega_engine/rag/router.py +110 -0
- package/omega/Agentik_Engine/omega_engine/reducer.py +21 -3
- package/omega/Agentik_Engine/omega_engine/router.py +28 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__init__.py +48 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/__init__.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/auditor.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/finder.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/installer.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/__pycache__/marketplaces.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/auditor.py +232 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/finder.py +94 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/installer.py +129 -0
- package/omega/Agentik_Engine/omega_engine/skill_discovery/marketplaces.py +80 -0
- package/omega/Agentik_Engine/omega_engine/skill_routing.py +388 -0
- package/omega/Agentik_Engine/omega_engine/smoke.py +81 -0
- package/omega/Agentik_Engine/omega_engine/store.py +132 -25
- package/omega/Agentik_Engine/omega_engine/sync.py +445 -0
- package/omega/Agentik_Engine/omega_engine/telegram_history.py +260 -0
- package/omega/Agentik_Engine/omega_engine/tmux.py +526 -0
- package/omega/Agentik_Engine/omega_engine/tools.py +272 -0
- package/omega/Agentik_Engine/omega_engine/understand_anything.py +275 -0
- package/omega/Agentik_Engine/omega_engine/updater.py +70 -0
- package/omega/Agentik_Engine/omega_engine/validate.py +186 -0
- package/omega/Agentik_Engine/omega_engine/vault.py +342 -0
- package/omega/Agentik_Engine/omega_engine/webhooks.py +262 -0
- package/omega/Agentik_Engine/omega_engine/worker.py +526 -0
- package/omega/Agentik_Engine/pyproject.toml +1 -1
- package/omega/Agentik_Engine/tests/__pycache__/test_account.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_account.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_adversarial.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_adversarial.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_agents_envelope.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_agents_envelope.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_audit_arsenal.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_audits_pipeline.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_audits_pipeline.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_auto_update_and_migrations.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_auto_update_and_migrations.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_autonomous.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_autonomous.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_educators.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_educators.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_executor.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_genesis_and_plan.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_genesis_and_plan.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_graphify.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_graphify.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_handoff.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_handoff.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_hermes_and_ua.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_hermes_and_ua.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_hermes_bootstrap_and_desktop.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_hermes_bootstrap_and_desktop.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_install_steps.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_install_steps.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_install_ux.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_install_ux.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_installer_wiring.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_intelligence.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_intelligence.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_llm_clis_and_uninstall.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_llm_clis_and_uninstall.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_managed_agent.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_managed_agent.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_max_provider_and_menu.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_max_provider_and_menu.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_menu_coverage.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_menu_coverage.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_mission.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_progress.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_project.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_pursue_cadence.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_pursue_cadence.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_rag.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_rag.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_reducer.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_report.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_role_aliases_and_ssot.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_role_aliases_and_ssot.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_discovery_and_gate.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_discovery_and_gate.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_power.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_power.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_routing.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_skill_routing.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_snapshot_partial.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_snapshot_partial.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_telegram_history.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_telegram_history.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tmux_and_aisb_chat.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tmux_and_aisb_chat.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tools_and_sync.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_tools_and_sync.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_v06_features.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_v06_features.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_vault.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_vault.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_webhooks_and_readiness.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_webhooks_and_readiness.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_worker_and_cleanup.cpython-313-pytest-8.4.2.pyc +0 -0
- package/omega/Agentik_Engine/tests/__pycache__/test_worker_and_cleanup.cpython-313.pyc +0 -0
- package/omega/Agentik_Engine/tests/test_account.py +338 -0
- package/omega/Agentik_Engine/tests/test_adversarial.py +351 -0
- package/omega/Agentik_Engine/tests/test_agents_envelope.py +274 -0
- package/omega/Agentik_Engine/tests/test_audits_pipeline.py +348 -0
- package/omega/Agentik_Engine/tests/test_auto_update_and_migrations.py +394 -0
- package/omega/Agentik_Engine/tests/test_autonomous.py +361 -0
- package/omega/Agentik_Engine/tests/test_educators.py +233 -0
- package/omega/Agentik_Engine/tests/test_genesis_and_plan.py +573 -0
- package/omega/Agentik_Engine/tests/test_graphify.py +190 -0
- package/omega/Agentik_Engine/tests/test_handoff.py +311 -0
- package/omega/Agentik_Engine/tests/test_hermes_and_ua.py +387 -0
- package/omega/Agentik_Engine/tests/test_hermes_bootstrap_and_desktop.py +358 -0
- package/omega/Agentik_Engine/tests/test_install_steps.py +359 -0
- package/omega/Agentik_Engine/tests/test_install_ux.py +151 -0
- package/omega/Agentik_Engine/tests/test_installer_wiring.py +496 -0
- package/omega/Agentik_Engine/tests/test_intelligence.py +285 -0
- package/omega/Agentik_Engine/tests/test_llm_clis_and_uninstall.py +228 -0
- package/omega/Agentik_Engine/tests/test_managed_agent.py +363 -0
- package/omega/Agentik_Engine/tests/test_max_provider_and_menu.py +231 -0
- package/omega/Agentik_Engine/tests/test_menu_coverage.py +72 -0
- package/omega/Agentik_Engine/tests/test_pursue_cadence.py +217 -0
- package/omega/Agentik_Engine/tests/test_rag.py +287 -0
- package/omega/Agentik_Engine/tests/test_role_aliases_and_ssot.py +207 -0
- package/omega/Agentik_Engine/tests/test_skill_discovery_and_gate.py +337 -0
- package/omega/Agentik_Engine/tests/test_skill_power.py +259 -0
- package/omega/Agentik_Engine/tests/test_skill_routing.py +189 -0
- package/omega/Agentik_Engine/tests/test_snapshot_partial.py +172 -0
- package/omega/Agentik_Engine/tests/test_telegram_history.py +209 -0
- package/omega/Agentik_Engine/tests/test_tmux_and_aisb_chat.py +223 -0
- package/omega/Agentik_Engine/tests/test_tools_and_sync.py +312 -0
- package/omega/Agentik_Engine/tests/test_v06_features.py +370 -0
- package/omega/Agentik_Engine/tests/test_vault.py +173 -0
- package/omega/Agentik_Engine/tests/test_webhooks_and_readiness.py +277 -0
- package/omega/Agentik_Engine/tests/test_worker_and_cleanup.py +541 -0
- package/omega/Agentik_Extra/etc/secrets/.vault-key +3 -0
- package/omega/Agentik_Extra/etc/secrets/.vault-pub +1 -0
- package/omega/Agentik_Runtime/audits.db +0 -0
- package/omega/Agentik_SSOT/VERSION +1 -1
- package/omega/Agentik_SSOT/claude-plugins/claude-plugins.yaml +100 -0
- package/omega/Agentik_SSOT/docs/LAYERS.md +90 -0
- package/omega/Agentik_SSOT/docs/USER-JOURNEY.md +283 -0
- package/omega/Agentik_SSOT/marketplaces/design-discipline.yaml +86 -0
- package/omega/Agentik_SSOT/skills/a11yaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/apiaudit/SKILL.md +157 -0
- package/omega/Agentik_SSOT/skills/automationaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/cadence/SKILL.md +76 -0
- package/omega/Agentik_SSOT/skills/codeaudit/SKILL.md +153 -0
- package/omega/Agentik_SSOT/skills/copyaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/dataaudit/SKILL.md +157 -0
- package/omega/Agentik_SSOT/skills/debugaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/dispatch/SKILL.md +79 -0
- package/omega/Agentik_SSOT/skills/dxaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/featureaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/flowaudit/SKILL.md +165 -0
- package/omega/Agentik_SSOT/skills/genesis/SKILL.md +116 -0
- package/omega/Agentik_SSOT/skills/handoff/SKILL.md +117 -0
- package/omega/Agentik_SSOT/skills/logicaudit/SKILL.md +165 -0
- package/omega/Agentik_SSOT/skills/motionaudit/SKILL.md +165 -0
- package/omega/Agentik_SSOT/skills/perfaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/plan/SKILL.md +127 -0
- package/omega/Agentik_SSOT/skills/pursue/SKILL.md +68 -0
- package/omega/Agentik_SSOT/skills/rag-route.md +82 -0
- package/omega/Agentik_SSOT/skills/refontaudit/SKILL.md +165 -0
- package/omega/Agentik_SSOT/skills/retentionaudit/SKILL.md +165 -0
- package/omega/Agentik_SSOT/skills/secaudit/SKILL.md +157 -0
- package/omega/Agentik_SSOT/skills/seoaudit/SKILL.md +161 -0
- package/omega/Agentik_SSOT/skills/skill-auditor/SKILL.md +83 -0
- package/omega/Agentik_SSOT/skills/skill-finder/SKILL.md +116 -0
- package/omega/Agentik_SSOT/skills/uiuxaudit/SKILL.md +165 -0
- package/package.json +2 -2
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""AISB chat-loop — talk to the AISB master agent like it was Telegram.
|
|
2
|
+
|
|
3
|
+
The user often runs OmegaOS in places where Telegram isn't connected
|
|
4
|
+
(fresh VPS, the operator on a different machine, etc.). The AISB chat
|
|
5
|
+
loop is the fallback: spawn `tmux new-session -s AISB-chat` running
|
|
6
|
+
this loop, attach, and you get a REPL-style conversation with the AISB
|
|
7
|
+
master agent — same envelope, same .done.json contract, but stdin /
|
|
8
|
+
stdout instead of Telegram.
|
|
9
|
+
|
|
10
|
+
Conversation history is persisted in
|
|
11
|
+
``Agentik_Runtime/telegram-history.db`` under topic_id = -1 (a sentinel
|
|
12
|
+
"chat-loop" topic) so we share the same history layer the Telegram
|
|
13
|
+
daemon already uses. The user sees prior turns at the top of each new
|
|
14
|
+
session.
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
import sys
|
|
20
|
+
import time
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
CHAT_TOPIC = -1
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _omega_home() -> Path:
|
|
28
|
+
return Path(os.environ.get("OMEGA_HOME", str(Path.home() / "Omega")))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _print_banner() -> None:
|
|
32
|
+
print("─" * 60)
|
|
33
|
+
print(" AISB chat — Telegram-equivalent fallback")
|
|
34
|
+
print(f" history persisted under topic_id={CHAT_TOPIC}")
|
|
35
|
+
print(" type /quit to exit, /history to show the last 10 turns,")
|
|
36
|
+
print(" /clear to wipe this session's history")
|
|
37
|
+
print("─" * 60)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _print_history(home: Path, limit: int = 10) -> None:
|
|
41
|
+
from omega_engine.telegram_history import recent_messages
|
|
42
|
+
msgs = recent_messages(home, topic_id=CHAT_TOPIC, limit=limit)
|
|
43
|
+
if not msgs:
|
|
44
|
+
print(" (no history yet)")
|
|
45
|
+
return
|
|
46
|
+
for m in msgs:
|
|
47
|
+
print(f" {m.role}: {m.text[:300]}")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _clear_history(home: Path) -> int:
|
|
51
|
+
from omega_engine.telegram_history import _connect
|
|
52
|
+
conn = _connect(home)
|
|
53
|
+
try:
|
|
54
|
+
cur = conn.execute(
|
|
55
|
+
"DELETE FROM messages WHERE topic_id = ?", (CHAT_TOPIC,),
|
|
56
|
+
)
|
|
57
|
+
conn.commit()
|
|
58
|
+
return int(cur.rowcount or 0)
|
|
59
|
+
finally:
|
|
60
|
+
conn.close()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def run_chat_loop() -> int:
|
|
64
|
+
"""Block until /quit. Returns 0 on clean exit."""
|
|
65
|
+
home = _omega_home()
|
|
66
|
+
from omega_engine.envelope import EnvelopeContext, build_envelope
|
|
67
|
+
from omega_engine.provider import AgentRequest
|
|
68
|
+
from omega_engine.router import ModelRouter
|
|
69
|
+
from omega_engine.telegram_history import (
|
|
70
|
+
build_context_prompt, record_inbound, record_outbound,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
_print_banner()
|
|
74
|
+
router = ModelRouter.auto()
|
|
75
|
+
|
|
76
|
+
while True:
|
|
77
|
+
try:
|
|
78
|
+
line = input("\nyou > ").strip()
|
|
79
|
+
except (EOFError, KeyboardInterrupt):
|
|
80
|
+
print("\n(exit)")
|
|
81
|
+
return 0
|
|
82
|
+
if not line:
|
|
83
|
+
continue
|
|
84
|
+
if line == "/quit":
|
|
85
|
+
print("(exit)")
|
|
86
|
+
return 0
|
|
87
|
+
if line == "/history":
|
|
88
|
+
_print_history(home)
|
|
89
|
+
continue
|
|
90
|
+
if line == "/clear":
|
|
91
|
+
n = _clear_history(home)
|
|
92
|
+
print(f"(cleared {n} message(s))")
|
|
93
|
+
continue
|
|
94
|
+
|
|
95
|
+
# Record the user's turn.
|
|
96
|
+
record_inbound(home, topic_id=CHAT_TOPIC, text=line)
|
|
97
|
+
|
|
98
|
+
# Build the AISB envelope — same one the engine uses everywhere.
|
|
99
|
+
enriched = build_context_prompt(
|
|
100
|
+
home, topic_id=CHAT_TOPIC, new_intent=line, limit=10,
|
|
101
|
+
)
|
|
102
|
+
ctx = EnvelopeContext(
|
|
103
|
+
role="aisb",
|
|
104
|
+
intent=enriched,
|
|
105
|
+
task_id=f"chat-{int(time.time())}",
|
|
106
|
+
)
|
|
107
|
+
env = build_envelope(home, ctx)
|
|
108
|
+
provider = router.resolve("aisb")
|
|
109
|
+
try:
|
|
110
|
+
result = provider.run(AgentRequest(
|
|
111
|
+
role="aisb", prompt=env["user"], context={},
|
|
112
|
+
system=env["system"],
|
|
113
|
+
))
|
|
114
|
+
except Exception as exc: # noqa: BLE001
|
|
115
|
+
print(f"aisb (error): {exc}")
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
reply = (result.text or "").strip() or "(empty reply)"
|
|
119
|
+
record_outbound(home, topic_id=CHAT_TOPIC, text=reply)
|
|
120
|
+
print(f"\naisb > {reply}")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def main(argv: list[str] | None = None) -> int:
|
|
124
|
+
return run_chat_loop()
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
sys.exit(main())
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""`omega audit diff <run-id-1> <run-id-2>` — compare two forensic-audit runs.
|
|
2
|
+
|
|
3
|
+
Given two run ids (same audit usually, but different audits also work),
|
|
4
|
+
report:
|
|
5
|
+
|
|
6
|
+
* Score delta (run1 → run2)
|
|
7
|
+
* Findings that were FIXED (in run1, gone in run2)
|
|
8
|
+
* Findings that are NEW (in run2, weren't in run1)
|
|
9
|
+
* Findings that PERSIST (in both — the operator hasn't fixed them yet)
|
|
10
|
+
* Findings that REGRESSED (severity went UP in run2)
|
|
11
|
+
|
|
12
|
+
We dedupe by `(phase, location, message)` — same finding location is
|
|
13
|
+
considered "the same issue" across runs. This is a heuristic; for
|
|
14
|
+
findings without locations (architectural) we dedupe by phase+message.
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class FindingKey:
|
|
25
|
+
phase: str
|
|
26
|
+
location: str
|
|
27
|
+
message: str
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class AuditDiff:
|
|
32
|
+
run1: str
|
|
33
|
+
run2: str
|
|
34
|
+
audit_id: str
|
|
35
|
+
score1: int
|
|
36
|
+
score2: int
|
|
37
|
+
fixed: list[dict[str, Any]] = field(default_factory=list)
|
|
38
|
+
new: list[dict[str, Any]] = field(default_factory=list)
|
|
39
|
+
persist: list[dict[str, Any]] = field(default_factory=list)
|
|
40
|
+
regressed: list[dict[str, Any]] = field(default_factory=list)
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def delta(self) -> int:
|
|
44
|
+
return self.score2 - self.score1
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
_SEVERITY_RANK = {"low": 0, "medium": 1, "med": 1,
|
|
48
|
+
"high": 2, "critical": 3, "crit": 3}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _finding_key(f: dict) -> FindingKey:
|
|
52
|
+
return FindingKey(
|
|
53
|
+
phase=str(f.get("phase", "?")),
|
|
54
|
+
location=str(f.get("location", f.get("file", "?"))),
|
|
55
|
+
message=str(f.get("message", f.get("claim", "")))[:120],
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _by_key(findings: list[dict]) -> dict[FindingKey, dict]:
|
|
60
|
+
return {_finding_key(f): f for f in findings}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def diff_runs(
|
|
64
|
+
omega_home: str | Path, run1: str, run2: str,
|
|
65
|
+
) -> AuditDiff:
|
|
66
|
+
"""Load two audit runs from history and produce a structured diff."""
|
|
67
|
+
from omega_engine.audits.history import list_runs
|
|
68
|
+
|
|
69
|
+
runs = list_runs(omega_home, audit_id=None, limit=1000)
|
|
70
|
+
by_id = {r.run_id: r for r in runs}
|
|
71
|
+
r1 = by_id.get(run1)
|
|
72
|
+
r2 = by_id.get(run2)
|
|
73
|
+
if r1 is None:
|
|
74
|
+
raise KeyError(f"run not found: {run1}")
|
|
75
|
+
if r2 is None:
|
|
76
|
+
raise KeyError(f"run not found: {run2}")
|
|
77
|
+
|
|
78
|
+
findings1 = list(r1.verdict.get("findings") or [])
|
|
79
|
+
findings2 = list(r2.verdict.get("findings") or [])
|
|
80
|
+
map1 = _by_key(findings1)
|
|
81
|
+
map2 = _by_key(findings2)
|
|
82
|
+
|
|
83
|
+
fixed = [map1[k] for k in (map1.keys() - map2.keys())]
|
|
84
|
+
new = [map2[k] for k in (map2.keys() - map1.keys())]
|
|
85
|
+
persist_keys = map1.keys() & map2.keys()
|
|
86
|
+
persist = [map2[k] for k in persist_keys]
|
|
87
|
+
regressed = []
|
|
88
|
+
for k in persist_keys:
|
|
89
|
+
s1 = _SEVERITY_RANK.get(str(map1[k].get("severity", "medium")).lower(), 1)
|
|
90
|
+
s2 = _SEVERITY_RANK.get(str(map2[k].get("severity", "medium")).lower(), 1)
|
|
91
|
+
if s2 > s1:
|
|
92
|
+
regressed.append(map2[k])
|
|
93
|
+
|
|
94
|
+
return AuditDiff(
|
|
95
|
+
run1=run1, run2=run2,
|
|
96
|
+
audit_id=str(r2.audit_id),
|
|
97
|
+
score1=int(r1.score), score2=int(r2.score),
|
|
98
|
+
fixed=fixed, new=new, persist=persist, regressed=regressed,
|
|
99
|
+
)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""`omega audit gate` — the Claude Code Stop-hook gatekeeper.
|
|
2
|
+
|
|
3
|
+
When ``claude_code_settings.audit_gate: true`` is set in the install
|
|
4
|
+
manifest, the installer writes a ``Stop`` hook into
|
|
5
|
+
``~/.claude/settings.json`` that calls this command. The hook fires
|
|
6
|
+
whenever Claude is about to say "I'm done" — and this command decides
|
|
7
|
+
whether the audit verdicts let it.
|
|
8
|
+
|
|
9
|
+
Flow:
|
|
10
|
+
|
|
11
|
+
1. Claude finishes a turn.
|
|
12
|
+
2. Claude Code triggers the ``Stop`` hook.
|
|
13
|
+
3. ``omega audit gate`` reads the hook JSON from stdin
|
|
14
|
+
(``{session_id, cwd, ...}``).
|
|
15
|
+
4. We look at the per-session ``.done.json`` and the audit history
|
|
16
|
+
for the same scope.
|
|
17
|
+
5. If the most recent ``.done.json`` has ``status == "failed"`` OR
|
|
18
|
+
the latest audit run for the cwd has ``verified=False``, we
|
|
19
|
+
emit ``permissionDecision: deny`` with a clear reason. Claude
|
|
20
|
+
must keep working.
|
|
21
|
+
6. Otherwise we exit 0 silently and the Stop proceeds.
|
|
22
|
+
|
|
23
|
+
This is the killer rule that closes the "Claude says done but isn't"
|
|
24
|
+
loophole — at the *editor* level, not just the engine.
|
|
25
|
+
"""
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import json
|
|
29
|
+
import os
|
|
30
|
+
import sys
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
from typing import Any
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _omega_home() -> Path:
|
|
36
|
+
return Path(os.environ.get("OMEGA_HOME", str(Path.home() / "Omega")))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _read_hook_input() -> dict[str, Any]:
|
|
40
|
+
"""Best-effort JSON read from stdin; an empty dict on failure."""
|
|
41
|
+
try:
|
|
42
|
+
raw = sys.stdin.read()
|
|
43
|
+
except Exception: # noqa: BLE001
|
|
44
|
+
return {}
|
|
45
|
+
if not raw.strip():
|
|
46
|
+
return {}
|
|
47
|
+
try:
|
|
48
|
+
return json.loads(raw)
|
|
49
|
+
except json.JSONDecodeError:
|
|
50
|
+
return {}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _latest_done(home: Path, session_id: str) -> dict[str, Any] | None:
|
|
54
|
+
"""Return the latest .done.json content for the session, or None."""
|
|
55
|
+
if not session_id:
|
|
56
|
+
return None
|
|
57
|
+
sess_root = home / "Agentik_Runtime" / "sessions"
|
|
58
|
+
candidates = list(sess_root.glob(f"*{session_id}*/.done.json"))
|
|
59
|
+
if not candidates:
|
|
60
|
+
return None
|
|
61
|
+
# newest by mtime
|
|
62
|
+
latest = max(candidates, key=lambda p: p.stat().st_mtime)
|
|
63
|
+
try:
|
|
64
|
+
return json.loads(latest.read_text())
|
|
65
|
+
except (json.JSONDecodeError, OSError):
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _latest_audit_failed(home: Path) -> tuple[bool, str]:
|
|
70
|
+
"""Return (failed, message). True if the latest audit run was not verified."""
|
|
71
|
+
try:
|
|
72
|
+
from omega_engine.audits.history import list_runs
|
|
73
|
+
except ImportError:
|
|
74
|
+
return False, ""
|
|
75
|
+
runs = list_runs(home, audit_id=None, limit=1)
|
|
76
|
+
if not runs:
|
|
77
|
+
return False, ""
|
|
78
|
+
r = runs[0]
|
|
79
|
+
if r.verified:
|
|
80
|
+
return False, ""
|
|
81
|
+
return True, (
|
|
82
|
+
f"audit '{r.audit_id}' run {r.run_id} scored {r.score} "
|
|
83
|
+
f"(threshold not met). Fix the findings before declaring done."
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _deny(reason: str) -> None:
|
|
88
|
+
"""Emit the hookSpecificOutput payload that denies the Stop."""
|
|
89
|
+
payload = {
|
|
90
|
+
"continue": False,
|
|
91
|
+
"stopReason": reason,
|
|
92
|
+
"systemMessage": f"omega audit gate: {reason}",
|
|
93
|
+
"hookSpecificOutput": {
|
|
94
|
+
"hookEventName": "Stop",
|
|
95
|
+
"permissionDecision": "deny",
|
|
96
|
+
"permissionDecisionReason": reason,
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
print(json.dumps(payload))
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def gate(input_payload: dict[str, Any] | None = None) -> int:
|
|
103
|
+
"""Decide whether to allow the Stop. Returns the exit code.
|
|
104
|
+
|
|
105
|
+
Exit 0 = allow (silent). Exit 2 + JSON on stdout = deny.
|
|
106
|
+
Other failures → exit 0 (we never break the editor on our own bugs).
|
|
107
|
+
"""
|
|
108
|
+
home = _omega_home()
|
|
109
|
+
data = input_payload if input_payload is not None else _read_hook_input()
|
|
110
|
+
|
|
111
|
+
session_id = str(data.get("session_id") or "")
|
|
112
|
+
|
|
113
|
+
# 1. Did the worker explicitly write status=failed?
|
|
114
|
+
done = _latest_done(home, session_id)
|
|
115
|
+
if done and done.get("status") == "failed":
|
|
116
|
+
errs = ", ".join(done.get("errors") or [])[:300] or "no detail"
|
|
117
|
+
_deny(
|
|
118
|
+
f"worker reported status=failed in .done.json ({errs}). "
|
|
119
|
+
"Resume the task or revise."
|
|
120
|
+
)
|
|
121
|
+
return 2
|
|
122
|
+
|
|
123
|
+
# 2. Did the worker leave pending actions un-actioned?
|
|
124
|
+
if done and done.get("status") == "pending":
|
|
125
|
+
pa = done.get("pending_actions") or []
|
|
126
|
+
if pa:
|
|
127
|
+
_deny(
|
|
128
|
+
f"worker reported status=pending with {len(pa)} pending "
|
|
129
|
+
f"action(s): {pa[:3]}. Resolve or hand off explicitly."
|
|
130
|
+
)
|
|
131
|
+
return 2
|
|
132
|
+
|
|
133
|
+
# 3. Is the latest forensic audit verdict still failing?
|
|
134
|
+
failed, msg = _latest_audit_failed(home)
|
|
135
|
+
if failed:
|
|
136
|
+
_deny(msg)
|
|
137
|
+
return 2
|
|
138
|
+
|
|
139
|
+
# All clear.
|
|
140
|
+
return 0
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def main(argv: list[str] | None = None) -> int:
|
|
144
|
+
"""Entry point for the `omega audit gate` CLI."""
|
|
145
|
+
return gate()
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
if __name__ == "__main__":
|
|
149
|
+
sys.exit(main())
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Audits package — the 100% mega powerful Quality Arsenal layer.
|
|
2
|
+
|
|
3
|
+
What lives here:
|
|
4
|
+
|
|
5
|
+
* ``pipeline.AuditPipeline`` — gather + analyse + batch + dispatch +
|
|
6
|
+
re-audit + record, all in one call.
|
|
7
|
+
* ``batcher.batch_findings`` — cluster findings into ≤N disjoint
|
|
8
|
+
worker batches.
|
|
9
|
+
* ``dispatcher.dispatch_fixes`` — spawn a worker per batch via the
|
|
10
|
+
engine's executor.
|
|
11
|
+
* ``history.*`` — SQLite-backed score history per audit.
|
|
12
|
+
* ``generator.write_all`` — produce ``SKILL.md`` for every audit.
|
|
13
|
+
|
|
14
|
+
The existing forensic primitives (``Audit``, ``AuditRegistry``,
|
|
15
|
+
``run_forensic_audit``, ``ArsenalGate``) stay in
|
|
16
|
+
``omega_engine.audit_arsenal`` — this package builds the next layer on top.
|
|
17
|
+
"""
|
|
18
|
+
from omega_engine.audits.batcher import (
|
|
19
|
+
Batch,
|
|
20
|
+
BatchPlan,
|
|
21
|
+
Finding,
|
|
22
|
+
batch_findings,
|
|
23
|
+
)
|
|
24
|
+
from omega_engine.audits.dispatcher import (
|
|
25
|
+
DispatchResult,
|
|
26
|
+
dispatch_fixes,
|
|
27
|
+
)
|
|
28
|
+
from omega_engine.audits.generator import (
|
|
29
|
+
AuditSkillFile,
|
|
30
|
+
generate_all,
|
|
31
|
+
generate_skill,
|
|
32
|
+
write_all,
|
|
33
|
+
)
|
|
34
|
+
from omega_engine.audits.history import (
|
|
35
|
+
AuditRun,
|
|
36
|
+
latest_score,
|
|
37
|
+
list_runs,
|
|
38
|
+
make_run_id,
|
|
39
|
+
record_run,
|
|
40
|
+
trend,
|
|
41
|
+
)
|
|
42
|
+
from omega_engine.audits.pipeline import (
|
|
43
|
+
AuditOutcome,
|
|
44
|
+
AuditPipeline,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
__all__ = [
|
|
49
|
+
# pipeline
|
|
50
|
+
"AuditPipeline", "AuditOutcome",
|
|
51
|
+
# batcher
|
|
52
|
+
"Finding", "Batch", "BatchPlan", "batch_findings",
|
|
53
|
+
# dispatcher
|
|
54
|
+
"DispatchResult", "dispatch_fixes",
|
|
55
|
+
# history
|
|
56
|
+
"AuditRun", "record_run", "list_runs", "latest_score", "trend",
|
|
57
|
+
"make_run_id",
|
|
58
|
+
# generator
|
|
59
|
+
"AuditSkillFile", "generate_skill", "generate_all", "write_all",
|
|
60
|
+
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""Smart finding batcher — cluster audit findings into ≤N worker batches.
|
|
2
|
+
|
|
3
|
+
The user's hard constraint: fix the issues found, but DO NOT spawn one
|
|
4
|
+
worker per finding (that would explode parallelism and overwhelm the
|
|
5
|
+
system). Instead:
|
|
6
|
+
|
|
7
|
+
* Group findings by their file footprint.
|
|
8
|
+
* Pack groups into a small number of batches (default 3).
|
|
9
|
+
* Two batches MUST have disjoint file sets — never let two workers race
|
|
10
|
+
on the same file.
|
|
11
|
+
* Findings with no file location ("architectural") get their own batch.
|
|
12
|
+
* If total batches would exceed the cap, prefer the highest-severity
|
|
13
|
+
ones and emit a ``deferred`` list for the rest.
|
|
14
|
+
|
|
15
|
+
This module is pure logic — no I/O, no subprocess. The dispatcher
|
|
16
|
+
(``omega_engine.audits.dispatcher``) consumes the result and actually
|
|
17
|
+
spawns workers.
|
|
18
|
+
"""
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from collections import defaultdict
|
|
22
|
+
from dataclasses import dataclass, field
|
|
23
|
+
from typing import Any, Iterable
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
SEVERITY_WEIGHT = {
|
|
27
|
+
"critical": 100, "crit": 100,
|
|
28
|
+
"high": 30,
|
|
29
|
+
"medium": 10, "med": 10,
|
|
30
|
+
"low": 3,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _severity_weight(severity: str) -> int:
|
|
35
|
+
return SEVERITY_WEIGHT.get(severity.lower().strip(), 5)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class Finding:
|
|
40
|
+
"""A normalised finding used by the batcher.
|
|
41
|
+
|
|
42
|
+
Constructed from either an ``ArsenalFinding`` (the structured form
|
|
43
|
+
emitted by the forensic gate) or a raw dict.
|
|
44
|
+
"""
|
|
45
|
+
audit: str
|
|
46
|
+
phase: str
|
|
47
|
+
severity: str
|
|
48
|
+
file: str | None
|
|
49
|
+
line: int | None
|
|
50
|
+
message: str
|
|
51
|
+
fix_hint: str = ""
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def from_arsenal(f: Any) -> "Finding":
|
|
55
|
+
"""Build from an `ArsenalFinding` (duck-typed for testability)."""
|
|
56
|
+
loc = getattr(f, "location", "?") or "?"
|
|
57
|
+
file, line = _parse_location(loc)
|
|
58
|
+
return Finding(
|
|
59
|
+
audit=getattr(f, "audit", "?"),
|
|
60
|
+
phase=getattr(f, "phase", "?"),
|
|
61
|
+
severity=getattr(f, "severity", "medium"),
|
|
62
|
+
file=file, line=line,
|
|
63
|
+
message=(
|
|
64
|
+
f"{getattr(f, 'claim', '')} → {getattr(f, 'reality', '')}".strip(" →")
|
|
65
|
+
or getattr(f, "message", "")
|
|
66
|
+
),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def from_dict(d: dict[str, Any]) -> "Finding":
|
|
71
|
+
loc = d.get("location") or d.get("file") or "?"
|
|
72
|
+
if isinstance(loc, str):
|
|
73
|
+
file, line = _parse_location(loc)
|
|
74
|
+
else:
|
|
75
|
+
file, line = None, None
|
|
76
|
+
return Finding(
|
|
77
|
+
audit=str(d.get("audit", "?")),
|
|
78
|
+
phase=str(d.get("phase", "?")),
|
|
79
|
+
severity=str(d.get("severity", "medium")),
|
|
80
|
+
file=file, line=line,
|
|
81
|
+
message=str(d.get("message", d.get("claim", "")))[:500],
|
|
82
|
+
fix_hint=str(d.get("fix", d.get("fix_hint", "")))[:500],
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _parse_location(loc: str) -> tuple[str | None, int | None]:
|
|
87
|
+
"""Parse 'path/to/file.py:42' → ('path/to/file.py', 42). None if no file."""
|
|
88
|
+
if not loc or loc == "?":
|
|
89
|
+
return None, None
|
|
90
|
+
# Strip leading "./" and the like
|
|
91
|
+
s = loc.strip()
|
|
92
|
+
if ":" in s:
|
|
93
|
+
path, _, rest = s.partition(":")
|
|
94
|
+
try:
|
|
95
|
+
line = int(rest.partition(":")[0])
|
|
96
|
+
except ValueError:
|
|
97
|
+
line = None
|
|
98
|
+
return (path or None), line
|
|
99
|
+
return s, None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@dataclass
|
|
103
|
+
class Batch:
|
|
104
|
+
"""A fixable batch — a set of findings sharing a disjoint file footprint.
|
|
105
|
+
|
|
106
|
+
The dispatcher turns each Batch into one worker dispatch.
|
|
107
|
+
"""
|
|
108
|
+
id: str
|
|
109
|
+
findings: list[Finding] = field(default_factory=list)
|
|
110
|
+
files: list[str] = field(default_factory=list)
|
|
111
|
+
score: int = 0 # higher = more severe — used to prioritise
|
|
112
|
+
|
|
113
|
+
def to_intent(self, audit_id: str) -> str:
|
|
114
|
+
"""Render as a natural-language worker task description."""
|
|
115
|
+
bullets = []
|
|
116
|
+
for f in self.findings:
|
|
117
|
+
loc = f.file or "(global)"
|
|
118
|
+
if f.line:
|
|
119
|
+
loc = f"{loc}:{f.line}"
|
|
120
|
+
bullets.append(f"- [{f.severity}] {loc} — {f.message}")
|
|
121
|
+
return (
|
|
122
|
+
f"Fix the following {audit_id} findings:\n"
|
|
123
|
+
+ "\n".join(bullets)
|
|
124
|
+
+ ("\n\nFiles you may edit: " + ", ".join(self.files)
|
|
125
|
+
if self.files else "")
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass
|
|
130
|
+
class BatchPlan:
|
|
131
|
+
"""Output of ``batch_findings`` — ready-to-dispatch batches + deferred."""
|
|
132
|
+
batches: list[Batch]
|
|
133
|
+
deferred: list[Finding] = field(default_factory=list)
|
|
134
|
+
audit_id: str = ""
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def batch_findings(
|
|
138
|
+
findings: Iterable[Finding | Any],
|
|
139
|
+
*,
|
|
140
|
+
audit_id: str = "",
|
|
141
|
+
max_batches: int = 3,
|
|
142
|
+
max_files_per_batch: int = 10,
|
|
143
|
+
min_severity: str | None = None,
|
|
144
|
+
) -> BatchPlan:
|
|
145
|
+
"""Cluster findings into ≤``max_batches`` disjoint-file batches.
|
|
146
|
+
|
|
147
|
+
Algorithm:
|
|
148
|
+
1. Normalise the iterable to ``Finding`` objects.
|
|
149
|
+
2. Filter by ``min_severity`` if given (low|medium|high|critical).
|
|
150
|
+
3. Group by file (no file → goes in the "(global)" bucket).
|
|
151
|
+
4. Sort groups by aggregate severity (worst first).
|
|
152
|
+
5. Greedily pack the top groups into ``max_batches`` batches,
|
|
153
|
+
each carrying up to ``max_files_per_batch`` files, never
|
|
154
|
+
overlapping files between batches (impossible by construction
|
|
155
|
+
here, since each file lands in exactly one batch).
|
|
156
|
+
6. If we'd need more than ``max_batches`` batches, defer the
|
|
157
|
+
leftover groups and return them in ``deferred``.
|
|
158
|
+
"""
|
|
159
|
+
norm: list[Finding] = []
|
|
160
|
+
for raw in findings:
|
|
161
|
+
if isinstance(raw, Finding):
|
|
162
|
+
norm.append(raw)
|
|
163
|
+
elif isinstance(raw, dict):
|
|
164
|
+
norm.append(Finding.from_dict(raw))
|
|
165
|
+
else:
|
|
166
|
+
norm.append(Finding.from_arsenal(raw))
|
|
167
|
+
|
|
168
|
+
if min_severity:
|
|
169
|
+
threshold = _severity_weight(min_severity)
|
|
170
|
+
norm = [f for f in norm if _severity_weight(f.severity) >= threshold]
|
|
171
|
+
|
|
172
|
+
by_file: dict[str, list[Finding]] = defaultdict(list)
|
|
173
|
+
for f in norm:
|
|
174
|
+
key = f.file or "(global)"
|
|
175
|
+
by_file[key].append(f)
|
|
176
|
+
|
|
177
|
+
# Sort files by aggregate severity weight, worst first.
|
|
178
|
+
file_score = {
|
|
179
|
+
key: sum(_severity_weight(f.severity) for f in fs)
|
|
180
|
+
for key, fs in by_file.items()
|
|
181
|
+
}
|
|
182
|
+
files_ranked = sorted(by_file.keys(), key=lambda k: -file_score[k])
|
|
183
|
+
|
|
184
|
+
# Greedy pack into max_batches: pick the batch with the smallest
|
|
185
|
+
# current finding count (tie-broken by lowest aggregate score).
|
|
186
|
+
batches: list[Batch] = [
|
|
187
|
+
Batch(id=f"b{i + 1}") for i in range(max(1, max_batches))
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
deferred: list[Finding] = []
|
|
191
|
+
for file_key in files_ranked:
|
|
192
|
+
if file_key == "(global)":
|
|
193
|
+
# Global findings get their own slot — the LAST batch.
|
|
194
|
+
target_batch = batches[-1]
|
|
195
|
+
else:
|
|
196
|
+
# Smallest batch that still has file capacity.
|
|
197
|
+
candidates = [
|
|
198
|
+
b for b in batches
|
|
199
|
+
if len(b.files) < max_files_per_batch
|
|
200
|
+
and file_key not in b.files
|
|
201
|
+
]
|
|
202
|
+
if not candidates:
|
|
203
|
+
deferred.extend(by_file[file_key])
|
|
204
|
+
continue
|
|
205
|
+
target_batch = min(
|
|
206
|
+
candidates, key=lambda b: (len(b.findings), b.score)
|
|
207
|
+
)
|
|
208
|
+
target_batch.findings.extend(by_file[file_key])
|
|
209
|
+
if file_key != "(global)":
|
|
210
|
+
target_batch.files.append(file_key)
|
|
211
|
+
target_batch.score += file_score[file_key]
|
|
212
|
+
|
|
213
|
+
# Drop empty batches.
|
|
214
|
+
batches = [b for b in batches if b.findings]
|
|
215
|
+
# Re-id sequentially.
|
|
216
|
+
for i, b in enumerate(batches, start=1):
|
|
217
|
+
b.id = f"b{i}"
|
|
218
|
+
return BatchPlan(batches=batches, deferred=deferred, audit_id=audit_id)
|