@trac3r/oh-my-god 2.2.11
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/CHANGELOG.md +188 -0
- package/INSTALL-VERIFICATION-INDEX.md +51 -0
- package/LICENSE +21 -0
- package/OMG-setup.sh +2549 -0
- package/QUICK-REFERENCE.md +58 -0
- package/README.md +207 -0
- package/agents/__init__.py +1 -0
- package/agents/__pycache__/model_roles.cpython-313.pyc +0 -0
- package/agents/_model_roles.yaml +26 -0
- package/agents/designer.md +67 -0
- package/agents/explore.md +60 -0
- package/agents/model_roles.py +196 -0
- package/agents/omg-api-builder.md +23 -0
- package/agents/omg-architect-mode.md +41 -0
- package/agents/omg-architect.md +13 -0
- package/agents/omg-backend-engineer.md +41 -0
- package/agents/omg-critic.md +16 -0
- package/agents/omg-database-engineer.md +41 -0
- package/agents/omg-escalation-router.md +17 -0
- package/agents/omg-executor.md +12 -0
- package/agents/omg-frontend-designer.md +41 -0
- package/agents/omg-implement-mode.md +49 -0
- package/agents/omg-infra-engineer.md +41 -0
- package/agents/omg-qa-tester.md +16 -0
- package/agents/omg-research-mode.md +41 -0
- package/agents/omg-security-auditor.md +41 -0
- package/agents/omg-testing-engineer.md +41 -0
- package/agents/plan.md +80 -0
- package/agents/quick_task.md +64 -0
- package/agents/reviewer.md +83 -0
- package/agents/task.md +71 -0
- package/bin/omg +41 -0
- package/commands/OMG:ai-commit.md +113 -0
- package/commands/OMG:api-twin.md +22 -0
- package/commands/OMG:arch.md +313 -0
- package/commands/OMG:browser.md +29 -0
- package/commands/OMG:ccg.md +22 -0
- package/commands/OMG:compat.md +57 -0
- package/commands/OMG:cost.md +181 -0
- package/commands/OMG:crazy.md +125 -0
- package/commands/OMG:create-agent.md +183 -0
- package/commands/OMG:deep-plan.md +18 -0
- package/commands/OMG:deps.md +248 -0
- package/commands/OMG:diagnose-plugins.md +33 -0
- package/commands/OMG:doctor.md +37 -0
- package/commands/OMG:domain-init.md +11 -0
- package/commands/OMG:escalate.md +52 -0
- package/commands/OMG:forge.md +103 -0
- package/commands/OMG:health-check.md +48 -0
- package/commands/OMG:init.md +134 -0
- package/commands/OMG:issue.md +56 -0
- package/commands/OMG:mode.md +44 -0
- package/commands/OMG:playwright.md +17 -0
- package/commands/OMG:preflight.md +26 -0
- package/commands/OMG:preset.md +49 -0
- package/commands/OMG:profile-review.md +58 -0
- package/commands/OMG:project-init.md +11 -0
- package/commands/OMG:ralph-start.md +43 -0
- package/commands/OMG:ralph-stop.md +23 -0
- package/commands/OMG:security-check.md +28 -0
- package/commands/OMG:session-branch.md +101 -0
- package/commands/OMG:session-fork.md +57 -0
- package/commands/OMG:session-merge.md +138 -0
- package/commands/OMG:setup.md +82 -0
- package/commands/OMG:ship.md +18 -0
- package/commands/OMG:stats.md +225 -0
- package/commands/OMG:teams.md +54 -0
- package/commands/OMG:theme.md +44 -0
- package/commands/OMG:validate.md +59 -0
- package/commands/__init__.py +1 -0
- package/docs/command-surface.md +55 -0
- package/docs/install/claude-code.md +53 -0
- package/docs/install/codex.md +45 -0
- package/docs/install/gemini.md +43 -0
- package/docs/install/github-action.md +81 -0
- package/docs/install/github-app-required-checks.md +107 -0
- package/docs/install/github-app.md +161 -0
- package/docs/install/kimi.md +43 -0
- package/docs/install/opencode.md +38 -0
- package/docs/proof.md +182 -0
- package/hooks/__init__.py +0 -0
- package/hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_agent_registry.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_analytics.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_budget.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_common.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_compression_optimizer.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_cost_ledger.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_learnings.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_memory.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_post_write.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_protected_context.cpython-313.pyc +0 -0
- package/hooks/__pycache__/_token_counter.cpython-313.pyc +0 -0
- package/hooks/__pycache__/branch_manager.cpython-313.pyc +0 -0
- package/hooks/__pycache__/budget_governor.cpython-313.pyc +0 -0
- package/hooks/__pycache__/circuit-breaker.cpython-313.pyc +0 -0
- package/hooks/__pycache__/compression_feedback.cpython-313.pyc +0 -0
- package/hooks/__pycache__/config-guard.cpython-313.pyc +0 -0
- package/hooks/__pycache__/context_pressure.cpython-313.pyc +0 -0
- package/hooks/__pycache__/credential_store.cpython-313.pyc +0 -0
- package/hooks/__pycache__/fetch-rate-limits.cpython-313.pyc +0 -0
- package/hooks/__pycache__/firewall.cpython-313.pyc +0 -0
- package/hooks/__pycache__/hashline-formatter-bridge.cpython-313.pyc +0 -0
- package/hooks/__pycache__/hashline-injector.cpython-313.pyc +0 -0
- package/hooks/__pycache__/hashline-validator.cpython-313.pyc +0 -0
- package/hooks/__pycache__/idle-detector.cpython-313.pyc +0 -0
- package/hooks/__pycache__/instructions-loaded.cpython-313.pyc +0 -0
- package/hooks/__pycache__/intentgate-keyword-detector.cpython-313.pyc +0 -0
- package/hooks/__pycache__/magic-keyword-router.cpython-313.pyc +0 -0
- package/hooks/__pycache__/policy_engine.cpython-313.pyc +0 -0
- package/hooks/__pycache__/post-tool-failure.cpython-313.pyc +0 -0
- package/hooks/__pycache__/post-write.cpython-313.pyc +0 -0
- package/hooks/__pycache__/post_write.cpython-313.pyc +0 -0
- package/hooks/__pycache__/pre-compact.cpython-313.pyc +0 -0
- package/hooks/__pycache__/pre-tool-inject.cpython-313.pyc +0 -0
- package/hooks/__pycache__/prompt-enhancer.cpython-313.pyc +0 -0
- package/hooks/__pycache__/quality-runner.cpython-313.pyc +0 -0
- package/hooks/__pycache__/query.cpython-313.pyc +0 -0
- package/hooks/__pycache__/secret-guard.cpython-313.pyc +0 -0
- package/hooks/__pycache__/secret_audit.cpython-313.pyc +0 -0
- package/hooks/__pycache__/security_validators.cpython-313.pyc +0 -0
- package/hooks/__pycache__/session-end-capture.cpython-313.pyc +0 -0
- package/hooks/__pycache__/session-start.cpython-313.pyc +0 -0
- package/hooks/__pycache__/setup_wizard.cpython-313.pyc +0 -0
- package/hooks/__pycache__/shadow_manager.cpython-313.pyc +0 -0
- package/hooks/__pycache__/state_migration.cpython-313.pyc +0 -0
- package/hooks/__pycache__/stop-gate.cpython-313.pyc +0 -0
- package/hooks/__pycache__/stop_dispatcher.cpython-313.pyc +0 -0
- package/hooks/__pycache__/tdd-gate.cpython-313.pyc +0 -0
- package/hooks/__pycache__/terms-guard.cpython-313.pyc +0 -0
- package/hooks/__pycache__/test-validator.cpython-313.pyc +0 -0
- package/hooks/__pycache__/test_generator_hook.cpython-313.pyc +0 -0
- package/hooks/__pycache__/todo-state-tracker.cpython-313.pyc +0 -0
- package/hooks/__pycache__/tool-ledger.cpython-313.pyc +0 -0
- package/hooks/__pycache__/trust_review.cpython-313.pyc +0 -0
- package/hooks/__pycache__/user-prompt-submit.cpython-313.pyc +0 -0
- package/hooks/_agent_registry.py +481 -0
- package/hooks/_analytics.py +291 -0
- package/hooks/_budget.py +31 -0
- package/hooks/_common.py +761 -0
- package/hooks/_compression_optimizer.py +119 -0
- package/hooks/_cost_ledger.py +176 -0
- package/hooks/_learnings.py +126 -0
- package/hooks/_memory.py +103 -0
- package/hooks/_post_write.py +46 -0
- package/hooks/_protected_context.py +150 -0
- package/hooks/_token_counter.py +221 -0
- package/hooks/branch_manager.py +255 -0
- package/hooks/budget_governor.py +326 -0
- package/hooks/circuit-breaker.py +270 -0
- package/hooks/compression_feedback.py +254 -0
- package/hooks/config-guard.py +193 -0
- package/hooks/context_pressure.py +119 -0
- package/hooks/credential_store.py +970 -0
- package/hooks/fetch-rate-limits.py +212 -0
- package/hooks/firewall.py +323 -0
- package/hooks/hashline-formatter-bridge.py +224 -0
- package/hooks/hashline-injector.py +273 -0
- package/hooks/hashline-validator.py +216 -0
- package/hooks/idle-detector.py +97 -0
- package/hooks/instructions-loaded.py +26 -0
- package/hooks/intentgate-keyword-detector.py +200 -0
- package/hooks/magic-keyword-router.py +195 -0
- package/hooks/policy_engine.py +767 -0
- package/hooks/post-tool-failure.py +19 -0
- package/hooks/post-write.py +233 -0
- package/hooks/pre-compact.py +470 -0
- package/hooks/pre-tool-inject.py +98 -0
- package/hooks/prompt-enhancer.py +879 -0
- package/hooks/quality-runner.py +191 -0
- package/hooks/query.py +512 -0
- package/hooks/secret-guard.py +120 -0
- package/hooks/secret_audit.py +144 -0
- package/hooks/security_validators.py +93 -0
- package/hooks/session-end-capture.py +505 -0
- package/hooks/session-start.py +261 -0
- package/hooks/setup_wizard.py +1101 -0
- package/hooks/shadow_manager.py +476 -0
- package/hooks/state_migration.py +228 -0
- package/hooks/stop-gate.py +7 -0
- package/hooks/stop_dispatcher.py +1259 -0
- package/hooks/tdd-gate.py +10 -0
- package/hooks/terms-guard.py +98 -0
- package/hooks/test-validator.py +462 -0
- package/hooks/test_generator_hook.py +123 -0
- package/hooks/todo-state-tracker.py +114 -0
- package/hooks/tool-ledger.py +165 -0
- package/hooks/trust_review.py +662 -0
- package/hooks/user-prompt-submit.py +12 -0
- package/hud/omg-hud.mjs +1571 -0
- package/lab/__init__.py +1 -0
- package/lab/__pycache__/__init__.cpython-313.pyc +0 -0
- package/lab/__pycache__/axolotl_adapter.cpython-313.pyc +0 -0
- package/lab/__pycache__/forge_runner.cpython-313.pyc +0 -0
- package/lab/__pycache__/gazebo_adapter.cpython-313.pyc +0 -0
- package/lab/__pycache__/isaac_gym_adapter.cpython-313.pyc +0 -0
- package/lab/__pycache__/mock_isaac_env.cpython-313.pyc +0 -0
- package/lab/__pycache__/pipeline.cpython-313.pyc +0 -0
- package/lab/__pycache__/policies.cpython-313.pyc +0 -0
- package/lab/__pycache__/pybullet_adapter.cpython-313.pyc +0 -0
- package/lab/axolotl_adapter.py +531 -0
- package/lab/forge_runner.py +103 -0
- package/lab/gazebo_adapter.py +168 -0
- package/lab/isaac_gym_adapter.py +190 -0
- package/lab/mock_isaac_env.py +47 -0
- package/lab/pipeline.py +712 -0
- package/lab/policies.py +52 -0
- package/lab/pybullet_adapter.py +192 -0
- package/package.json +61 -0
- package/plugins/README.md +78 -0
- package/plugins/__init__.py +1 -0
- package/plugins/__pycache__/__init__.cpython-313.pyc +0 -0
- package/plugins/advanced/commands/OMG-code-review.md +114 -0
- package/plugins/advanced/commands/OMG-deep-plan.md +266 -0
- package/plugins/advanced/commands/OMG-handoff.md +115 -0
- package/plugins/advanced/commands/OMG-learn.md +110 -0
- package/plugins/advanced/commands/OMG-maintainer.md +31 -0
- package/plugins/advanced/commands/OMG-ralph-start.md +43 -0
- package/plugins/advanced/commands/OMG-ralph-stop.md +23 -0
- package/plugins/advanced/commands/OMG-security-review.md +16 -0
- package/plugins/advanced/commands/OMG-sequential-thinking.md +20 -0
- package/plugins/advanced/commands/OMG-ship.md +46 -0
- package/plugins/advanced/commands/OMG:code-review.md +114 -0
- package/plugins/advanced/commands/OMG:deep-plan.md +266 -0
- package/plugins/advanced/commands/OMG:handoff.md +115 -0
- package/plugins/advanced/commands/OMG:learn.md +110 -0
- package/plugins/advanced/commands/OMG:maintainer.md +31 -0
- package/plugins/advanced/commands/OMG:ralph-start.md +43 -0
- package/plugins/advanced/commands/OMG:ralph-stop.md +23 -0
- package/plugins/advanced/commands/OMG:security-review.md +16 -0
- package/plugins/advanced/commands/OMG:sequential-thinking.md +20 -0
- package/plugins/advanced/commands/OMG:ship.md +46 -0
- package/plugins/advanced/plugin.json +104 -0
- package/plugins/core/plugin.json +204 -0
- package/plugins/dephealth/__init__.py +0 -0
- package/plugins/dephealth/__pycache__/__init__.cpython-313.pyc +0 -0
- package/plugins/dephealth/__pycache__/cve_scanner.cpython-313.pyc +0 -0
- package/plugins/dephealth/__pycache__/license_checker.cpython-313.pyc +0 -0
- package/plugins/dephealth/__pycache__/manifest_detector.cpython-313.pyc +0 -0
- package/plugins/dephealth/__pycache__/vuln_analyzer.cpython-313.pyc +0 -0
- package/plugins/dephealth/cve_scanner.py +279 -0
- package/plugins/dephealth/license_checker.py +135 -0
- package/plugins/dephealth/manifest_detector.py +423 -0
- package/plugins/dephealth/vuln_analyzer.py +176 -0
- package/plugins/testgen/__init__.py +0 -0
- package/plugins/testgen/__pycache__/__init__.cpython-313.pyc +0 -0
- package/plugins/testgen/__pycache__/codamosa_engine.cpython-313.pyc +0 -0
- package/plugins/testgen/__pycache__/edge_case_synthesizer.cpython-313.pyc +0 -0
- package/plugins/testgen/__pycache__/framework_detector.cpython-313.pyc +0 -0
- package/plugins/testgen/__pycache__/skeleton_generator.cpython-313.pyc +0 -0
- package/plugins/testgen/codamosa_engine.py +402 -0
- package/plugins/testgen/edge_case_synthesizer.py +184 -0
- package/plugins/testgen/framework_detector.py +271 -0
- package/plugins/testgen/skeleton_generator.py +219 -0
- package/plugins/viz/__init__.py +0 -0
- package/plugins/viz/__pycache__/__init__.cpython-313.pyc +0 -0
- package/plugins/viz/__pycache__/ast_parser.cpython-313.pyc +0 -0
- package/plugins/viz/__pycache__/diagram_generator.cpython-313.pyc +0 -0
- package/plugins/viz/__pycache__/graph_builder.cpython-313.pyc +0 -0
- package/plugins/viz/__pycache__/native_parsers.cpython-313.pyc +0 -0
- package/plugins/viz/__pycache__/regex_parser.cpython-313.pyc +0 -0
- package/plugins/viz/ast_parser.py +139 -0
- package/plugins/viz/diagram_generator.py +192 -0
- package/plugins/viz/graph_builder.py +444 -0
- package/plugins/viz/native_parsers.py +259 -0
- package/plugins/viz/regex_parser.py +112 -0
- package/pyproject.toml +143 -0
- package/registry/__init__.py +1 -0
- package/registry/__pycache__/__init__.cpython-313.pyc +0 -0
- package/registry/__pycache__/approval_artifact.cpython-313.pyc +0 -0
- package/registry/__pycache__/verify_artifact.cpython-313.pyc +0 -0
- package/registry/approval_artifact.py +236 -0
- package/registry/bundles/algorithms.yaml +45 -0
- package/registry/bundles/api-twin.yaml +48 -0
- package/registry/bundles/ast-pack.yaml +80 -0
- package/registry/bundles/claim-judge.yaml +49 -0
- package/registry/bundles/control-plane.yaml +192 -0
- package/registry/bundles/data-lineage.yaml +47 -0
- package/registry/bundles/delta-classifier.yaml +47 -0
- package/registry/bundles/eval-gate.yaml +47 -0
- package/registry/bundles/hash-edit.yaml +73 -0
- package/registry/bundles/health.yaml +45 -0
- package/registry/bundles/hook-governor.yaml +101 -0
- package/registry/bundles/incident-replay.yaml +47 -0
- package/registry/bundles/lsp-pack.yaml +80 -0
- package/registry/bundles/mcp-fabric.yaml +53 -0
- package/registry/bundles/plan-council.yaml +56 -0
- package/registry/bundles/preflight.yaml +48 -0
- package/registry/bundles/proof-gate.yaml +49 -0
- package/registry/bundles/remote-supervisor.yaml +49 -0
- package/registry/bundles/robotics.yaml +45 -0
- package/registry/bundles/secure-worktree-pipeline.yaml +69 -0
- package/registry/bundles/security-check.yaml +50 -0
- package/registry/bundles/terminal-lane.yaml +61 -0
- package/registry/bundles/test-intent-lock.yaml +49 -0
- package/registry/bundles/tracebank.yaml +47 -0
- package/registry/bundles/vision.yaml +45 -0
- package/registry/omg-capability.schema.json +378 -0
- package/registry/policy-packs/airgapped.lock.json +11 -0
- package/registry/policy-packs/airgapped.signature.json +10 -0
- package/registry/policy-packs/airgapped.yaml +16 -0
- package/registry/policy-packs/fintech.lock.json +11 -0
- package/registry/policy-packs/fintech.signature.json +10 -0
- package/registry/policy-packs/fintech.yaml +15 -0
- package/registry/policy-packs/locked-prod.lock.json +11 -0
- package/registry/policy-packs/locked-prod.signature.json +10 -0
- package/registry/policy-packs/locked-prod.yaml +18 -0
- package/registry/trusted_signers.json +44 -0
- package/registry/verify_artifact.py +493 -0
- package/runtime/__init__.py +36 -0
- package/runtime/__pycache__/__init__.cpython-313.pyc +0 -0
- package/runtime/__pycache__/adoption.cpython-313.pyc +0 -0
- package/runtime/__pycache__/agent_selector.cpython-313.pyc +0 -0
- package/runtime/__pycache__/api_twin.cpython-313.pyc +0 -0
- package/runtime/__pycache__/architecture_signal.cpython-313.pyc +0 -0
- package/runtime/__pycache__/artifact_parsers.cpython-313.pyc +0 -0
- package/runtime/__pycache__/asset_loader.cpython-313.pyc +0 -0
- package/runtime/__pycache__/background_verification.cpython-313.pyc +0 -0
- package/runtime/__pycache__/budget_envelopes.cpython-313.pyc +0 -0
- package/runtime/__pycache__/business_workflow.cpython-313.pyc +0 -0
- package/runtime/__pycache__/canonical_surface.cpython-313.pyc +0 -0
- package/runtime/__pycache__/canonical_taxonomy.cpython-313.pyc +0 -0
- package/runtime/__pycache__/claim_judge.cpython-313.pyc +0 -0
- package/runtime/__pycache__/cli_provider.cpython-313.pyc +0 -0
- package/runtime/__pycache__/compat.cpython-313.pyc +0 -0
- package/runtime/__pycache__/complexity_scorer.cpython-313.pyc +0 -0
- package/runtime/__pycache__/compliance_governor.cpython-313.pyc +0 -0
- package/runtime/__pycache__/config_transaction.cpython-313.pyc +0 -0
- package/runtime/__pycache__/context_compiler.cpython-313.pyc +0 -0
- package/runtime/__pycache__/context_engine.cpython-313.pyc +0 -0
- package/runtime/__pycache__/context_limits.cpython-313.pyc +0 -0
- package/runtime/__pycache__/contract_compiler.cpython-313.pyc +0 -0
- package/runtime/__pycache__/custom_agent_loader.cpython-313.pyc +0 -0
- package/runtime/__pycache__/data_lineage.cpython-313.pyc +0 -0
- package/runtime/__pycache__/defense_state.cpython-313.pyc +0 -0
- package/runtime/__pycache__/delta_classifier.cpython-313.pyc +0 -0
- package/runtime/__pycache__/dispatcher.cpython-313.pyc +0 -0
- package/runtime/__pycache__/doc_generator.cpython-313.pyc +0 -0
- package/runtime/__pycache__/domain_packs.cpython-313.pyc +0 -0
- package/runtime/__pycache__/ecosystem.cpython-313.pyc +0 -0
- package/runtime/__pycache__/equalizer.cpython-313.pyc +0 -0
- package/runtime/__pycache__/eval_gate.cpython-313.pyc +0 -0
- package/runtime/__pycache__/evidence_narrator.cpython-313.pyc +0 -0
- package/runtime/__pycache__/evidence_query.cpython-313.pyc +0 -0
- package/runtime/__pycache__/evidence_registry.cpython-313.pyc +0 -0
- package/runtime/__pycache__/evidence_requirements.cpython-313.pyc +0 -0
- package/runtime/__pycache__/exec_kernel.cpython-313.pyc +0 -0
- package/runtime/__pycache__/explainer_formatter.cpython-313.pyc +0 -0
- package/runtime/__pycache__/feature_registry.cpython-313.pyc +0 -0
- package/runtime/__pycache__/forge_agents.cpython-313.pyc +0 -0
- package/runtime/__pycache__/forge_contracts.cpython-313.pyc +0 -0
- package/runtime/__pycache__/forge_domains.cpython-313.pyc +0 -0
- package/runtime/__pycache__/forge_run_id.cpython-313.pyc +0 -0
- package/runtime/__pycache__/github_integration.cpython-313.pyc +0 -0
- package/runtime/__pycache__/github_review_bot.cpython-313.pyc +0 -0
- package/runtime/__pycache__/github_review_contract.cpython-313.pyc +0 -0
- package/runtime/__pycache__/github_review_formatter.cpython-313.pyc +0 -0
- package/runtime/__pycache__/guide_assert.cpython-313.pyc +0 -0
- package/runtime/__pycache__/hook_governor.cpython-313.pyc +0 -0
- package/runtime/__pycache__/host_parity.cpython-313.pyc +0 -0
- package/runtime/__pycache__/incident_replay.cpython-313.pyc +0 -0
- package/runtime/__pycache__/install_planner.cpython-313.pyc +0 -0
- package/runtime/__pycache__/interaction_journal.cpython-313.pyc +0 -0
- package/runtime/__pycache__/issue_surface.cpython-313.pyc +0 -0
- package/runtime/__pycache__/legacy_compat.cpython-313.pyc +0 -0
- package/runtime/__pycache__/mcp_config_writers.cpython-313.pyc +0 -0
- package/runtime/__pycache__/mcp_lifecycle.cpython-313.pyc +0 -0
- package/runtime/__pycache__/mcp_memory_server.cpython-313.pyc +0 -0
- package/runtime/__pycache__/memory_store.cpython-313.pyc +0 -0
- package/runtime/__pycache__/merge_writer.cpython-313.pyc +0 -0
- package/runtime/__pycache__/music_omr_testbed.cpython-313.pyc +0 -0
- package/runtime/__pycache__/mutation_gate.cpython-313.pyc +0 -0
- package/runtime/__pycache__/omc_compat.cpython-313.pyc +0 -0
- package/runtime/__pycache__/omg_browser_cli.cpython-313.pyc +0 -0
- package/runtime/__pycache__/omg_mcp_server.cpython-313.pyc +0 -0
- package/runtime/__pycache__/opus_plan.cpython-313.pyc +0 -0
- package/runtime/__pycache__/playwright_adapter.cpython-313.pyc +0 -0
- package/runtime/__pycache__/playwright_pack.cpython-313.pyc +0 -0
- package/runtime/__pycache__/plugin_diagnostics.cpython-313.pyc +0 -0
- package/runtime/__pycache__/plugin_interop.cpython-313.pyc +0 -0
- package/runtime/__pycache__/policy_pack_loader.cpython-313.pyc +0 -0
- package/runtime/__pycache__/preflight.cpython-313.pyc +0 -0
- package/runtime/__pycache__/profile_io.cpython-313.pyc +0 -0
- package/runtime/__pycache__/prompt_compiler.cpython-313.pyc +0 -0
- package/runtime/__pycache__/proof_chain.cpython-313.pyc +0 -0
- package/runtime/__pycache__/proof_gate.cpython-313.pyc +0 -0
- package/runtime/__pycache__/provider_parity_eval.cpython-313.pyc +0 -0
- package/runtime/__pycache__/release_artifact_audit.cpython-313.pyc +0 -0
- package/runtime/__pycache__/release_run_coordinator.cpython-313.pyc +0 -0
- package/runtime/__pycache__/release_surface_compiler.cpython-313.pyc +0 -0
- package/runtime/__pycache__/release_surface_registry.cpython-313.pyc +0 -0
- package/runtime/__pycache__/release_surfaces.cpython-313.pyc +0 -0
- package/runtime/__pycache__/remote_supervisor.cpython-313.pyc +0 -0
- package/runtime/__pycache__/repro_pack.cpython-313.pyc +0 -0
- package/runtime/__pycache__/rollback_manifest.cpython-313.pyc +0 -0
- package/runtime/__pycache__/router_critics.cpython-313.pyc +0 -0
- package/runtime/__pycache__/router_executor.cpython-313.pyc +0 -0
- package/runtime/__pycache__/router_selector.cpython-313.pyc +0 -0
- package/runtime/__pycache__/runtime_contracts.cpython-313.pyc +0 -0
- package/runtime/__pycache__/runtime_profile.cpython-313.pyc +0 -0
- package/runtime/__pycache__/security_check.cpython-313.pyc +0 -0
- package/runtime/__pycache__/session_health.cpython-313.pyc +0 -0
- package/runtime/__pycache__/skill_evolution.cpython-313.pyc +0 -0
- package/runtime/__pycache__/skill_registry.cpython-313.pyc +0 -0
- package/runtime/__pycache__/subagent_dispatcher.cpython-313.pyc +0 -0
- package/runtime/__pycache__/subscription_tiers.cpython-313.pyc +0 -0
- package/runtime/__pycache__/team_router.cpython-313.pyc +0 -0
- package/runtime/__pycache__/test_intent_lock.cpython-313-pytest-9.0.2.pyc +0 -0
- package/runtime/__pycache__/test_intent_lock.cpython-313.pyc +0 -0
- package/runtime/__pycache__/tmux_session_manager.cpython-313.pyc +0 -0
- package/runtime/__pycache__/tool_fabric.cpython-313.pyc +0 -0
- package/runtime/__pycache__/tool_plan_gate.cpython-313.pyc +0 -0
- package/runtime/__pycache__/tool_relevance.cpython-313.pyc +0 -0
- package/runtime/__pycache__/tracebank.cpython-313.pyc +0 -0
- package/runtime/__pycache__/untrusted_content.cpython-313.pyc +0 -0
- package/runtime/__pycache__/validate.cpython-313.pyc +0 -0
- package/runtime/__pycache__/verdict_schema.cpython-313.pyc +0 -0
- package/runtime/__pycache__/verification_controller.cpython-313.pyc +0 -0
- package/runtime/__pycache__/verification_loop.cpython-313.pyc +0 -0
- package/runtime/__pycache__/vision_artifacts.cpython-313.pyc +0 -0
- package/runtime/__pycache__/vision_cache.cpython-313.pyc +0 -0
- package/runtime/__pycache__/vision_jobs.cpython-313.pyc +0 -0
- package/runtime/__pycache__/worker_watchdog.cpython-313.pyc +0 -0
- package/runtime/adapters/__init__.py +13 -0
- package/runtime/adapters/__pycache__/__init__.cpython-313.pyc +0 -0
- package/runtime/adapters/__pycache__/claude.cpython-313.pyc +0 -0
- package/runtime/adapters/__pycache__/gpt.cpython-313.pyc +0 -0
- package/runtime/adapters/__pycache__/local.cpython-313.pyc +0 -0
- package/runtime/adapters/claude.py +63 -0
- package/runtime/adapters/gpt.py +56 -0
- package/runtime/adapters/local.py +56 -0
- package/runtime/adoption.py +280 -0
- package/runtime/api_twin.py +450 -0
- package/runtime/architecture_signal.py +226 -0
- package/runtime/artifact_parsers.py +161 -0
- package/runtime/asset_loader.py +62 -0
- package/runtime/background_verification.py +178 -0
- package/runtime/budget_envelopes.py +398 -0
- package/runtime/business_workflow.py +234 -0
- package/runtime/canonical_surface.py +53 -0
- package/runtime/canonical_taxonomy.py +27 -0
- package/runtime/claim_judge.py +648 -0
- package/runtime/cli_provider.py +105 -0
- package/runtime/compat.py +2222 -0
- package/runtime/complexity_scorer.py +148 -0
- package/runtime/compliance_governor.py +505 -0
- package/runtime/config_transaction.py +304 -0
- package/runtime/context_compiler.py +131 -0
- package/runtime/context_engine.py +708 -0
- package/runtime/context_limits.py +363 -0
- package/runtime/contract_compiler.py +3664 -0
- package/runtime/custom_agent_loader.py +366 -0
- package/runtime/data_lineage.py +244 -0
- package/runtime/defense_state.py +261 -0
- package/runtime/delta_classifier.py +231 -0
- package/runtime/dispatcher.py +47 -0
- package/runtime/doc_generator.py +319 -0
- package/runtime/domain_packs.py +75 -0
- package/runtime/ecosystem.py +371 -0
- package/runtime/equalizer.py +268 -0
- package/runtime/eval_gate.py +96 -0
- package/runtime/evidence_narrator.py +147 -0
- package/runtime/evidence_query.py +303 -0
- package/runtime/evidence_registry.py +16 -0
- package/runtime/evidence_requirements.py +157 -0
- package/runtime/exec_kernel.py +267 -0
- package/runtime/explainer_formatter.py +82 -0
- package/runtime/feature_registry.py +109 -0
- package/runtime/forge_agents.py +915 -0
- package/runtime/forge_contracts.py +519 -0
- package/runtime/forge_domains.py +68 -0
- package/runtime/forge_run_id.py +86 -0
- package/runtime/guide_assert.py +135 -0
- package/runtime/hook_governor.py +156 -0
- package/runtime/host_parity.py +373 -0
- package/runtime/incident_replay.py +310 -0
- package/runtime/install_planner.py +617 -0
- package/runtime/interaction_journal.py +566 -0
- package/runtime/issue_surface.py +472 -0
- package/runtime/legacy_compat.py +7 -0
- package/runtime/mcp_config_writers.py +360 -0
- package/runtime/mcp_lifecycle.py +175 -0
- package/runtime/mcp_memory_server.py +220 -0
- package/runtime/memory_parsers/__init__.py +0 -0
- package/runtime/memory_parsers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/runtime/memory_parsers/__pycache__/chatgpt_parser.cpython-313.pyc +0 -0
- package/runtime/memory_parsers/__pycache__/claude_import.cpython-313.pyc +0 -0
- package/runtime/memory_parsers/__pycache__/export.cpython-313.pyc +0 -0
- package/runtime/memory_parsers/__pycache__/gemini_import.cpython-313.pyc +0 -0
- package/runtime/memory_parsers/__pycache__/kimi_import.cpython-313.pyc +0 -0
- package/runtime/memory_parsers/chatgpt_parser.py +257 -0
- package/runtime/memory_parsers/claude_import.py +107 -0
- package/runtime/memory_parsers/export.py +97 -0
- package/runtime/memory_parsers/gemini_import.py +91 -0
- package/runtime/memory_parsers/kimi_import.py +91 -0
- package/runtime/memory_store.py +1182 -0
- package/runtime/merge_writer.py +445 -0
- package/runtime/music_omr_testbed.py +336 -0
- package/runtime/mutation_gate.py +320 -0
- package/runtime/omc_compat.py +7 -0
- package/runtime/omg_browser_cli.py +95 -0
- package/runtime/omg_compat_contract_snapshot.json +936 -0
- package/runtime/omg_contract_snapshot.json +936 -0
- package/runtime/omg_mcp_server.py +306 -0
- package/runtime/playwright_adapter.py +39 -0
- package/runtime/playwright_pack.py +253 -0
- package/runtime/plugin_diagnostics.py +308 -0
- package/runtime/plugin_interop.py +1060 -0
- package/runtime/policy_pack_loader.py +147 -0
- package/runtime/preflight.py +135 -0
- package/runtime/profile_io.py +328 -0
- package/runtime/proof_chain.py +472 -0
- package/runtime/proof_gate.py +442 -0
- package/runtime/provider_parity_eval.py +109 -0
- package/runtime/providers/__init__.py +0 -0
- package/runtime/providers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/runtime/providers/__pycache__/codex_provider.cpython-313.pyc +0 -0
- package/runtime/providers/__pycache__/gemini_provider.cpython-313.pyc +0 -0
- package/runtime/providers/__pycache__/kimi_provider.cpython-313.pyc +0 -0
- package/runtime/providers/__pycache__/opencode_provider.cpython-313.pyc +0 -0
- package/runtime/providers/codex_provider.py +129 -0
- package/runtime/providers/gemini_provider.py +143 -0
- package/runtime/providers/kimi_provider.py +167 -0
- package/runtime/providers/opencode_provider.py +99 -0
- package/runtime/release_artifact_audit.py +556 -0
- package/runtime/release_run_coordinator.py +574 -0
- package/runtime/release_surface_compiler.py +643 -0
- package/runtime/release_surface_registry.py +283 -0
- package/runtime/release_surfaces.py +320 -0
- package/runtime/remote_supervisor.py +79 -0
- package/runtime/repro_pack.py +398 -0
- package/runtime/rollback_manifest.py +143 -0
- package/runtime/router_critics.py +229 -0
- package/runtime/router_executor.py +142 -0
- package/runtime/router_selector.py +99 -0
- package/runtime/runtime_contracts.py +292 -0
- package/runtime/runtime_profile.py +133 -0
- package/runtime/security_check.py +1094 -0
- package/runtime/session_health.py +546 -0
- package/runtime/skill_evolution.py +221 -0
- package/runtime/skill_registry.py +53 -0
- package/runtime/subagent_dispatcher.py +604 -0
- package/runtime/subscription_tiers.py +258 -0
- package/runtime/team_router.py +1399 -0
- package/runtime/test_intent_lock.py +543 -0
- package/runtime/tmux_session_manager.py +172 -0
- package/runtime/tool_fabric.py +570 -0
- package/runtime/tool_plan_gate.py +460 -0
- package/runtime/tracebank.py +125 -0
- package/runtime/untrusted_content.py +360 -0
- package/runtime/validate.py +293 -0
- package/runtime/verdict_schema.py +198 -0
- package/runtime/verification_controller.py +235 -0
- package/runtime/verification_loop.py +73 -0
- package/runtime/vision_artifacts.py +31 -0
- package/runtime/vision_cache.py +38 -0
- package/runtime/vision_jobs.py +92 -0
- package/runtime/worker_watchdog.py +526 -0
- package/scripts/__pycache__/audit-published-artifact.cpython-313.pyc +0 -0
- package/scripts/__pycache__/check-doc-parity.cpython-313.pyc +0 -0
- package/scripts/__pycache__/check-omg-standalone-clean.cpython-313.pyc +0 -0
- package/scripts/__pycache__/github_review_helpers.cpython-313.pyc +0 -0
- package/scripts/__pycache__/omg.cpython-313.pyc +0 -0
- package/scripts/__pycache__/prepare-release-proof-fixtures.cpython-313.pyc +0 -0
- package/scripts/__pycache__/sync-release-identity.cpython-313.pyc +0 -0
- package/scripts/__pycache__/validate-release-identity.cpython-313.pyc +0 -0
- package/scripts/audit-published-artifact.py +59 -0
- package/scripts/check-omg-compat-contract-snapshot.py +137 -0
- package/scripts/check-omg-contract-snapshot.py +12 -0
- package/scripts/check-omg-public-ready.py +273 -0
- package/scripts/check-omg-standalone-clean.py +133 -0
- package/scripts/emit_host_parity.py +72 -0
- package/scripts/legacy_to_omg_migrate.py +29 -0
- package/scripts/migrate-legacy.py +464 -0
- package/scripts/omc_to_omg_migrate.py +12 -0
- package/scripts/omg.py +2962 -0
- package/scripts/pre-release-check.sh +38 -0
- package/scripts/prepare-release-proof-fixtures.py +602 -0
- package/scripts/print-canonical-version.py +80 -0
- package/scripts/settings-merge.py +289 -0
- package/scripts/sync-release-identity.py +481 -0
- package/scripts/validate-release-identity.py +632 -0
- package/scripts/verify-no-omc.sh +5 -0
- package/scripts/verify-standalone.sh +35 -0
- package/settings.json +751 -0
- package/tools/__init__.py +2 -0
- package/tools/__pycache__/__init__.cpython-313.pyc +0 -0
- package/tools/__pycache__/browser_consent.cpython-313.pyc +0 -0
- package/tools/__pycache__/browser_stealth.cpython-313.pyc +0 -0
- package/tools/__pycache__/browser_tool.cpython-313.pyc +0 -0
- package/tools/__pycache__/changelog_generator.cpython-313.pyc +0 -0
- package/tools/__pycache__/commit_splitter.cpython-313.pyc +0 -0
- package/tools/__pycache__/config_discovery.cpython-313.pyc +0 -0
- package/tools/__pycache__/config_merger.cpython-313.pyc +0 -0
- package/tools/__pycache__/dashboard_generator.cpython-313.pyc +0 -0
- package/tools/__pycache__/git_inspector.cpython-313.pyc +0 -0
- package/tools/__pycache__/lsp_client.cpython-313.pyc +0 -0
- package/tools/__pycache__/lsp_operations.cpython-313.pyc +0 -0
- package/tools/__pycache__/pr_generator.cpython-313.pyc +0 -0
- package/tools/__pycache__/python_repl.cpython-313.pyc +0 -0
- package/tools/__pycache__/python_sandbox.cpython-313.pyc +0 -0
- package/tools/__pycache__/session_snapshot.cpython-313.pyc +0 -0
- package/tools/__pycache__/ssh_manager.cpython-313.pyc +0 -0
- package/tools/__pycache__/theme_engine.cpython-313.pyc +0 -0
- package/tools/__pycache__/theme_selector.cpython-313.pyc +0 -0
- package/tools/__pycache__/web_search.cpython-313.pyc +0 -0
- package/tools/browser_consent.py +289 -0
- package/tools/browser_stealth.py +481 -0
- package/tools/browser_tool.py +448 -0
- package/tools/changelog_generator.py +347 -0
- package/tools/commit_splitter.py +749 -0
- package/tools/config_discovery.py +151 -0
- package/tools/config_merger.py +449 -0
- package/tools/dashboard_generator.py +300 -0
- package/tools/git_inspector.py +298 -0
- package/tools/lsp_client.py +275 -0
- package/tools/lsp_discovery.py +231 -0
- package/tools/lsp_operations.py +392 -0
- package/tools/pr_generator.py +404 -0
- package/tools/python_repl.py +712 -0
- package/tools/python_sandbox.py +768 -0
- package/tools/search_providers/__init__.py +77 -0
- package/tools/search_providers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/tools/search_providers/__pycache__/brave.cpython-313.pyc +0 -0
- package/tools/search_providers/__pycache__/exa.cpython-313.pyc +0 -0
- package/tools/search_providers/__pycache__/jina.cpython-313.pyc +0 -0
- package/tools/search_providers/__pycache__/perplexity.cpython-313.pyc +0 -0
- package/tools/search_providers/__pycache__/synthetic.cpython-313.pyc +0 -0
- package/tools/search_providers/brave.py +115 -0
- package/tools/search_providers/exa.py +116 -0
- package/tools/search_providers/jina.py +104 -0
- package/tools/search_providers/perplexity.py +139 -0
- package/tools/search_providers/synthetic.py +74 -0
- package/tools/session_snapshot.py +851 -0
- package/tools/ssh_manager.py +912 -0
- package/tools/theme_engine.py +296 -0
- package/tools/theme_selector.py +137 -0
- package/tools/web_search.py +675 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Protected context registry for PreCompact hook.
|
|
2
|
+
|
|
3
|
+
Reads .claude-context-protect entries (file paths, regex patterns, literal strings)
|
|
4
|
+
and collects protected context items to re-inject via additionalContext during compaction.
|
|
5
|
+
|
|
6
|
+
Default protections (when no .claude-context-protect exists):
|
|
7
|
+
- CLAUDE.md content
|
|
8
|
+
- Active task definitions (## Task:, - [ ])
|
|
9
|
+
- Recent error messages (Error:, Exception:, FAILED)
|
|
10
|
+
|
|
11
|
+
Pure stdlib — no external dependencies.
|
|
12
|
+
"""
|
|
13
|
+
import os
|
|
14
|
+
import re
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
PROTECT_FILE_NAME = ".claude-context-protect"
|
|
18
|
+
|
|
19
|
+
# Default protection patterns (used when no protect file exists)
|
|
20
|
+
_DEFAULT_TASK_PATTERNS = [
|
|
21
|
+
re.compile(r"^## Task:"),
|
|
22
|
+
re.compile(r"^- \[ \]"),
|
|
23
|
+
]
|
|
24
|
+
_DEFAULT_ERROR_KEYWORDS = ("Error:", "Exception:", "FAILED")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def load_protect_entries(project_dir):
|
|
28
|
+
"""Read .claude-context-protect file, return list of entries or None if missing.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
list[str] | None: List of non-empty, non-comment lines. None if file missing.
|
|
32
|
+
"""
|
|
33
|
+
protect_path = os.path.join(project_dir, PROTECT_FILE_NAME)
|
|
34
|
+
if not os.path.isfile(protect_path):
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
with open(protect_path, "r", encoding="utf-8", errors="ignore") as f:
|
|
39
|
+
lines = f.readlines()
|
|
40
|
+
except Exception:
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
entries = []
|
|
44
|
+
for line in lines:
|
|
45
|
+
stripped = line.strip()
|
|
46
|
+
if stripped and not stripped.startswith("#"):
|
|
47
|
+
entries.append(stripped)
|
|
48
|
+
return entries
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _read_file_content(file_path):
|
|
52
|
+
"""Read file content. Returns stripped string or None on failure."""
|
|
53
|
+
try:
|
|
54
|
+
if not os.path.isfile(file_path):
|
|
55
|
+
return None
|
|
56
|
+
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
|
|
57
|
+
content = f.read().strip()
|
|
58
|
+
return content if content else None
|
|
59
|
+
except Exception:
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _match_entry_against_lines(entry, context_lines):
|
|
64
|
+
"""Match entry against context lines. Tries regex first, falls back to literal.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
list[str]: Matching lines.
|
|
68
|
+
"""
|
|
69
|
+
try:
|
|
70
|
+
pattern = re.compile(entry)
|
|
71
|
+
return [line for line in context_lines if pattern.search(line)]
|
|
72
|
+
except re.error:
|
|
73
|
+
# Invalid regex — fall back to literal substring match
|
|
74
|
+
return [line for line in context_lines if entry in line]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _process_entry(entry, project_dir, context_lines):
|
|
78
|
+
"""Process a single protect entry. Returns list of protected strings.
|
|
79
|
+
|
|
80
|
+
Resolution order:
|
|
81
|
+
1. If entry resolves to an existing file → include file content
|
|
82
|
+
2. Otherwise, try regex match against context lines
|
|
83
|
+
3. If regex fails (re.error), fall back to literal substring match
|
|
84
|
+
"""
|
|
85
|
+
# 1. Try as file path
|
|
86
|
+
file_path = os.path.join(project_dir, entry)
|
|
87
|
+
content = _read_file_content(file_path)
|
|
88
|
+
if content is not None:
|
|
89
|
+
return [content]
|
|
90
|
+
|
|
91
|
+
# 2. Try as regex/literal against context lines
|
|
92
|
+
return _match_entry_against_lines(entry, context_lines)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _get_default_protections(project_dir, context_lines):
|
|
96
|
+
"""Apply default protections when no .claude-context-protect exists.
|
|
97
|
+
|
|
98
|
+
Default protected items:
|
|
99
|
+
- CLAUDE.md content (if file exists)
|
|
100
|
+
- Active task definitions (## Task:, - [ ])
|
|
101
|
+
- Recent error messages (Error:, Exception:, FAILED)
|
|
102
|
+
"""
|
|
103
|
+
parts = []
|
|
104
|
+
|
|
105
|
+
# 1. CLAUDE.md content
|
|
106
|
+
claude_md_path = os.path.join(project_dir, "CLAUDE.md")
|
|
107
|
+
claude_content = _read_file_content(claude_md_path)
|
|
108
|
+
if claude_content:
|
|
109
|
+
parts.append(claude_content)
|
|
110
|
+
|
|
111
|
+
# 2. Active task definitions
|
|
112
|
+
for line in context_lines:
|
|
113
|
+
for pat in _DEFAULT_TASK_PATTERNS:
|
|
114
|
+
if pat.search(line):
|
|
115
|
+
parts.append(line)
|
|
116
|
+
break
|
|
117
|
+
|
|
118
|
+
# 3. Recent error messages
|
|
119
|
+
for line in context_lines:
|
|
120
|
+
if any(kw in line for kw in _DEFAULT_ERROR_KEYWORDS):
|
|
121
|
+
parts.append(line)
|
|
122
|
+
|
|
123
|
+
return parts
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def collect_protected_context(project_dir, context_text=""):
|
|
127
|
+
"""Collect all protected context items and return as a single string.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
project_dir: Project root directory.
|
|
131
|
+
context_text: Current context text to scan for regex/literal matches.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
str: Protected context items joined by newlines. Empty string if nothing.
|
|
135
|
+
"""
|
|
136
|
+
context_lines = [l for l in context_text.split("\n") if l.strip()] if context_text else []
|
|
137
|
+
protected_parts = []
|
|
138
|
+
|
|
139
|
+
entries = load_protect_entries(project_dir)
|
|
140
|
+
|
|
141
|
+
if entries is None:
|
|
142
|
+
# No protect file — use defaults
|
|
143
|
+
protected_parts = _get_default_protections(project_dir, context_lines)
|
|
144
|
+
else:
|
|
145
|
+
# Process each entry from protect file
|
|
146
|
+
for entry in entries:
|
|
147
|
+
matched = _process_entry(entry, project_dir, context_lines)
|
|
148
|
+
protected_parts.extend(matched)
|
|
149
|
+
|
|
150
|
+
return "\n".join(protected_parts) if protected_parts else ""
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Tiered token estimation helpers for OMG hooks."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import importlib
|
|
8
|
+
import urllib.request
|
|
9
|
+
from collections.abc import Iterable
|
|
10
|
+
|
|
11
|
+
API_URL = "https://api.anthropic.com/v1/messages/count_tokens"
|
|
12
|
+
API_MODEL = "claude-3-5-haiku-20241022"
|
|
13
|
+
|
|
14
|
+
_FEATURE_UI_DISPLAY = "ui_display"
|
|
15
|
+
_FEATURE_BUDGET_ENFORCEMENT = "budget_enforcement"
|
|
16
|
+
_FEATURE_PREFLIGHT = "preflight"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _safe_int(value: float) -> int:
|
|
20
|
+
if value <= 0:
|
|
21
|
+
return 0
|
|
22
|
+
return int(value)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _extract_features(text: str) -> tuple[int, int, int]:
|
|
26
|
+
encoded = text.encode("utf-8")
|
|
27
|
+
byte_count = len(encoded)
|
|
28
|
+
word_count = len(text.split())
|
|
29
|
+
line_count = text.count("\n") + (1 if text else 0)
|
|
30
|
+
return byte_count, word_count, line_count
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _default_coefficients() -> tuple[float, float, float, float]:
|
|
34
|
+
return (1.0, 0.19, 0.75, 1.1)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _gaussian_solve(matrix: list[list[float]], vector: list[float]) -> list[float] | None:
|
|
38
|
+
n = len(vector)
|
|
39
|
+
if n == 0:
|
|
40
|
+
return None
|
|
41
|
+
try:
|
|
42
|
+
for i in range(n):
|
|
43
|
+
pivot = i
|
|
44
|
+
for r in range(i + 1, n):
|
|
45
|
+
if abs(matrix[r][i]) > abs(matrix[pivot][i]):
|
|
46
|
+
pivot = r
|
|
47
|
+
if abs(matrix[pivot][i]) < 1e-12:
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
if pivot != i:
|
|
51
|
+
matrix[i], matrix[pivot] = matrix[pivot], matrix[i]
|
|
52
|
+
vector[i], vector[pivot] = vector[pivot], vector[i]
|
|
53
|
+
|
|
54
|
+
pivot_val = matrix[i][i]
|
|
55
|
+
for c in range(i, n):
|
|
56
|
+
matrix[i][c] /= pivot_val
|
|
57
|
+
vector[i] /= pivot_val
|
|
58
|
+
|
|
59
|
+
for r in range(n):
|
|
60
|
+
if r == i:
|
|
61
|
+
continue
|
|
62
|
+
factor = matrix[r][i]
|
|
63
|
+
if factor == 0:
|
|
64
|
+
continue
|
|
65
|
+
for c in range(i, n):
|
|
66
|
+
matrix[r][c] -= factor * matrix[i][c]
|
|
67
|
+
vector[r] -= factor * vector[i]
|
|
68
|
+
return vector
|
|
69
|
+
except Exception:
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _fit_linear_coefficients(samples: Iterable[tuple[str, int]]) -> tuple[float, float, float, float]:
|
|
74
|
+
rows: list[list[float]] = []
|
|
75
|
+
targets: list[float] = []
|
|
76
|
+
for text, tokens in samples:
|
|
77
|
+
bcount, wcount, lcount = _extract_features(text)
|
|
78
|
+
rows.append([1.0, float(bcount), float(wcount), float(lcount)])
|
|
79
|
+
targets.append(float(tokens))
|
|
80
|
+
|
|
81
|
+
dim = 4
|
|
82
|
+
if len(rows) < dim:
|
|
83
|
+
return _default_coefficients()
|
|
84
|
+
|
|
85
|
+
xtx = [[0.0 for _ in range(dim)] for _ in range(dim)]
|
|
86
|
+
xty = [0.0 for _ in range(dim)]
|
|
87
|
+
for row, target in zip(rows, targets):
|
|
88
|
+
for i in range(dim):
|
|
89
|
+
xty[i] += row[i] * target
|
|
90
|
+
for j in range(dim):
|
|
91
|
+
xtx[i][j] += row[i] * row[j]
|
|
92
|
+
|
|
93
|
+
solved = _gaussian_solve(xtx, xty)
|
|
94
|
+
if solved is None:
|
|
95
|
+
return _default_coefficients()
|
|
96
|
+
|
|
97
|
+
return (float(solved[0]), float(solved[1]), float(solved[2]), float(solved[3]))
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
_CALIBRATION_SAMPLES: tuple[tuple[str, int], ...] = (
|
|
101
|
+
("ls", 5),
|
|
102
|
+
("git status", 7),
|
|
103
|
+
("echo 'hello world'", 10),
|
|
104
|
+
("python3 -m pytest tests/hooks/test_feature_flags_v2.py -q", 18),
|
|
105
|
+
("def hello():\n return 'world'\n", 24),
|
|
106
|
+
(
|
|
107
|
+
"""from pathlib import Path\nfor path in Path('hooks').glob('*.py'):\n print(path.name)\n""",
|
|
108
|
+
44,
|
|
109
|
+
),
|
|
110
|
+
(
|
|
111
|
+
"""def estimate_tokens(text: str, tier: int = 1) -> int:\n if tier == 1:\n return max(1, int(len(text) / 3.5))\n return 0\n""",
|
|
112
|
+
80,
|
|
113
|
+
),
|
|
114
|
+
(
|
|
115
|
+
"\n".join(["line with common code and comments" for _ in range(80)]),
|
|
116
|
+
720,
|
|
117
|
+
),
|
|
118
|
+
(
|
|
119
|
+
"\n".join(["longer source line with punctuation () {} [] == != <= >=" for _ in range(250)]),
|
|
120
|
+
1800,
|
|
121
|
+
),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
_COEFFICIENTS = _fit_linear_coefficients(_CALIBRATION_SAMPLES)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _estimate_tier1(text: str) -> int:
|
|
128
|
+
if not text:
|
|
129
|
+
return 0
|
|
130
|
+
return max(1, int(len(text) / 3.5))
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _estimate_tier2(text: str) -> int:
|
|
134
|
+
if not text:
|
|
135
|
+
return 0
|
|
136
|
+
bias, w_bytes, w_words, w_lines = _COEFFICIENTS
|
|
137
|
+
bcount, wcount, lcount = _extract_features(text)
|
|
138
|
+
prediction = bias + (w_bytes * bcount) + (w_words * wcount) + (w_lines * lcount)
|
|
139
|
+
return max(1, _safe_int(prediction))
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _get_anthropic_api_key() -> str | None:
|
|
143
|
+
try:
|
|
144
|
+
store_mod = importlib.import_module("credential_store")
|
|
145
|
+
key = store_mod.get_active_key("anthropic")
|
|
146
|
+
if key:
|
|
147
|
+
return key
|
|
148
|
+
except (ImportError, RuntimeError, ValueError, OSError, AttributeError):
|
|
149
|
+
pass
|
|
150
|
+
return os.environ.get("ANTHROPIC_API_KEY")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _estimate_tier3(text: str) -> int:
|
|
154
|
+
if not text:
|
|
155
|
+
return 0
|
|
156
|
+
|
|
157
|
+
api_key = _get_anthropic_api_key()
|
|
158
|
+
if not api_key:
|
|
159
|
+
return _estimate_tier2(text)
|
|
160
|
+
|
|
161
|
+
payload = {
|
|
162
|
+
"model": API_MODEL,
|
|
163
|
+
"messages": [{"role": "user", "content": text}],
|
|
164
|
+
}
|
|
165
|
+
body = json.dumps(payload).encode("utf-8")
|
|
166
|
+
request = urllib.request.Request(
|
|
167
|
+
API_URL,
|
|
168
|
+
data=body,
|
|
169
|
+
method="POST",
|
|
170
|
+
headers={
|
|
171
|
+
"content-type": "application/json",
|
|
172
|
+
"x-api-key": api_key,
|
|
173
|
+
"anthropic-version": "2023-06-01",
|
|
174
|
+
},
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
with urllib.request.urlopen(request, timeout=8) as response:
|
|
179
|
+
raw = response.read().decode("utf-8")
|
|
180
|
+
parsed = json.loads(raw)
|
|
181
|
+
token_value = parsed.get("input_tokens")
|
|
182
|
+
if isinstance(token_value, int) and token_value >= 0:
|
|
183
|
+
return token_value
|
|
184
|
+
except Exception:
|
|
185
|
+
return _estimate_tier2(text)
|
|
186
|
+
|
|
187
|
+
return _estimate_tier2(text)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def auto_select_tier(operation: str, text: str = "") -> int:
|
|
191
|
+
normalized = (operation or "").strip().lower()
|
|
192
|
+
if normalized == _FEATURE_UI_DISPLAY:
|
|
193
|
+
return 1
|
|
194
|
+
if normalized == _FEATURE_BUDGET_ENFORCEMENT:
|
|
195
|
+
return 2
|
|
196
|
+
if normalized == _FEATURE_PREFLIGHT:
|
|
197
|
+
if len(text) >= 8000:
|
|
198
|
+
return 3
|
|
199
|
+
if _estimate_tier2(text) >= 1000:
|
|
200
|
+
return 3
|
|
201
|
+
return 2
|
|
202
|
+
return 1
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def estimate_tokens(text: str, tier: int = 1) -> int:
|
|
206
|
+
"""Estimate token count with 3 reliability/cost tiers.
|
|
207
|
+
|
|
208
|
+
Tier 1: fast heuristic (`len(text)/3.5`).
|
|
209
|
+
Tier 2: calibrated linear model using bytes, words, lines.
|
|
210
|
+
Tier 3: Anthropic count_tokens API with graceful fallback to tier 2.
|
|
211
|
+
"""
|
|
212
|
+
try:
|
|
213
|
+
if tier == 1:
|
|
214
|
+
return _estimate_tier1(text)
|
|
215
|
+
if tier == 2:
|
|
216
|
+
return _estimate_tier2(text)
|
|
217
|
+
if tier == 3:
|
|
218
|
+
return _estimate_tier3(text)
|
|
219
|
+
return _estimate_tier1(text)
|
|
220
|
+
except Exception:
|
|
221
|
+
return _estimate_tier1(text)
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""SessionStart Hook — Smart Branch Manager.
|
|
3
|
+
|
|
4
|
+
Auto-creates a feature branch when on main/master/develop.
|
|
5
|
+
Extracts task description from OMG state files for branch naming.
|
|
6
|
+
|
|
7
|
+
Feature-gated: OMG_GIT_WORKFLOW_ENABLED (uses get_feature_flag('GIT_WORKFLOW'))
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
import subprocess
|
|
15
|
+
import sys
|
|
16
|
+
from datetime import datetime
|
|
17
|
+
|
|
18
|
+
HOOKS_DIR = os.path.dirname(__file__)
|
|
19
|
+
if HOOKS_DIR not in sys.path:
|
|
20
|
+
sys.path.insert(0, HOOKS_DIR)
|
|
21
|
+
|
|
22
|
+
from _common import setup_crash_handler, json_input, get_feature_flag
|
|
23
|
+
|
|
24
|
+
setup_crash_handler("branch-manager", fail_closed=False)
|
|
25
|
+
|
|
26
|
+
# Default branches that trigger feature branch creation
|
|
27
|
+
DEFAULT_BRANCHES = frozenset({"main", "master", "develop"})
|
|
28
|
+
|
|
29
|
+
# Max length for the descriptive part of branch name
|
|
30
|
+
MAX_BRANCH_NAME_LEN = 50
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _get_project_dir() -> str:
|
|
34
|
+
"""Get project directory from env or cwd."""
|
|
35
|
+
return os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _has_git(project_dir: str) -> bool:
|
|
39
|
+
"""Check if project_dir is inside a git repo."""
|
|
40
|
+
try:
|
|
41
|
+
result = subprocess.run(
|
|
42
|
+
["git", "-C", project_dir, "rev-parse", "--git-dir"],
|
|
43
|
+
capture_output=True, text=True, timeout=5,
|
|
44
|
+
)
|
|
45
|
+
return result.returncode == 0
|
|
46
|
+
except Exception:
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _current_branch(project_dir: str) -> str | None:
|
|
51
|
+
"""Get current branch name. Returns None on failure."""
|
|
52
|
+
try:
|
|
53
|
+
result = subprocess.run(
|
|
54
|
+
["git", "-C", project_dir, "rev-parse", "--abbrev-ref", "HEAD"],
|
|
55
|
+
capture_output=True, text=True, timeout=5,
|
|
56
|
+
)
|
|
57
|
+
if result.returncode == 0:
|
|
58
|
+
return result.stdout.strip()
|
|
59
|
+
except Exception:
|
|
60
|
+
pass
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _sanitize_branch_name(description: str) -> str:
|
|
65
|
+
"""Sanitize a description into a valid git branch name segment.
|
|
66
|
+
|
|
67
|
+
Rules:
|
|
68
|
+
- Lowercase
|
|
69
|
+
- Replace spaces/underscores with hyphens
|
|
70
|
+
- Strip special characters (keep alphanumeric and hyphens)
|
|
71
|
+
- Collapse consecutive hyphens
|
|
72
|
+
- Strip leading/trailing hyphens
|
|
73
|
+
- Max MAX_BRANCH_NAME_LEN chars
|
|
74
|
+
"""
|
|
75
|
+
name = description.lower().strip()
|
|
76
|
+
# Replace spaces and underscores with hyphens
|
|
77
|
+
name = re.sub(r"[\s_]+", "-", name)
|
|
78
|
+
# Remove everything except alphanumeric and hyphens
|
|
79
|
+
name = re.sub(r"[^a-z0-9-]", "", name)
|
|
80
|
+
# Collapse consecutive hyphens
|
|
81
|
+
name = re.sub(r"-{2,}", "-", name)
|
|
82
|
+
# Strip leading/trailing hyphens
|
|
83
|
+
name = name.strip("-")
|
|
84
|
+
# Truncate to max length, but don't cut mid-word if possible
|
|
85
|
+
if len(name) > MAX_BRANCH_NAME_LEN:
|
|
86
|
+
truncated = name[:MAX_BRANCH_NAME_LEN]
|
|
87
|
+
# Try to cut at last hyphen to avoid mid-word truncation
|
|
88
|
+
last_hyphen = truncated.rfind("-")
|
|
89
|
+
if last_hyphen > 20:
|
|
90
|
+
truncated = truncated[:last_hyphen]
|
|
91
|
+
name = truncated.rstrip("-")
|
|
92
|
+
return name
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _extract_task_description(project_dir: str) -> str | None:
|
|
96
|
+
"""Extract task description from OMG state files.
|
|
97
|
+
|
|
98
|
+
Priority order:
|
|
99
|
+
(a) .omg/state/_plan.md title (first # heading)
|
|
100
|
+
(b) .omg/state/_checklist.md first item
|
|
101
|
+
(c) .omg/state/working-memory.md last entry
|
|
102
|
+
(d) fallback: None (caller uses session-{timestamp})
|
|
103
|
+
"""
|
|
104
|
+
state_dir = os.path.join(project_dir, ".omg", "state")
|
|
105
|
+
|
|
106
|
+
# (a) Plan title
|
|
107
|
+
plan_path = os.path.join(state_dir, "_plan.md")
|
|
108
|
+
if os.path.isfile(plan_path):
|
|
109
|
+
try:
|
|
110
|
+
with open(plan_path, "r", encoding="utf-8", errors="ignore") as f:
|
|
111
|
+
for line in f:
|
|
112
|
+
line = line.strip()
|
|
113
|
+
if line.startswith("# "):
|
|
114
|
+
title = line[2:].strip()
|
|
115
|
+
if title:
|
|
116
|
+
return title
|
|
117
|
+
except Exception:
|
|
118
|
+
pass
|
|
119
|
+
|
|
120
|
+
# (b) Checklist first item
|
|
121
|
+
checklist_path = os.path.join(state_dir, "_checklist.md")
|
|
122
|
+
if os.path.isfile(checklist_path):
|
|
123
|
+
try:
|
|
124
|
+
with open(checklist_path, "r", encoding="utf-8", errors="ignore") as f:
|
|
125
|
+
for line in f:
|
|
126
|
+
line = line.strip()
|
|
127
|
+
# Match markdown checkbox items: - [ ] or - [x]
|
|
128
|
+
m = re.match(r"^-\s*\[.\]\s*(.+)$", line)
|
|
129
|
+
if m:
|
|
130
|
+
item = m.group(1).strip()
|
|
131
|
+
if item:
|
|
132
|
+
return item
|
|
133
|
+
except Exception:
|
|
134
|
+
pass
|
|
135
|
+
|
|
136
|
+
# (c) Working memory last entry
|
|
137
|
+
wm_path = os.path.join(state_dir, "working-memory.md")
|
|
138
|
+
if os.path.isfile(wm_path):
|
|
139
|
+
try:
|
|
140
|
+
with open(wm_path, "r", encoding="utf-8", errors="ignore") as f:
|
|
141
|
+
content = f.read()
|
|
142
|
+
# Split by ## headings, take last entry's content
|
|
143
|
+
sections = re.split(r"\n## ", content)
|
|
144
|
+
if len(sections) > 1:
|
|
145
|
+
# Last section: first line is heading, rest is content
|
|
146
|
+
last_lines = sections[-1].split("\n")
|
|
147
|
+
# Find first non-empty content line after heading
|
|
148
|
+
for line in last_lines[1:]:
|
|
149
|
+
line = line.strip()
|
|
150
|
+
if line:
|
|
151
|
+
return line
|
|
152
|
+
# Fallback to heading if no content
|
|
153
|
+
heading = last_lines[0].strip()
|
|
154
|
+
if heading:
|
|
155
|
+
return heading
|
|
156
|
+
elif sections:
|
|
157
|
+
# Single section — try first non-empty non-heading line
|
|
158
|
+
for line in sections[0].split("\n"):
|
|
159
|
+
line = line.strip()
|
|
160
|
+
if line and not line.startswith("#"):
|
|
161
|
+
return line
|
|
162
|
+
except Exception:
|
|
163
|
+
pass
|
|
164
|
+
|
|
165
|
+
# (d) No state files found
|
|
166
|
+
return None
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _is_merge_writer_locked(project_dir: str) -> bool:
|
|
170
|
+
try:
|
|
171
|
+
_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
172
|
+
if _root not in sys.path:
|
|
173
|
+
sys.path.insert(0, _root)
|
|
174
|
+
from runtime.merge_writer import MergeWriter # pyright: ignore[reportMissingImports]
|
|
175
|
+
return MergeWriter(project_dir).is_locked()
|
|
176
|
+
except Exception:
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _create_branch(project_dir: str, branch_name: str) -> bool:
|
|
181
|
+
"""Create and checkout a new branch. Returns True on success."""
|
|
182
|
+
if _is_merge_writer_locked(project_dir):
|
|
183
|
+
print(
|
|
184
|
+
f"[OMG branch-manager] Branch creation blocked: merge-writer lock is held",
|
|
185
|
+
file=sys.stderr,
|
|
186
|
+
)
|
|
187
|
+
return False
|
|
188
|
+
try:
|
|
189
|
+
result = subprocess.run(
|
|
190
|
+
["git", "-C", project_dir, "checkout", "-b", branch_name],
|
|
191
|
+
capture_output=True, text=True, timeout=10,
|
|
192
|
+
)
|
|
193
|
+
return result.returncode == 0
|
|
194
|
+
except Exception:
|
|
195
|
+
return False
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def main() -> None:
|
|
199
|
+
"""Main hook entry point."""
|
|
200
|
+
data = json_input()
|
|
201
|
+
|
|
202
|
+
# Feature gate: exit silently if disabled
|
|
203
|
+
if not get_feature_flag("GIT_WORKFLOW", default=False):
|
|
204
|
+
sys.exit(0)
|
|
205
|
+
|
|
206
|
+
project_dir = _get_project_dir()
|
|
207
|
+
|
|
208
|
+
# No-op if not a git repo
|
|
209
|
+
if not _has_git(project_dir):
|
|
210
|
+
sys.exit(0)
|
|
211
|
+
|
|
212
|
+
# Get current branch
|
|
213
|
+
branch = _current_branch(project_dir)
|
|
214
|
+
if branch is None:
|
|
215
|
+
sys.exit(0)
|
|
216
|
+
|
|
217
|
+
# No-op if already on a non-default branch (feature branch, etc.)
|
|
218
|
+
if branch not in DEFAULT_BRANCHES:
|
|
219
|
+
sys.exit(0)
|
|
220
|
+
|
|
221
|
+
# Extract task description and build branch name
|
|
222
|
+
description = _extract_task_description(project_dir)
|
|
223
|
+
if description:
|
|
224
|
+
sanitized = _sanitize_branch_name(description)
|
|
225
|
+
else:
|
|
226
|
+
sanitized = ""
|
|
227
|
+
|
|
228
|
+
if not sanitized:
|
|
229
|
+
# Fallback: session-{timestamp}
|
|
230
|
+
sanitized = f"session-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
|
|
231
|
+
|
|
232
|
+
target_branch = f"feature/{sanitized}"
|
|
233
|
+
|
|
234
|
+
# Dry-run mode: output what would happen without executing
|
|
235
|
+
dry_run = os.environ.get("OMG_GIT_WORKFLOW_DRY_RUN", "").lower() in ("1", "true", "yes")
|
|
236
|
+
if dry_run:
|
|
237
|
+
print(
|
|
238
|
+
f"[OMG branch-manager] DRY-RUN: Would create branch '{target_branch}' from '{branch}'",
|
|
239
|
+
file=sys.stderr,
|
|
240
|
+
)
|
|
241
|
+
sys.exit(0)
|
|
242
|
+
|
|
243
|
+
# Create the feature branch
|
|
244
|
+
success = _create_branch(project_dir, target_branch)
|
|
245
|
+
if success:
|
|
246
|
+
print(
|
|
247
|
+
f"[OMG branch-manager] Created branch '{target_branch}' from '{branch}'",
|
|
248
|
+
file=sys.stderr,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
sys.exit(0)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
if __name__ == "__main__":
|
|
255
|
+
main()
|