core-runtime 0.1.1__py3-none-any.whl
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.
- api/__init__.py +4 -0
- api/cli/__init__.py +10 -0
- api/cli/audit_client.py +92 -0
- api/cli/census_client.py +77 -0
- api/cli/client.py +508 -0
- api/cli/coverage_client.py +121 -0
- api/cli/daemon_client.py +42 -0
- api/cli/fix_client.py +101 -0
- api/cli/inspect_client.py +143 -0
- api/cli/integration_client.py +42 -0
- api/cli/integrity_client.py +45 -0
- api/cli/proposals_client.py +101 -0
- api/cli/quality_client.py +83 -0
- api/cli/refactor_client.py +82 -0
- api/cli/sync_client.py +106 -0
- api/dependencies.py +37 -0
- api/errors.py +74 -0
- api/main.py +88 -0
- api/v1/__init__.py +4 -0
- api/v1/audit_routes.py +302 -0
- api/v1/census_routes.py +207 -0
- api/v1/coverage_routes.py +352 -0
- api/v1/daemon_routes.py +86 -0
- api/v1/development_routes.py +70 -0
- api/v1/fix_routes.py +428 -0
- api/v1/inspect_routes.py +220 -0
- api/v1/integration_routes.py +56 -0
- api/v1/integrity_routes.py +72 -0
- api/v1/knowledge_routes.py +36 -0
- api/v1/lint_routes.py +40 -0
- api/v1/proposals_routes.py +267 -0
- api/v1/quality_routes.py +272 -0
- api/v1/refactor_routes.py +225 -0
- api/v1/sync_routes.py +261 -0
- body/__init__.py +4 -0
- body/analyzers/__init__.py +25 -0
- body/analyzers/base_analyzer.py +28 -0
- body/analyzers/constitutional_path_analyzer.py +63 -0
- body/analyzers/file_analyzer.py +211 -0
- body/analyzers/knowledge_graph_analyzer.py +86 -0
- body/analyzers/prompt_analyzer.py +155 -0
- body/analyzers/symbol_extractor.py +280 -0
- body/atomic/__init__.py +74 -0
- body/atomic/build_tests_action.py +354 -0
- body/atomic/check_actions.py +142 -0
- body/atomic/crate_ops.py +59 -0
- body/atomic/executor.py +470 -0
- body/atomic/file_ops.py +153 -0
- body/atomic/fix_actions.py +1142 -0
- body/atomic/import_resolver.py +200 -0
- body/atomic/metadata_ops.py +161 -0
- body/atomic/modularity_fix.py +839 -0
- body/atomic/modularity_splitter.py +521 -0
- body/atomic/proposal_lifecycle_actions.py +171 -0
- body/atomic/registry.py +326 -0
- body/atomic/remediate_cognitive_role.py +104 -0
- body/atomic/sandbox_lifecycle.py +252 -0
- body/atomic/split_plan.py +155 -0
- body/atomic/sync_actions/__init__.py +22 -0
- body/atomic/sync_actions/chunking_helpers.py +218 -0
- body/atomic/sync_actions/sync_actions.py +431 -0
- body/atomic/test_actions.py +47 -0
- body/autonomy/__init__.py +16 -0
- body/autonomy/audit_analyzer.py +343 -0
- body/autonomy/micro_proposal_executor.py +316 -0
- body/crate_processing/canary_executor.py +144 -0
- body/evaluators/__init__.py +27 -0
- body/evaluators/atomic_actions_evaluator.py +162 -0
- body/evaluators/atomic_actions_format.py +45 -0
- body/evaluators/atomic_actions_rules.py +278 -0
- body/evaluators/base_evaluator.py +67 -0
- body/evaluators/clarity_evaluator.py +83 -0
- body/evaluators/constitutional_evaluator.py +227 -0
- body/evaluators/failure_evaluator.py +136 -0
- body/evaluators/performance_evaluator.py +341 -0
- body/evaluators/security_evaluator.py +393 -0
- body/flows/__init__.py +33 -0
- body/flows/executor.py +275 -0
- body/flows/registry.py +272 -0
- body/flows/result.py +113 -0
- body/governance/__init__.py +29 -0
- body/governance/body_contracts_service.py +317 -0
- body/governance/code_validator.py +118 -0
- body/governance/engine_dispatcher.py +128 -0
- body/governance/intent_guard.py +592 -0
- body/governance/intent_pattern_validators.py +197 -0
- body/governance/key_management_service.py +100 -0
- body/governance/path_validator.py +187 -0
- body/governance/remediation_service.py +263 -0
- body/governance/runtime_validator.py +184 -0
- body/infrastructure/bootstrap.py +135 -0
- body/infrastructure/lifespan.py +85 -0
- body/infrastructure/repositories/__init__.py +1 -0
- body/infrastructure/repositories/decision_trace_repository.py +210 -0
- body/infrastructure/repositories/refusal_repository.py +294 -0
- body/introspection/__init__.py +4 -0
- body/introspection/capability_discovery_service.py +107 -0
- body/introspection/discovery/from_kgb.py +33 -0
- body/introspection/discovery/from_source_scan.py +40 -0
- body/introspection/discovery/loader.py +62 -0
- body/introspection/discovery/registry.py +22 -0
- body/introspection/discovery/semantics.py +21 -0
- body/introspection/discovery/sync.py +47 -0
- body/introspection/drift_detector.py +81 -0
- body/introspection/drift_service.py +48 -0
- body/introspection/export_vectors.py +133 -0
- body/introspection/generate_capability_docs.py +130 -0
- body/introspection/generate_correction_map.py +98 -0
- body/introspection/graph_analysis_service.py +66 -0
- body/introspection/knowledge_graph_service.py +170 -0
- body/introspection/semantic_clusterer.py +128 -0
- body/introspection/symbol_index_builder.py +244 -0
- body/introspection/sync/engine.py +92 -0
- body/introspection/sync/scanner.py +56 -0
- body/introspection/sync/visitor.py +83 -0
- body/introspection/sync_service.py +62 -0
- body/invokers/__init__.py +4 -0
- body/invokers/capability_invoker.py +4 -0
- body/maintenance/command_sync_service.py +73 -0
- body/maintenance/dotenv_sync_service.py +99 -0
- body/maintenance/idempotency_harness.py +70 -0
- body/maintenance/maintenance_service.py +123 -0
- body/maintenance/memory_cleanup_service.py +131 -0
- body/maintenance/refactor_settings_access.py +274 -0
- body/maintenance/scripts/__init__.py +5 -0
- body/maintenance/scripts/context_export.py +278 -0
- body/maintenance/scripts/vector_verify.py +73 -0
- body/maintenance/sync_vectors.py +338 -0
- body/models/__init__.py +4 -0
- body/project_lifecycle/__init__.py +4 -0
- body/project_lifecycle/bootstrap_service.py +157 -0
- body/project_lifecycle/definition_service.py +264 -0
- body/project_lifecycle/integration_service.py +113 -0
- body/project_lifecycle/scaffolding_service.py +187 -0
- body/quality/coverage_analyzer.py +177 -0
- body/repositories/__init__.py +4 -0
- body/self_healing/atomic_actions_fixer.py +113 -0
- body/self_healing/body_ui_fixer.py +193 -0
- body/self_healing/capability_parser.py +65 -0
- body/self_healing/code_style_service.py +51 -0
- body/self_healing/complexity_filter.py +70 -0
- body/self_healing/docstring_service.py +345 -0
- body/self_healing/duplicate_id_service.py +407 -0
- body/self_healing/duplicates_service.py +165 -0
- body/self_healing/handlers/__init__.py +1 -0
- body/self_healing/handlers/id_assignment_handler.py +201 -0
- body/self_healing/handlers/import_sorting_handler.py +181 -0
- body/self_healing/header_service.py +308 -0
- body/self_healing/id_tagging_service.py +227 -0
- body/self_healing/knowledge_consolidation_service.py +80 -0
- body/self_healing/logging_service.py +292 -0
- body/self_healing/owner_tagging_service.py +5 -0
- body/self_healing/placeholder_fixer_service.py +27 -0
- body/self_healing/prune_private_capabilities.py +144 -0
- body/self_healing/purge_legacy_tags_service.py +146 -0
- body/self_healing/remediation_models.py +238 -0
- body/self_healing/test_context/__init__.py +10 -0
- body/self_healing/test_context/detectors.py +74 -0
- body/self_healing/test_context/examples.py +53 -0
- body/self_healing/test_context/formatter.py +65 -0
- body/self_healing/test_context/metrics.py +62 -0
- body/self_healing/test_context/models.py +83 -0
- body/self_healing/test_context/parsers.py +70 -0
- body/self_healing/test_context_analyzer.py +79 -0
- body/self_healing/test_failure_analyzer.py +259 -0
- body/self_healing/test_target_analyzer.py +118 -0
- body/self_healing/vulture_healer.py +161 -0
- body/services/__init__.py +4 -0
- body/services/artifact_service.py +155 -0
- body/services/blackboard_service/__init__.py +22 -0
- body/services/blackboard_service/blackboard_claim_service.py +216 -0
- body/services/blackboard_service/blackboard_proposal_service.py +305 -0
- body/services/blackboard_service/blackboard_query_service.py +333 -0
- body/services/blackboard_service/blackboard_service.py +602 -0
- body/services/capabilities.py +51 -0
- body/services/cim/__init__.py +22 -0
- body/services/cim/baselines.py +102 -0
- body/services/cim/census_service.py +190 -0
- body/services/cim/cim_constants.py +116 -0
- body/services/cim/cim_path_utils.py +123 -0
- body/services/cim/diff.py +152 -0
- body/services/cim/history.py +94 -0
- body/services/cim/models.py +319 -0
- body/services/cim/policy.py +149 -0
- body/services/cim/scanners.py +332 -0
- body/services/coherence_service.py +552 -0
- body/services/consequence_log_service.py +189 -0
- body/services/constitutional_rule_loader.py +141 -0
- body/services/constitutional_validator.py +366 -0
- body/services/crate_creation_service.py +217 -0
- body/services/crate_processing_service.py +279 -0
- body/services/crawl_service/__init__.py +10 -0
- body/services/crawl_service/main_module.py +531 -0
- body/services/crawl_service/orchestrator.py +452 -0
- body/services/crawl_service/symbol_processing.py +279 -0
- body/services/database_service.py +242 -0
- body/services/doc_service.py +57 -0
- body/services/file_service.py +260 -0
- body/services/governance_claims_service.py +240 -0
- body/services/governance_init.py +41 -0
- body/services/health_log_service.py +167 -0
- body/services/intent_schema_validator.py +211 -0
- body/services/llm_client.py +87 -0
- body/services/mind_state_service.py +129 -0
- body/services/policy_expression_evaluator.py +154 -0
- body/services/proposal_supervision_service.py +187 -0
- body/services/representation_coherence_service.py +209 -0
- body/services/service_registry.py +431 -0
- body/services/session_attached_service.py +51 -0
- body/services/symbol_query_service.py +218 -0
- body/services/symbol_service.py +94 -0
- body/services/validation/__init__.py +14 -0
- body/services/validation/python_validator.py +89 -0
- body/services/validation/validation_policies.py +121 -0
- body/services/worker_registry_service.py +184 -0
- body/validators/__init__.py +1 -0
- body/validators/logic_conservation_validator.py +201 -0
- body/workers/call_site_rewriter.py +527 -0
- body/workers/prompt_artifact_writer.py +323 -0
- cli/__init__.py +4 -0
- cli/admin_cli.py +98 -0
- cli/cli_user.py +121 -0
- cli/commands/__init__.py +4 -0
- cli/commands/audit_reporter.py +272 -0
- cli/commands/check/__init__.py +115 -0
- cli/commands/check/audit.py +130 -0
- cli/commands/check/converters.py +129 -0
- cli/commands/check/diagnostics_commands.py +70 -0
- cli/commands/check/formatters.py +310 -0
- cli/commands/check/imports.py +73 -0
- cli/commands/check/quality.py +71 -0
- cli/commands/check/quality_gates.py +107 -0
- cli/commands/check/rule.py +136 -0
- cli/commands/check/utils.py +28 -0
- cli/commands/check_atomic_actions.py +167 -0
- cli/commands/components.py +66 -0
- cli/commands/coverage/__init__.py +22 -0
- cli/commands/coverage/analysis_commands.py +87 -0
- cli/commands/coverage/check_commands.py +173 -0
- cli/commands/coverage/generation_commands.py +155 -0
- cli/commands/coverage/services/__init__.py +15 -0
- cli/commands/coverage/services/coverage_checker.py +50 -0
- cli/commands/coverage/services/coverage_reporter.py +81 -0
- cli/commands/coverage/services/gaps_analyzer.py +114 -0
- cli/commands/daemon.py +908 -0
- cli/commands/develop.py +127 -0
- cli/commands/diagnostics.py +32 -0
- cli/commands/fix/__init__.py +84 -0
- cli/commands/fix/all_commands.py +94 -0
- cli/commands/fix/atomic_actions.py +48 -0
- cli/commands/fix/audit.py +146 -0
- cli/commands/fix/body_ui.py +93 -0
- cli/commands/fix/code_style.py +52 -0
- cli/commands/fix/db_tools.py +90 -0
- cli/commands/fix/fix_ir.py +79 -0
- cli/commands/fix/handler_discovery.py +54 -0
- cli/commands/fix/imports.py +55 -0
- cli/commands/fix/list_commands.py +54 -0
- cli/commands/fix/metadata.py +160 -0
- cli/commands/fix/modularity.py +88 -0
- cli/commands/fix/settings_access.py +65 -0
- cli/commands/fix_governed.py +103 -0
- cli/commands/fix_logging.py +24 -0
- cli/commands/governance.py +294 -0
- cli/commands/guard.py +125 -0
- cli/commands/inspect/__init__.py +79 -0
- cli/commands/inspect/_helpers.py +226 -0
- cli/commands/inspect/analysis.py +158 -0
- cli/commands/inspect/decisions.py +140 -0
- cli/commands/inspect/diagnostics.py +126 -0
- cli/commands/inspect/drift.py +100 -0
- cli/commands/inspect/patterns.py +102 -0
- cli/commands/inspect/refusals.py +211 -0
- cli/commands/inspect/repo_census.py +175 -0
- cli/commands/inspect/status.py +48 -0
- cli/commands/interactive_test.py +85 -0
- cli/commands/mind.py +49 -0
- cli/commands/refactor.py +234 -0
- cli/commands/refactor_support/__init__.py +7 -0
- cli/commands/refactor_support/analyzer.py +107 -0
- cli/commands/refactor_support/config.py +67 -0
- cli/commands/refactor_support/display.py +170 -0
- cli/commands/refactor_support/recommendations.py +55 -0
- cli/commands/run.py +60 -0
- cli/commands/search.py +103 -0
- cli/commands/status.py +86 -0
- cli/commands/submit.py +23 -0
- cli/interactive.py +177 -0
- cli/logic/__init__.py +7 -0
- cli/logic/agent.py +110 -0
- cli/logic/audit_capability_domains.py +106 -0
- cli/logic/audit_renderer.py +150 -0
- cli/logic/autonomy/actions.py +36 -0
- cli/logic/autonomy/views.py +116 -0
- cli/logic/body_contracts_checker.py +23 -0
- cli/logic/build.py +27 -0
- cli/logic/byor.py +148 -0
- cli/logic/capability.py +27 -0
- cli/logic/cli_utils.py +210 -0
- cli/logic/context.py +7 -0
- cli/logic/db.py +154 -0
- cli/logic/db_manage.py +22 -0
- cli/logic/decision_inspect_logic.py +62 -0
- cli/logic/diagnostics.py +148 -0
- cli/logic/diagnostics_policy.py +100 -0
- cli/logic/diagnostics_registry.py +165 -0
- cli/logic/duplicates.py +19 -0
- cli/logic/embeddings_cli.py +43 -0
- cli/logic/governance/__init__.py +16 -0
- cli/logic/governance/engine.py +216 -0
- cli/logic/governance/forensics_service.py +67 -0
- cli/logic/governance/limb_status_service.py +83 -0
- cli/logic/governance/renderer.py +115 -0
- cli/logic/governance/traceability_service.py +78 -0
- cli/logic/governance_logic.py +33 -0
- cli/logic/hub/__init__.py +14 -0
- cli/logic/hub/app.py +107 -0
- cli/logic/hub/formatter.py +29 -0
- cli/logic/hub/introspection.py +20 -0
- cli/logic/hub/repository.py +17 -0
- cli/logic/init.py +22 -0
- cli/logic/interactive_test/__init__.py +21 -0
- cli/logic/interactive_test/session.py +102 -0
- cli/logic/interactive_test/steps/__init__.py +23 -0
- cli/logic/interactive_test/steps/execution.py +53 -0
- cli/logic/interactive_test/steps/generation.py +88 -0
- cli/logic/interactive_test/steps/healing.py +79 -0
- cli/logic/interactive_test/steps/utils.py +31 -0
- cli/logic/interactive_test/steps/verification.py +71 -0
- cli/logic/interactive_test/ui.py +203 -0
- cli/logic/interactive_test/workflow.py +168 -0
- cli/logic/interactive_test_logic.py +41 -0
- cli/logic/knowledge.py +47 -0
- cli/logic/legacy_scan_logic.py +306 -0
- cli/logic/list_audits.py +49 -0
- cli/logic/log_audit.py +53 -0
- cli/logic/new.py +8 -0
- cli/logic/project_docs.py +28 -0
- cli/logic/reconcile.py +127 -0
- cli/logic/refusal_inspect_logic.py +208 -0
- cli/logic/report.py +47 -0
- cli/logic/status.py +47 -0
- cli/logic/symbol_drift.py +77 -0
- cli/logic/sync.py +48 -0
- cli/logic/sync_domains.py +72 -0
- cli/logic/sync_manifest.py +31 -0
- cli/logic/tools.py +133 -0
- cli/logic/utils_migration.py +43 -0
- cli/logic/validate.py +107 -0
- cli/logic/vector_drift.py +109 -0
- cli/logic/yaml_processor.py +5 -0
- cli/renderers/audit_detail.py +37 -0
- cli/renderers/audit_overview.py +39 -0
- cli/resources/__init__.py +27 -0
- cli/resources/admin/__init__.py +23 -0
- cli/resources/admin/coverage.py +63 -0
- cli/resources/admin/debt_scan.py +195 -0
- cli/resources/admin/forensics.py +97 -0
- cli/resources/admin/health.py +66 -0
- cli/resources/admin/hub.py +9 -0
- cli/resources/admin/meta.py +47 -0
- cli/resources/admin/patterns.py +28 -0
- cli/resources/admin/refusals.py +31 -0
- cli/resources/admin/self_check.py +175 -0
- cli/resources/admin/status.py +66 -0
- cli/resources/admin/summary.py +67 -0
- cli/resources/admin/traces.py +46 -0
- cli/resources/admin/validate_env.py +56 -0
- cli/resources/code/__init__.py +31 -0
- cli/resources/code/actions.py +48 -0
- cli/resources/code/audit.py +416 -0
- cli/resources/code/audit_duplicates.py +22 -0
- cli/resources/code/check_imports.py +75 -0
- cli/resources/code/check_ui.py +62 -0
- cli/resources/code/clarity.py +51 -0
- cli/resources/code/complexity.py +55 -0
- cli/resources/code/docstrings.py +51 -0
- cli/resources/code/fix_atomic.py +51 -0
- cli/resources/code/format.py +62 -0
- cli/resources/code/hub.py +10 -0
- cli/resources/code/integrity.py +75 -0
- cli/resources/code/lint.py +37 -0
- cli/resources/code/logging.py +49 -0
- cli/resources/code/refactor.py +32 -0
- cli/resources/code/test.py +30 -0
- cli/resources/coherence/__init__.py +13 -0
- cli/resources/coherence/check.py +111 -0
- cli/resources/coherence/hub.py +13 -0
- cli/resources/coherence/repair_counts.py +73 -0
- cli/resources/coherence/report.py +144 -0
- cli/resources/coherence/seed.py +297 -0
- cli/resources/coherence/supersede.py +124 -0
- cli/resources/coherence/triage.py +81 -0
- cli/resources/constitution/__init__.py +19 -0
- cli/resources/constitution/audit.py +49 -0
- cli/resources/constitution/query.py +45 -0
- cli/resources/constitution/status.py +34 -0
- cli/resources/constitution/validate.py +36 -0
- cli/resources/context/__init__.py +21 -0
- cli/resources/context/build.py +374 -0
- cli/resources/context/cache.py +156 -0
- cli/resources/context/explain.py +140 -0
- cli/resources/context/hub.py +11 -0
- cli/resources/context/search.py +114 -0
- cli/resources/database/__init__.py +13 -0
- cli/resources/database/cleanup.py +107 -0
- cli/resources/database/export.py +61 -0
- cli/resources/database/hub.py +11 -0
- cli/resources/database/migrate.py +57 -0
- cli/resources/database/status.py +101 -0
- cli/resources/database/sync.py +84 -0
- cli/resources/database/sync_env.py +76 -0
- cli/resources/database/sync_registry.py +48 -0
- cli/resources/dev/__init__.py +14 -0
- cli/resources/dev/hub.py +11 -0
- cli/resources/dev/refactor.py +92 -0
- cli/resources/dev/stability.py +60 -0
- cli/resources/dev/strategic_audit.py +113 -0
- cli/resources/dev/sync.py +51 -0
- cli/resources/dev/test.py +34 -0
- cli/resources/intent/__init__.py +11 -0
- cli/resources/intent/hub.py +9 -0
- cli/resources/intent/sync_vocabulary.py +396 -0
- cli/resources/project/__init__.py +19 -0
- cli/resources/project/docs.py +41 -0
- cli/resources/project/new.py +40 -0
- cli/resources/project/onboard.py +31 -0
- cli/resources/proposals/__init__.py +28 -0
- cli/resources/proposals/create.py +82 -0
- cli/resources/proposals/integrate.py +49 -0
- cli/resources/proposals/list.py +76 -0
- cli/resources/proposals/manage.py +117 -0
- cli/resources/runtime/__init__.py +9 -0
- cli/resources/runtime/health.py +925 -0
- cli/resources/secrets/__init__.py +10 -0
- cli/resources/secrets/hub.py +9 -0
- cli/resources/secrets/manage.py +309 -0
- cli/resources/symbols/__init__.py +13 -0
- cli/resources/symbols/audit.py +46 -0
- cli/resources/symbols/fix_ids.py +43 -0
- cli/resources/symbols/hub.py +11 -0
- cli/resources/symbols/resolve_duplicates.py +30 -0
- cli/resources/symbols/sync.py +39 -0
- cli/resources/symbols/tag.py +47 -0
- cli/resources/vectors/__init__.py +11 -0
- cli/resources/vectors/cleanup.py +95 -0
- cli/resources/vectors/hub.py +9 -0
- cli/resources/vectors/query.py +105 -0
- cli/resources/vectors/status.py +30 -0
- cli/resources/vectors/sync.py +57 -0
- cli/resources/vectors/sync_code.py +67 -0
- cli/resources/workers/__init__.py +13 -0
- cli/resources/workers/blackboard.py +253 -0
- cli/resources/workers/remediate.py +337 -0
- cli/resources/workers/run.py +140 -0
- cli/utils/__init__.py +32 -0
- cli/utils/annotation_formatter.py +154 -0
- cli/utils/decorators.py +184 -0
- cli/utils/display.py +79 -0
- cli/utils/exit_codes.py +59 -0
- cli/utils/helpers.py +34 -0
- cli/utils/prompts.py +21 -0
- core_runtime-0.1.1.dist-info/LICENSE +21 -0
- core_runtime-0.1.1.dist-info/METADATA +346 -0
- core_runtime-0.1.1.dist-info/RECORD +962 -0
- core_runtime-0.1.1.dist-info/WHEEL +4 -0
- core_runtime-0.1.1.dist-info/entry_points.txt +4 -0
- mind/__init__.py +4 -0
- mind/coherence/__init__.py +1 -0
- mind/coherence/checker.py +314 -0
- mind/coherence/checks/__init__.py +4 -0
- mind/coherence/checks/base.py +34 -0
- mind/coherence/checks/r1_scoped.py +228 -0
- mind/coherence/checks/row2_grounding.py +69 -0
- mind/coherence/checks/row3_citation.py +119 -0
- mind/coherence/checks/row4_naming.py +126 -0
- mind/coherence/checks/sameconcern.py +136 -0
- mind/coherence/checks/specgap.py +233 -0
- mind/coherence/checks/vocabulary.py +112 -0
- mind/coherence/llm_judge.py +207 -0
- mind/enforcement/audit.py +78 -0
- mind/governance/__init__.py +22 -0
- mind/governance/assumption_extractor.py +326 -0
- mind/governance/audit_context.py +520 -0
- mind/governance/audit_postprocessor.py +36 -0
- mind/governance/audit_report_writer.py +46 -0
- mind/governance/audit_types.py +98 -0
- mind/governance/auditor.py +179 -0
- mind/governance/authority_package_builder.py +502 -0
- mind/governance/constitutional_auditor_dynamic.py +362 -0
- mind/governance/enforcement/__init__.py +24 -0
- mind/governance/enforcement_loader.py +245 -0
- mind/governance/enforcement_methods.py +28 -0
- mind/governance/entry_point_policy.py +62 -0
- mind/governance/executable_rule.py +127 -0
- mind/governance/filtered_audit.py +272 -0
- mind/governance/finding_processor.py +76 -0
- mind/governance/meta_validator.py +259 -0
- mind/governance/micro_proposal_validator.py +169 -0
- mind/governance/policy_coverage_service.py +183 -0
- mind/governance/policy_rule.py +94 -0
- mind/governance/rule_conflict_detector.py +127 -0
- mind/governance/rule_executor.py +306 -0
- mind/governance/rule_extractor.py +376 -0
- mind/governance/stateless_audit.py +206 -0
- mind/governance/violation_report.py +136 -0
- mind/logic/engines/_knowledge_gate_duplication.py +117 -0
- mind/logic/engines/action_gate.py +76 -0
- mind/logic/engines/artifact_gate.py +1168 -0
- mind/logic/engines/ast_gate/__init__.py +9 -0
- mind/logic/engines/ast_gate/base.py +263 -0
- mind/logic/engines/ast_gate/checks/__init__.py +35 -0
- mind/logic/engines/ast_gate/checks/async_checks.py +276 -0
- mind/logic/engines/ast_gate/checks/capability_checks.py +197 -0
- mind/logic/engines/ast_gate/checks/conservation_checks.py +126 -0
- mind/logic/engines/ast_gate/checks/generic_checks.py +244 -0
- mind/logic/engines/ast_gate/checks/import_checks.py +164 -0
- mind/logic/engines/ast_gate/checks/knowledge_source_check.py +88 -0
- mind/logic/engines/ast_gate/checks/logging_checks.py +133 -0
- mind/logic/engines/ast_gate/checks/metadata_checks.py +242 -0
- mind/logic/engines/ast_gate/checks/modularity_checks.py +436 -0
- mind/logic/engines/ast_gate/checks/naming_checks.py +120 -0
- mind/logic/engines/ast_gate/checks/prompt_model_checks.py +83 -0
- mind/logic/engines/ast_gate/checks/protected_namespace_access_check.py +298 -0
- mind/logic/engines/ast_gate/checks/purity_checks.py +421 -0
- mind/logic/engines/ast_gate/checks/purity_enforcement_check.py +56 -0
- mind/logic/engines/ast_gate/checks/runtime_import_boundary.py +198 -0
- mind/logic/engines/ast_gate/checks/schema_conformance_checks.py +130 -0
- mind/logic/engines/ast_gate/engine.py +317 -0
- mind/logic/engines/ast_gate.py +19 -0
- mind/logic/engines/base.py +106 -0
- mind/logic/engines/cli_gate/__init__.py +25 -0
- mind/logic/engines/cli_gate/base_check.py +45 -0
- mind/logic/engines/cli_gate/checks/__init__.py +31 -0
- mind/logic/engines/cli_gate/checks/async_execution.py +65 -0
- mind/logic/engines/cli_gate/checks/dangerous_explicit.py +60 -0
- mind/logic/engines/cli_gate/checks/discovery_strict.py +167 -0
- mind/logic/engines/cli_gate/checks/help_required.py +43 -0
- mind/logic/engines/cli_gate/checks/no_duplicates.py +57 -0
- mind/logic/engines/cli_gate/checks/no_layer_exposure.py +48 -0
- mind/logic/engines/cli_gate/checks/resource_first.py +58 -0
- mind/logic/engines/cli_gate/checks/standard_verbs.py +50 -0
- mind/logic/engines/cli_gate/engine.py +211 -0
- mind/logic/engines/glob_gate.py +214 -0
- mind/logic/engines/knowledge_gate.py +410 -0
- mind/logic/engines/llm_gate.py +407 -0
- mind/logic/engines/llm_gate_stub.py +67 -0
- mind/logic/engines/passive_gate.py +45 -0
- mind/logic/engines/regex_gate.py +97 -0
- mind/logic/engines/registry.py +134 -0
- mind/logic/engines/runtime_gate.py +265 -0
- mind/logic/engines/taxonomy_gate.py +229 -0
- mind/logic/engines/workflow_gate/__init__.py +22 -0
- mind/logic/engines/workflow_gate/base_check.py +42 -0
- mind/logic/engines/workflow_gate/checks/__init__.py +32 -0
- mind/logic/engines/workflow_gate/checks/alignment.py +93 -0
- mind/logic/engines/workflow_gate/checks/audit.py +80 -0
- mind/logic/engines/workflow_gate/checks/canary.py +47 -0
- mind/logic/engines/workflow_gate/checks/coverage.py +74 -0
- mind/logic/engines/workflow_gate/checks/dead_code.py +53 -0
- mind/logic/engines/workflow_gate/checks/import_resolution.py +97 -0
- mind/logic/engines/workflow_gate/checks/linter.py +104 -0
- mind/logic/engines/workflow_gate/checks/quality.py +49 -0
- mind/logic/engines/workflow_gate/checks/ruff_format.py +99 -0
- mind/logic/engines/workflow_gate/checks/tests.py +81 -0
- mind/logic/engines/workflow_gate/engine.py +207 -0
- shared/__init__.py +32 -0
- shared/action_logger.py +61 -0
- shared/action_types.py +199 -0
- shared/activity_logging.py +149 -0
- shared/ai/constitutional_envelope.py +341 -0
- shared/ai/prompt_model.py +585 -0
- shared/ai/response_parser.py +191 -0
- shared/ast_utility.py +279 -0
- shared/atomic_action.py +117 -0
- shared/cli/__init__.py +6 -0
- shared/cli/app_introspection.py +134 -0
- shared/cli/command_meta.py +224 -0
- shared/cli_types.py +92 -0
- shared/component_primitive.py +216 -0
- shared/config.py +216 -0
- shared/config_loader.py +54 -0
- shared/context.py +113 -0
- shared/exceptions.py +100 -0
- shared/governance/__init__.py +9 -0
- shared/governance/coherence_harvester.py +258 -0
- shared/governance_token.py +77 -0
- shared/infrastructure/__init__.py +5 -0
- shared/infrastructure/adapters/__init__.py +5 -0
- shared/infrastructure/adapters/embedding_provider.py +66 -0
- shared/infrastructure/bootstrap_registry.py +57 -0
- shared/infrastructure/clients/__init__.py +5 -0
- shared/infrastructure/clients/qdrant_client.py +455 -0
- shared/infrastructure/config_service.py +382 -0
- shared/infrastructure/config_validator.py +70 -0
- shared/infrastructure/context/__init__.py +45 -0
- shared/infrastructure/context/builder.py +804 -0
- shared/infrastructure/context/cache.py +101 -0
- shared/infrastructure/context/database.py +205 -0
- shared/infrastructure/context/limb_workspace.py +134 -0
- shared/infrastructure/context/models.py +65 -0
- shared/infrastructure/context/providers/__init__.py +18 -0
- shared/infrastructure/context/providers/ast.py +211 -0
- shared/infrastructure/context/providers/db.py +165 -0
- shared/infrastructure/context/providers/vectors.py +195 -0
- shared/infrastructure/context/redactor.py +109 -0
- shared/infrastructure/context/serializers.py +144 -0
- shared/infrastructure/context/service.py +271 -0
- shared/infrastructure/context/validator.py +247 -0
- shared/infrastructure/database/models/__init__.py +80 -0
- shared/infrastructure/database/models/autonomous_proposals.py +83 -0
- shared/infrastructure/database/models/decision_traces.py +129 -0
- shared/infrastructure/database/models/governance.py +183 -0
- shared/infrastructure/database/models/knowledge.py +205 -0
- shared/infrastructure/database/models/learning.py +99 -0
- shared/infrastructure/database/models/llm_config.py +274 -0
- shared/infrastructure/database/models/operations.py +152 -0
- shared/infrastructure/database/models/refusals.py +147 -0
- shared/infrastructure/database/models/system.py +124 -0
- shared/infrastructure/database/models/vectors.py +113 -0
- shared/infrastructure/database/models/workers.py +96 -0
- shared/infrastructure/database/session_manager.py +166 -0
- shared/infrastructure/diagnostic_service.py +103 -0
- shared/infrastructure/events/__init__.py +5 -0
- shared/infrastructure/events/base.py +44 -0
- shared/infrastructure/events/bus.py +76 -0
- shared/infrastructure/git_service.py +385 -0
- shared/infrastructure/intent/action_risk.py +135 -0
- shared/infrastructure/intent/audit_verdict.py +131 -0
- shared/infrastructure/intent/autonomy_dirty_tree.py +104 -0
- shared/infrastructure/intent/canonical_enums.py +116 -0
- shared/infrastructure/intent/cognitive_roles.py +96 -0
- shared/infrastructure/intent/errors.py +13 -0
- shared/infrastructure/intent/filesystem_operations.py +359 -0
- shared/infrastructure/intent/intent_connector.py +157 -0
- shared/infrastructure/intent/intent_repository.py +707 -0
- shared/infrastructure/intent/intent_validator.py +248 -0
- shared/infrastructure/intent/operational_capabilities.py +470 -0
- shared/infrastructure/intent/operational_config.py +1343 -0
- shared/infrastructure/intent/operational_mode.py +66 -0
- shared/infrastructure/intent/task_type_phases.py +180 -0
- shared/infrastructure/intent/test_coverage_paths.py +181 -0
- shared/infrastructure/intent/vocabulary_projection.py +241 -0
- shared/infrastructure/knowledge/knowledge_service.py +155 -0
- shared/infrastructure/knowledge_graph_service.py +214 -0
- shared/infrastructure/llm/client.py +448 -0
- shared/infrastructure/llm/client_registry.py +153 -0
- shared/infrastructure/llm/fallback_client.py +144 -0
- shared/infrastructure/llm/providers/anthropic.py +113 -0
- shared/infrastructure/llm/providers/base.py +130 -0
- shared/infrastructure/llm/providers/ollama.py +265 -0
- shared/infrastructure/llm/providers/openai.py +168 -0
- shared/infrastructure/repositories/__init__.py +5 -0
- shared/infrastructure/repositories/db/__init__.py +5 -0
- shared/infrastructure/repositories/db/common.py +138 -0
- shared/infrastructure/repositories/db/engine.py +26 -0
- shared/infrastructure/repositories/db/migration_service.py +75 -0
- shared/infrastructure/repositories/db/status_service.py +61 -0
- shared/infrastructure/repositories/memory_repository.py +134 -0
- shared/infrastructure/repositories/symbol_definition_repository.py +170 -0
- shared/infrastructure/repositories/task_repository.py +59 -0
- shared/infrastructure/repositories/vector_link_repository.py +83 -0
- shared/infrastructure/rooted_repository.py +50 -0
- shared/infrastructure/secrets_service.py +317 -0
- shared/infrastructure/specs/__init__.py +9 -0
- shared/infrastructure/specs/specs_repository.py +100 -0
- shared/infrastructure/storage/file_classifier.py +32 -0
- shared/infrastructure/storage/file_handler.py +330 -0
- shared/infrastructure/storage/file_provider.py +233 -0
- shared/infrastructure/storage/integrity_service.py +108 -0
- shared/infrastructure/validation/black_formatter.py +41 -0
- shared/infrastructure/validation/quality.py +46 -0
- shared/infrastructure/validation/ruff_linter.py +104 -0
- shared/infrastructure/validation/syntax_checker.py +45 -0
- shared/infrastructure/validation/test_runner.py +167 -0
- shared/infrastructure/validation/yaml_validator.py +45 -0
- shared/infrastructure/vector/__init__.py +15 -0
- shared/infrastructure/vector/adapters/__init__.py +20 -0
- shared/infrastructure/vector/adapters/constitutional/__init__.py +26 -0
- shared/infrastructure/vector/adapters/constitutional/chunker.py +246 -0
- shared/infrastructure/vector/adapters/constitutional/doc_key_resolver.py +109 -0
- shared/infrastructure/vector/adapters/constitutional/item_builder.py +158 -0
- shared/infrastructure/vector/adapters/constitutional/utils.py +39 -0
- shared/infrastructure/vector/adapters/constitutional_adapter.py +309 -0
- shared/infrastructure/vector/adapters/specs_adapter.py +171 -0
- shared/infrastructure/vector/cognitive_adapter.py +119 -0
- shared/infrastructure/vector/vector_index_service.py +230 -0
- shared/logger.py +195 -0
- shared/models/__init__.py +47 -0
- shared/models/action_result.py +77 -0
- shared/models/audit_models.py +106 -0
- shared/models/audit_rendering.py +30 -0
- shared/models/capability_models.py +22 -0
- shared/models/constitutional_validation.py +185 -0
- shared/models/drift_models.py +24 -0
- shared/models/embedding_payload.py +45 -0
- shared/models/execution_models.py +71 -0
- shared/models/pattern_graph.py +62 -0
- shared/models/prompt_model.py +244 -0
- shared/models/refusal_result.py +294 -0
- shared/models/remediation.py +35 -0
- shared/models/validation_result.py +34 -0
- shared/models/vector_models.py +62 -0
- shared/models/workflow_models.py +242 -0
- shared/path_resolver.py +408 -0
- shared/path_utils.py +60 -0
- shared/processors/base_processor.py +171 -0
- shared/processors/yaml_processor.py +72 -0
- shared/protocols/__init__.py +21 -0
- shared/protocols/brain_services.py +35 -0
- shared/protocols/cognitive.py +35 -0
- shared/protocols/executor.py +47 -0
- shared/protocols/interpreter.py +24 -0
- shared/protocols/knowledge.py +21 -0
- shared/protocols/llm.py +25 -0
- shared/protocols/typer_protocols.py +37 -0
- shared/time.py +18 -0
- shared/universal.py +43 -0
- shared/utils/__init__.py +81 -0
- shared/utils/audit_grouping.py +50 -0
- shared/utils/common_knowledge.py +82 -0
- shared/utils/domain_mapper.py +61 -0
- shared/utils/embedding_utils.py +182 -0
- shared/utils/glob_match.py +93 -0
- shared/utils/header_tools.py +177 -0
- shared/utils/parallel_processor.py +60 -0
- shared/utils/parsing.py +189 -0
- shared/utils/path_utils.py +268 -0
- shared/utils/subprocess_utils.py +87 -0
- shared/workers/__init__.py +19 -0
- shared/workers/base.py +533 -0
- shared/workers/declaration_validator.py +124 -0
- shared/workers/loop_hold_telemetry.py +210 -0
- shared/workers/schedule.py +123 -0
- will/__init__.py +4 -0
- will/agents/__init__.py +4 -0
- will/agents/base_planner.py +133 -0
- will/agents/code_generation/__init__.py +15 -0
- will/agents/code_generation/code_generator.py +247 -0
- will/agents/code_generation/context_formatters.py +99 -0
- will/agents/code_generation/correction_engine.py +157 -0
- will/agents/code_generation/extraction.py +165 -0
- will/agents/code_generation/pattern_validator.py +264 -0
- will/agents/code_generation/prompt_builders.py +209 -0
- will/agents/coder_agent.py +229 -0
- will/agents/coder_agent_refusal_handler.py +168 -0
- will/agents/cognitive_orchestrator.py +152 -0
- will/agents/conversational/__init__.py +13 -0
- will/agents/conversational/agent.py +271 -0
- will/agents/conversational/factory.py +72 -0
- will/agents/conversational/helpers.py +116 -0
- will/agents/execution_agent.py +294 -0
- will/agents/governance_mixin.py +132 -0
- will/agents/planner_agent.py +261 -0
- will/agents/resource_selector.py +228 -0
- will/agents/strategic_auditor/__init__.py +15 -0
- will/agents/strategic_auditor/agent.py +199 -0
- will/agents/strategic_auditor/context_gatherer.py +586 -0
- will/agents/strategic_auditor/effects.py +136 -0
- will/agents/strategic_auditor/models.py +61 -0
- will/agents/strategic_auditor/reasoning.py +169 -0
- will/agents/tagger_agent.py +294 -0
- will/agents/traced_agent_mixin.py +33 -0
- will/autonomy/__init__.py +20 -0
- will/autonomy/autonomous_developer.py +127 -0
- will/autonomy/proposal.py +585 -0
- will/autonomy/proposal_execution_pipeline.py +264 -0
- will/autonomy/proposal_executor.py +410 -0
- will/autonomy/proposal_mapper.py +187 -0
- will/autonomy/proposal_repository.py +118 -0
- will/autonomy/proposal_service.py +251 -0
- will/autonomy/proposal_state_manager.py +239 -0
- will/deciders/__init__.py +9 -0
- will/deciders/governance_decider.py +207 -0
- will/governance/__init__.py +13 -0
- will/governance/audit_remediation_runner.py +197 -0
- will/governance/audit_runner.py +368 -0
- will/governance/census_runner.py +278 -0
- will/governance/coverage_runner.py +489 -0
- will/governance/daemon_runner.py +164 -0
- will/governance/fix_runner.py +693 -0
- will/governance/inspect_runner.py +521 -0
- will/governance/integrity_runner.py +66 -0
- will/governance/lint_runner.py +93 -0
- will/governance/refactor_runner.py +372 -0
- will/governance/sync_runner.py +186 -0
- will/interpreters/__init__.py +44 -0
- will/interpreters/cli_args_interpreter.py +106 -0
- will/interpreters/natural_language_interpreter.py +276 -0
- will/interpreters/request_interpreter.py +126 -0
- will/lifecycle/__init__.py +12 -0
- will/lifecycle/integration_runner.py +54 -0
- will/maintenance/metadata_scribe_service.py +64 -0
- will/orchestration/__init__.py +4 -0
- will/orchestration/cognitive_service.py +185 -0
- will/orchestration/decision_tracer.py +257 -0
- will/orchestration/intent_alignment.py +59 -0
- will/orchestration/intent_guard.py +20 -0
- will/orchestration/phase_registry.py +92 -0
- will/orchestration/process_orchestrator.py +270 -0
- will/orchestration/prompt_pipeline.py +174 -0
- will/orchestration/remediation_orchestrator.py +292 -0
- will/orchestration/self_correction_engine.py +154 -0
- will/orchestration/validation_pipeline.py +45 -0
- will/orchestration/workflow_orchestrator.py +277 -0
- will/phases/__init__.py +24 -0
- will/phases/audit_phase.py +152 -0
- will/phases/canary/pytest_runner.py +156 -0
- will/phases/canary/result_builder.py +130 -0
- will/phases/canary/test_discovery.py +104 -0
- will/phases/canary_validation_phase.py +188 -0
- will/phases/code_generation/artifact_saver.py +175 -0
- will/phases/code_generation/code_sensor.py +117 -0
- will/phases/code_generation/file_path_extractor.py +53 -0
- will/phases/code_generation/work_directory_manager.py +83 -0
- will/phases/code_generation_phase.py +480 -0
- will/phases/execution_phase.py +179 -0
- will/phases/interpret_phase.py +266 -0
- will/phases/load_phase.py +102 -0
- will/phases/parse_phase.py +117 -0
- will/phases/planning_phase.py +182 -0
- will/phases/runtime_phase.py +112 -0
- will/phases/sandbox_validation_phase.py +130 -0
- will/phases/style_check_phase.py +209 -0
- will/phases/test_generation_phase.py +159 -0
- will/self_healing/alignment/persistence.py +53 -0
- will/self_healing/alignment/sandbox.py +51 -0
- will/self_healing/alignment/specialists.py +165 -0
- will/self_healing/alignment_orchestrator.py +140 -0
- will/self_healing/audit_remediation_service.py +199 -0
- will/self_healing/batch_remediation_service.py +280 -0
- will/self_healing/capability_reconciliation_service.py +96 -0
- will/self_healing/capability_tagging_service.py +224 -0
- will/self_healing/clarity_service.py +204 -0
- will/self_healing/complexity_service.py +260 -0
- will/self_healing/context_aware_test_generator.py +298 -0
- will/self_healing/coverage_remediation_service.py +97 -0
- will/self_healing/coverage_watcher.py +192 -0
- will/self_healing/enrichment_service.py +211 -0
- will/self_healing/linelength_service.py +168 -0
- will/self_healing/modularity_remediation_service.py +203 -0
- will/self_healing/remediation_evidence_writer.py +144 -0
- will/self_healing/remediation_executor.py +113 -0
- will/self_healing/remediation_interpretation/__init__.py +1 -0
- will/self_healing/remediation_interpretation/file_context_assembler.py +383 -0
- will/self_healing/remediation_interpretation/file_role_detector.py +599 -0
- will/self_healing/remediation_interpretation/finding_normalizer.py +221 -0
- will/self_healing/remediation_interpretation/models.py +198 -0
- will/self_healing/remediation_interpretation/reasoning_brief_builder.py +235 -0
- will/self_healing/remediation_interpretation/responsibility_extractor.py +421 -0
- will/self_healing/remediation_interpretation/service.py +202 -0
- will/self_healing/remediation_interpretation/strategy_catalog.py +252 -0
- will/self_healing/remediation_interpretation/strategy_selector.py +395 -0
- will/self_healing/remediation_pattern_matcher.py +126 -0
- will/self_healing/simple_test_generator.py +252 -0
- will/self_healing/single_file_remediation.py +137 -0
- will/self_healing/test_generation/automatic_repair.py +377 -0
- will/self_healing/test_generation/code_extractor.py +238 -0
- will/self_healing/test_generation/context_builder.py +140 -0
- will/self_healing/test_generation/executor.py +64 -0
- will/self_healing/test_generation/failure_parser.py +37 -0
- will/self_healing/test_generation/generation_workflow.py +140 -0
- will/self_healing/test_generation/generator.py +283 -0
- will/self_healing/test_generation/llm_correction.py +160 -0
- will/self_healing/test_generation/repair_workflow.py +128 -0
- will/self_healing/test_generation/single_test_fixer.py +77 -0
- will/self_healing/test_generation/test_extractor.py +50 -0
- will/self_healing/test_generation/test_scorer.py +53 -0
- will/self_healing/test_generation/test_validator.py +64 -0
- will/self_healing/test_generator.py +12 -0
- will/strategists/__init__.py +46 -0
- will/strategists/base_strategist.py +29 -0
- will/strategists/clarity_strategist.py +55 -0
- will/strategists/complexity_strategist.py +55 -0
- will/strategists/fix_strategist.py +467 -0
- will/strategists/sync_strategist.py +369 -0
- will/strategists/test_strategist.py +140 -0
- will/strategists/validation_strategist.py +315 -0
- will/test_generation/__init__.py +46 -0
- will/test_generation/adaptive_test_generator.py +123 -0
- will/test_generation/artifacts.py +102 -0
- will/test_generation/harness_detection.py +103 -0
- will/test_generation/helpers/__init__.py +14 -0
- will/test_generation/helpers/context_extractor.py +100 -0
- will/test_generation/helpers/test_executor.py +230 -0
- will/test_generation/llm_output.py +62 -0
- will/test_generation/models.py +25 -0
- will/test_generation/persistence.py +248 -0
- will/test_generation/phases/__init__.py +16 -0
- will/test_generation/phases/generation_phase.py +150 -0
- will/test_generation/phases/load_phase.py +53 -0
- will/test_generation/phases/parse_phase.py +50 -0
- will/test_generation/prompt_engine.py +123 -0
- will/test_generation/result_aggregator.py +73 -0
- will/test_generation/sandbox.py +203 -0
- will/test_generation/strategy_link.py +56 -0
- will/test_generation/test_extractor.py +140 -0
- will/test_generation/validation.py +89 -0
- will/tools/__init__.py +13 -0
- will/tools/anchor_builder.py +111 -0
- will/tools/anchor_search.py +73 -0
- will/tools/anchors/discovery.py +55 -0
- will/tools/anchors/storage.py +32 -0
- will/tools/architectural_context_builder.py +94 -0
- will/tools/cognitive_toolbox.py +47 -0
- will/tools/context/code_snippet_extractor.py +83 -0
- will/tools/context/embedding_search.py +76 -0
- will/tools/context/formatter.py +87 -0
- will/tools/context/models.py +38 -0
- will/tools/context/query_builder.py +42 -0
- will/tools/context/retriever.py +182 -0
- will/tools/context/standards.py +53 -0
- will/tools/file_navigator.py +180 -0
- will/tools/layers.py +31 -0
- will/tools/module_anchor_generator.py +137 -0
- will/tools/module_descriptor.py +154 -0
- will/tools/policy_vectorizer.py +184 -0
- will/tools/symbol_finder.py +188 -0
- will/tools/tool_generator.py +103 -0
- will/workers/audit_ingest_worker.py +207 -0
- will/workers/audit_violation_filter.py +108 -0
- will/workers/audit_violation_normalizer.py +108 -0
- will/workers/audit_violation_sensor.py +370 -0
- will/workers/blackboard_shop_manager.py +280 -0
- will/workers/capability_tagger.py +153 -0
- will/workers/circuit_breaker.py +335 -0
- will/workers/coherence_sensor.py +212 -0
- will/workers/commit_reachability_auditor.py +135 -0
- will/workers/db_sync_worker.py +96 -0
- will/workers/governance_embedding/__init__.py +9 -0
- will/workers/governance_embedding/governance_embedder_worker.py +189 -0
- will/workers/intent_inspector.py +599 -0
- will/workers/observer_worker.py +158 -0
- will/workers/prompt_extractor_worker.py +241 -0
- will/workers/proposal_consumer_effects.py +216 -0
- will/workers/proposal_consumer_revival.py +131 -0
- will/workers/proposal_consumer_worker.py +271 -0
- will/workers/proposal_pipeline_shop_manager.py +273 -0
- will/workers/repo_crawler.py +171 -0
- will/workers/repo_embedding/__init__.py +18 -0
- will/workers/repo_embedding/helpers.py +245 -0
- will/workers/repo_embedding/repo_embedder_workers.py +163 -0
- will/workers/test_coverage_sensor.py +208 -0
- will/workers/test_remediator/__init__.py +12 -0
- will/workers/test_remediator/_operations.py +295 -0
- will/workers/test_remediator/worker.py +187 -0
- will/workers/test_runner_sensor.py +430 -0
- will/workers/violation_executor.py +496 -0
- will/workers/violation_remediator.py +394 -0
- will/workers/violation_remediator_blackboard.py +225 -0
- will/workers/violation_remediator_body/__init__.py +12 -0
- will/workers/violation_remediator_body/blackboard.py +139 -0
- will/workers/violation_remediator_body/ceremony.py +154 -0
- will/workers/violation_remediator_body/context.py +70 -0
- will/workers/violation_remediator_body/llm.py +112 -0
- will/workers/violation_remediator_body/models.py +35 -0
- will/workers/violation_remediator_body/worker.py +518 -0
- will/workers/violation_remediator_proposal.py +328 -0
- will/workers/worker_shop_manager.py +244 -0
- will/workflows/__init__.py +23 -0
- will/workflows/dev_sync_reporter.py +274 -0
- will/workflows/dev_sync_workflow.py +118 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# src/mind/logic/engines/ast_gate/base.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Shared AST analysis utilities for constitutional enforcement.
|
|
5
|
+
|
|
6
|
+
Provides common helpers for traversing and analyzing Python AST nodes.
|
|
7
|
+
CONSTITUTIONAL FIX (V2.3.0):
|
|
8
|
+
- Added 'extract_domain_from_path' to centralize architectural layout knowledge.
|
|
9
|
+
- Added 'domain_matches' to support trust-zone based enforcement.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import ast
|
|
15
|
+
from collections.abc import Iterable
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ID: f75299d7-84aa-4254-8a2d-0e17da174d45
|
|
20
|
+
class ASTHelpers:
|
|
21
|
+
"""
|
|
22
|
+
Reusable AST traversal and analysis utilities.
|
|
23
|
+
|
|
24
|
+
Used by all AST check implementations to avoid duplication.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
@staticmethod
|
|
28
|
+
# ID: b338ca12-adb5-482c-8399-a691192ee7ae
|
|
29
|
+
def lineno(node: ast.AST) -> int:
|
|
30
|
+
"""Extract line number from AST node."""
|
|
31
|
+
return int(getattr(node, "lineno", 0) or 0)
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
# ID: 533311f7-6f83-4660-a3b7-1db18d2a60ce
|
|
35
|
+
def full_attr_name(node: ast.AST) -> str | None:
|
|
36
|
+
"""
|
|
37
|
+
Resolve dotted name from ast.Name / ast.Attribute chains.
|
|
38
|
+
|
|
39
|
+
Examples:
|
|
40
|
+
asyncio.run -> "asyncio.run"
|
|
41
|
+
loop.create_task -> "loop.create_task"
|
|
42
|
+
create_async_engine -> "create_async_engine"
|
|
43
|
+
"""
|
|
44
|
+
if isinstance(node, ast.Name):
|
|
45
|
+
return node.id
|
|
46
|
+
if isinstance(node, ast.Attribute):
|
|
47
|
+
left = ASTHelpers.full_attr_name(node.value)
|
|
48
|
+
if left:
|
|
49
|
+
return f"{left}.{node.attr}"
|
|
50
|
+
return node.attr
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
# ID: b86381d2-3020-4866-b5d0-265950020b84
|
|
55
|
+
def build_import_alias_map(tree: ast.AST) -> dict[str, str]:
|
|
56
|
+
"""Map local names to their qualified imported names.
|
|
57
|
+
|
|
58
|
+
Walks ImportFrom and Import statements anywhere in the tree and
|
|
59
|
+
records the translation a caller needs to recover the fully
|
|
60
|
+
qualified form of a Name- or Attribute-rooted call:
|
|
61
|
+
|
|
62
|
+
from os import replace -> {"replace": "os.replace"}
|
|
63
|
+
from os import replace as r -> {"r": "os.replace"}
|
|
64
|
+
import os -> {"os": "os"}
|
|
65
|
+
import os.path as op -> {"op": "os.path"}
|
|
66
|
+
|
|
67
|
+
Function-local imports are included by design: governance-grade
|
|
68
|
+
detection prefers conservative over-inclusion to silent
|
|
69
|
+
bypass via `def f(): from os import replace`. False positives
|
|
70
|
+
from local shadowing are an accepted trade.
|
|
71
|
+
|
|
72
|
+
Out of scope (per #488):
|
|
73
|
+
- Star imports (`from os import *`) — explicit policy is no.
|
|
74
|
+
- Relative imports (`from . import x`) — `node.level > 0` skipped.
|
|
75
|
+
- Dynamic / `__import__` / `importlib` patterns.
|
|
76
|
+
"""
|
|
77
|
+
alias_map: dict[str, str] = {}
|
|
78
|
+
for node in ast.walk(tree):
|
|
79
|
+
if isinstance(node, ast.ImportFrom):
|
|
80
|
+
if not node.module or node.level > 0:
|
|
81
|
+
continue
|
|
82
|
+
for alias in node.names:
|
|
83
|
+
if alias.name == "*":
|
|
84
|
+
continue
|
|
85
|
+
local = alias.asname or alias.name
|
|
86
|
+
alias_map[local] = f"{node.module}.{alias.name}"
|
|
87
|
+
elif isinstance(node, ast.Import):
|
|
88
|
+
for alias in node.names:
|
|
89
|
+
if alias.asname:
|
|
90
|
+
# `import os.path as op` -> {"op": "os.path"}
|
|
91
|
+
alias_map[alias.asname] = alias.name
|
|
92
|
+
else:
|
|
93
|
+
# `import os` -> {"os": "os"}
|
|
94
|
+
# `import os.path` binds the leftmost name "os";
|
|
95
|
+
# callers still write `os.path.exists(...)`, which
|
|
96
|
+
# full_attr_name already resolves correctly.
|
|
97
|
+
head = alias.name.split(".", 1)[0]
|
|
98
|
+
alias_map[head] = head
|
|
99
|
+
return alias_map
|
|
100
|
+
|
|
101
|
+
@staticmethod
|
|
102
|
+
# ID: a24dd4d6-a617-4197-a65e-d1257c691d38
|
|
103
|
+
def resolve_qualified_name(node: ast.AST, alias_map: dict[str, str]) -> str | None:
|
|
104
|
+
"""Resolve a Name/Attribute chain to its qualified form via aliases.
|
|
105
|
+
|
|
106
|
+
Computes `full_attr_name(node)` and, if the leftmost segment is in
|
|
107
|
+
the alias map, replaces it with the imported qualified form:
|
|
108
|
+
|
|
109
|
+
r + {"r": "os.replace"} -> "os.replace"
|
|
110
|
+
path.exists + {"path": "os.path"} -> "os.path.exists"
|
|
111
|
+
os.replace + {"os": "os"} -> "os.replace"
|
|
112
|
+
unrelated.thing + {} -> "unrelated.thing"
|
|
113
|
+
|
|
114
|
+
Returns None when the node is neither a Name nor an Attribute
|
|
115
|
+
chain (e.g., Call().method() — the receiver is a Call, not a
|
|
116
|
+
resolvable dotted name).
|
|
117
|
+
"""
|
|
118
|
+
name = ASTHelpers.full_attr_name(node)
|
|
119
|
+
if not name:
|
|
120
|
+
return None
|
|
121
|
+
head, _, tail = name.partition(".")
|
|
122
|
+
if head in alias_map:
|
|
123
|
+
resolved = alias_map[head]
|
|
124
|
+
return f"{resolved}.{tail}" if tail else resolved
|
|
125
|
+
return name
|
|
126
|
+
|
|
127
|
+
@staticmethod
|
|
128
|
+
# ID: e5fec108-e53c-4611-9ccb-1b17f9d3523b
|
|
129
|
+
def matches_call(call_name: str, disallowed: list[str]) -> bool:
|
|
130
|
+
"""
|
|
131
|
+
Match call name against disallowed patterns.
|
|
132
|
+
|
|
133
|
+
Strategies:
|
|
134
|
+
- Exact match on fully qualified name (e.g., "asyncio.run" == "asyncio.run")
|
|
135
|
+
- Suffix match with dot (e.g., "foo.asyncio.run" matches "asyncio.run")
|
|
136
|
+
|
|
137
|
+
DOES NOT match bare leaf names to prevent false positives.
|
|
138
|
+
Example: "subprocess.run" will NOT match "asyncio.run"
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
call_name: Fully qualified call name from AST (e.g., "asyncio.run")
|
|
142
|
+
disallowed: List of forbidden call patterns (e.g., ["asyncio.run"])
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
True if call_name matches any disallowed pattern
|
|
146
|
+
"""
|
|
147
|
+
for pattern in disallowed:
|
|
148
|
+
# Strategy 1: Exact match
|
|
149
|
+
if call_name == pattern:
|
|
150
|
+
return True
|
|
151
|
+
|
|
152
|
+
# Strategy 2: Suffix match (handles nested imports)
|
|
153
|
+
if "." in pattern:
|
|
154
|
+
# Only match if it's a proper suffix with a dot boundary
|
|
155
|
+
if call_name.endswith(f".{pattern}") or call_name.endswith(pattern):
|
|
156
|
+
call_parts = call_name.split(".")
|
|
157
|
+
pattern_parts = pattern.split(".")
|
|
158
|
+
|
|
159
|
+
if len(call_parts) >= len(pattern_parts):
|
|
160
|
+
# Check if the rightmost N parts match
|
|
161
|
+
if call_parts[-len(pattern_parts) :] == pattern_parts:
|
|
162
|
+
return True
|
|
163
|
+
|
|
164
|
+
return False
|
|
165
|
+
|
|
166
|
+
@staticmethod
|
|
167
|
+
# ID: 9e091307-b265-4f46-8a62-e6b4ac1681eb
|
|
168
|
+
def iter_module_level_stmts(tree: ast.AST) -> Iterable[ast.stmt]:
|
|
169
|
+
"""Iterate over module-level statements."""
|
|
170
|
+
if isinstance(tree, ast.Module):
|
|
171
|
+
return tree.body
|
|
172
|
+
return []
|
|
173
|
+
|
|
174
|
+
@staticmethod
|
|
175
|
+
# ID: 10e7f915-2059-4010-afe6-6be56b2084fb
|
|
176
|
+
def walk_module_stmt_without_nested_scopes(stmt: ast.stmt) -> Iterable[ast.AST]:
|
|
177
|
+
"""
|
|
178
|
+
Walk statement but don't descend into nested scopes.
|
|
179
|
+
|
|
180
|
+
Skips: function defs, class defs, lambdas
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
def _walk(node: ast.AST) -> Iterable[ast.AST]:
|
|
184
|
+
yield node
|
|
185
|
+
for child in ast.iter_child_nodes(node):
|
|
186
|
+
if isinstance(
|
|
187
|
+
child,
|
|
188
|
+
(ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef, ast.Lambda),
|
|
189
|
+
):
|
|
190
|
+
continue
|
|
191
|
+
yield from _walk(child)
|
|
192
|
+
|
|
193
|
+
return _walk(stmt)
|
|
194
|
+
|
|
195
|
+
# -------------------------------------------------------------------------
|
|
196
|
+
# NEW ARCHITECTURAL HELPERS (Constitutional Mapping Logic)
|
|
197
|
+
# -------------------------------------------------------------------------
|
|
198
|
+
|
|
199
|
+
@staticmethod
|
|
200
|
+
# ID: e4d3c2b1-a0f9-8e7d-6c5b-4a3f2e1d0c9b
|
|
201
|
+
def extract_domain_from_path(file_path: Path | str) -> str:
|
|
202
|
+
"""
|
|
203
|
+
Extract domain from file path following CORE's domain convention.
|
|
204
|
+
|
|
205
|
+
Example: 'src/mind/governance/auditor.py' -> 'mind.governance'
|
|
206
|
+
"""
|
|
207
|
+
path_str = str(file_path).replace("\\", "/")
|
|
208
|
+
|
|
209
|
+
if "/src/" in path_str:
|
|
210
|
+
path_str = path_str.split("/src/", 1)[1]
|
|
211
|
+
elif path_str.startswith("src/"):
|
|
212
|
+
path_str = path_str[4:]
|
|
213
|
+
|
|
214
|
+
parts = path_str.split("/")
|
|
215
|
+
domain_parts = [p for p in parts[:-1] if p]
|
|
216
|
+
|
|
217
|
+
return ".".join(domain_parts) if domain_parts else ""
|
|
218
|
+
|
|
219
|
+
@staticmethod
|
|
220
|
+
# ID: f3e2d1c0-b9a8-7f6e-5d4c-3b2a1f0e9d8c
|
|
221
|
+
def domain_matches(file_domain: str, allowed_domains: list[str]) -> bool:
|
|
222
|
+
"""
|
|
223
|
+
Check if file domain matches any allowed domain (exact or prefix).
|
|
224
|
+
"""
|
|
225
|
+
if not file_domain or not allowed_domains:
|
|
226
|
+
return False
|
|
227
|
+
|
|
228
|
+
for allowed in allowed_domains:
|
|
229
|
+
if file_domain == allowed or file_domain.startswith(f"{allowed}."):
|
|
230
|
+
return True
|
|
231
|
+
|
|
232
|
+
return False
|
|
233
|
+
|
|
234
|
+
@staticmethod
|
|
235
|
+
# ID: 337aed3b-dc01-4b17-bbe3-e8498e1dee13
|
|
236
|
+
def is_type_checking_condition(test_node: ast.expr) -> bool:
|
|
237
|
+
"""
|
|
238
|
+
Check if an If condition is checking TYPE_CHECKING.
|
|
239
|
+
|
|
240
|
+
Matches:
|
|
241
|
+
- TYPE_CHECKING
|
|
242
|
+
- typing.TYPE_CHECKING
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
test_node: The test expression from an ast.If node
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
True if the condition checks TYPE_CHECKING
|
|
249
|
+
|
|
250
|
+
Examples:
|
|
251
|
+
>>> # Matches: if TYPE_CHECKING:
|
|
252
|
+
>>> # Matches: if typing.TYPE_CHECKING:
|
|
253
|
+
"""
|
|
254
|
+
if isinstance(test_node, ast.Name):
|
|
255
|
+
return test_node.id == "TYPE_CHECKING"
|
|
256
|
+
|
|
257
|
+
if isinstance(test_node, ast.Attribute):
|
|
258
|
+
# Handle typing.TYPE_CHECKING
|
|
259
|
+
if test_node.attr == "TYPE_CHECKING":
|
|
260
|
+
if isinstance(test_node.value, ast.Name):
|
|
261
|
+
return test_node.value.id == "typing"
|
|
262
|
+
|
|
263
|
+
return False
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# src/mind/logic/engines/ast_gate/checks/__init__.py
|
|
2
|
+
|
|
3
|
+
"""Provides functionality for the __init__ module."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from .async_checks import AsyncChecks
|
|
8
|
+
from .capability_checks import CapabilityChecks
|
|
9
|
+
from .conservation_checks import ConservationChecks
|
|
10
|
+
from .generic_checks import GenericASTChecks
|
|
11
|
+
from .import_checks import ImportChecks
|
|
12
|
+
from .logging_checks import LoggingChecks
|
|
13
|
+
from .metadata_checks import normalize_ast, verify_metadata_only_diff
|
|
14
|
+
from .naming_checks import NamingChecks
|
|
15
|
+
from .prompt_model_checks import PromptModelChecks
|
|
16
|
+
from .protected_namespace_access_check import ProtectedNamespaceAccessCheck
|
|
17
|
+
from .purity_checks import PurityChecks
|
|
18
|
+
from .schema_conformance_checks import SchemaConformanceChecks
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"AsyncChecks",
|
|
23
|
+
"CapabilityChecks",
|
|
24
|
+
"ConservationChecks",
|
|
25
|
+
"GenericASTChecks",
|
|
26
|
+
"ImportChecks",
|
|
27
|
+
"LoggingChecks",
|
|
28
|
+
"NamingChecks",
|
|
29
|
+
"PromptModelChecks",
|
|
30
|
+
"ProtectedNamespaceAccessCheck",
|
|
31
|
+
"PurityChecks",
|
|
32
|
+
"SchemaConformanceChecks",
|
|
33
|
+
"normalize_ast",
|
|
34
|
+
"verify_metadata_only_diff",
|
|
35
|
+
]
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# src/mind/logic/engines/ast_gate/checks/async_checks.py
|
|
2
|
+
"""Async safety checks for constitutional enforcement."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import ast
|
|
7
|
+
|
|
8
|
+
from mind.logic.engines.ast_gate.base import ASTHelpers
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# ID: a6facc5a-b9b3-45fd-9ae9-414ca0976c6c
|
|
12
|
+
class AsyncChecks:
|
|
13
|
+
"""Async safety and event loop management checks."""
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
# ID: 965336f9-45fd-4c4e-b063-1cba88974b3c
|
|
17
|
+
def check_restricted_event_loop_creation(
|
|
18
|
+
tree: ast.AST, forbidden_calls: list[str]
|
|
19
|
+
) -> list[str]:
|
|
20
|
+
"""
|
|
21
|
+
Forbid dangerous event loop hijacking.
|
|
22
|
+
|
|
23
|
+
ALLOWS (defensive patterns):
|
|
24
|
+
- asyncio.get_event_loop() for checking state (not followed by .run_until_complete())
|
|
25
|
+
- asyncio.run() when guarded by loop existence check
|
|
26
|
+
|
|
27
|
+
FORBIDS (dangerous patterns):
|
|
28
|
+
- asyncio.run() without checking for existing loop first
|
|
29
|
+
- loop.run_until_complete() (manual loop hijacking)
|
|
30
|
+
- asyncio.new_event_loop() (manual loop creation)
|
|
31
|
+
"""
|
|
32
|
+
if not forbidden_calls:
|
|
33
|
+
return []
|
|
34
|
+
|
|
35
|
+
findings: list[str] = []
|
|
36
|
+
|
|
37
|
+
# Build parent map for context analysis
|
|
38
|
+
parent_map = {}
|
|
39
|
+
for parent in ast.walk(tree):
|
|
40
|
+
for child in ast.iter_child_nodes(parent):
|
|
41
|
+
parent_map[child] = parent
|
|
42
|
+
|
|
43
|
+
for node in ast.walk(tree):
|
|
44
|
+
if not isinstance(node, ast.Call):
|
|
45
|
+
continue
|
|
46
|
+
fn = ASTHelpers.full_attr_name(node.func)
|
|
47
|
+
if not fn:
|
|
48
|
+
continue
|
|
49
|
+
|
|
50
|
+
# 1. CHECK: loop.run_until_complete() - ALWAYS DANGEROUS
|
|
51
|
+
if fn.endswith(".run_until_complete"):
|
|
52
|
+
findings.append(
|
|
53
|
+
f"Line {ASTHelpers.lineno(node)}: Forbidden manual loop hijacking '{fn}()'"
|
|
54
|
+
)
|
|
55
|
+
continue
|
|
56
|
+
|
|
57
|
+
# 2. CHECK: asyncio.get_event_loop() - only dangerous if used for run_until_complete
|
|
58
|
+
if ASTHelpers.matches_call(fn, ["asyncio.get_event_loop"]):
|
|
59
|
+
# Check what they do with the loop
|
|
60
|
+
if AsyncChecks._is_loop_hijacking(node, parent_map):
|
|
61
|
+
findings.append(
|
|
62
|
+
f"Line {ASTHelpers.lineno(node)}: Forbidden event-loop hijacking via get_event_loop().run_until_complete()"
|
|
63
|
+
)
|
|
64
|
+
# Otherwise it's just checking - SAFE (defensive pattern)
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
# 3. CHECK: asyncio.run() - only dangerous if NOT guarded
|
|
68
|
+
if ASTHelpers.matches_call(fn, ["asyncio.run"]):
|
|
69
|
+
# Check if this is in a defensive pattern
|
|
70
|
+
if not AsyncChecks._is_defensively_guarded(node, tree, parent_map):
|
|
71
|
+
findings.append(
|
|
72
|
+
f"Line {ASTHelpers.lineno(node)}: Forbidden asyncio.run() without defensive loop check"
|
|
73
|
+
)
|
|
74
|
+
# Otherwise it's guarded - SAFE (defensive pattern)
|
|
75
|
+
continue
|
|
76
|
+
|
|
77
|
+
# 4. CHECK: Other forbidden calls (asyncio.new_event_loop, etc.)
|
|
78
|
+
if ASTHelpers.matches_call(fn, forbidden_calls):
|
|
79
|
+
# These are always dangerous
|
|
80
|
+
if fn not in [
|
|
81
|
+
"asyncio.get_event_loop",
|
|
82
|
+
"asyncio.run",
|
|
83
|
+
]: # Already handled above
|
|
84
|
+
findings.append(
|
|
85
|
+
f"Line {ASTHelpers.lineno(node)}: Forbidden event-loop call '{fn}()'"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
return findings
|
|
89
|
+
|
|
90
|
+
@staticmethod
|
|
91
|
+
def _is_loop_hijacking(get_event_loop_call: ast.Call, parent_map: dict) -> bool:
|
|
92
|
+
"""
|
|
93
|
+
Check if asyncio.get_event_loop() is followed by .run_until_complete().
|
|
94
|
+
|
|
95
|
+
Pattern we're detecting:
|
|
96
|
+
loop = asyncio.get_event_loop()
|
|
97
|
+
loop.run_until_complete(...) # DANGEROUS
|
|
98
|
+
"""
|
|
99
|
+
# Get the parent assignment or expression
|
|
100
|
+
parent = parent_map.get(get_event_loop_call)
|
|
101
|
+
|
|
102
|
+
# Check if assigned to a variable
|
|
103
|
+
if isinstance(parent, ast.Assign):
|
|
104
|
+
# Get the variable name
|
|
105
|
+
if parent.targets and isinstance(parent.targets[0], ast.Name):
|
|
106
|
+
loop_var = parent.targets[0].id
|
|
107
|
+
|
|
108
|
+
# Look for usage of this variable with .run_until_complete()
|
|
109
|
+
# We need to check the function/method body containing this assignment
|
|
110
|
+
function_node = AsyncChecks._find_containing_function(
|
|
111
|
+
parent, parent_map
|
|
112
|
+
)
|
|
113
|
+
if function_node:
|
|
114
|
+
for node in ast.walk(function_node):
|
|
115
|
+
if isinstance(node, ast.Call):
|
|
116
|
+
if isinstance(node.func, ast.Attribute):
|
|
117
|
+
if (
|
|
118
|
+
node.func.attr
|
|
119
|
+
in ["run_until_complete", "run_forever"]
|
|
120
|
+
and isinstance(node.func.value, ast.Name)
|
|
121
|
+
and node.func.value.id == loop_var
|
|
122
|
+
):
|
|
123
|
+
return True
|
|
124
|
+
|
|
125
|
+
# Check for direct chaining: asyncio.get_event_loop().run_until_complete(...)
|
|
126
|
+
if isinstance(parent, ast.Attribute):
|
|
127
|
+
if parent.attr in ["run_until_complete", "run_forever"]:
|
|
128
|
+
return True
|
|
129
|
+
|
|
130
|
+
return False
|
|
131
|
+
|
|
132
|
+
@staticmethod
|
|
133
|
+
def _is_defensively_guarded(
|
|
134
|
+
asyncio_run_call: ast.Call, tree: ast.AST, parent_map: dict
|
|
135
|
+
) -> bool:
|
|
136
|
+
"""
|
|
137
|
+
Check if asyncio.run() is guarded by a check for existing event loop.
|
|
138
|
+
|
|
139
|
+
Defensive pattern we're allowing:
|
|
140
|
+
try:
|
|
141
|
+
loop = asyncio.get_running_loop()
|
|
142
|
+
except RuntimeError:
|
|
143
|
+
loop = None
|
|
144
|
+
|
|
145
|
+
if loop and loop.is_running():
|
|
146
|
+
# handle async context
|
|
147
|
+
else:
|
|
148
|
+
asyncio.run(...) # SAFE - guarded
|
|
149
|
+
"""
|
|
150
|
+
# Find the function containing this asyncio.run() call
|
|
151
|
+
function_node = AsyncChecks._find_containing_function(
|
|
152
|
+
asyncio_run_call, parent_map
|
|
153
|
+
)
|
|
154
|
+
if not function_node:
|
|
155
|
+
# Top-level or script - always unguarded
|
|
156
|
+
return False
|
|
157
|
+
|
|
158
|
+
# Look for defensive patterns in the function:
|
|
159
|
+
# 1. try/except with get_running_loop
|
|
160
|
+
# 2. if statement checking loop.is_running()
|
|
161
|
+
|
|
162
|
+
has_get_running_loop = False
|
|
163
|
+
has_is_running_check = False
|
|
164
|
+
|
|
165
|
+
for node in ast.walk(function_node):
|
|
166
|
+
# Check for asyncio.get_running_loop() call
|
|
167
|
+
if isinstance(node, ast.Call):
|
|
168
|
+
fn = ASTHelpers.full_attr_name(node.func)
|
|
169
|
+
if fn == "asyncio.get_running_loop":
|
|
170
|
+
has_get_running_loop = True
|
|
171
|
+
|
|
172
|
+
# Check for .is_running() check
|
|
173
|
+
if isinstance(node, ast.Attribute):
|
|
174
|
+
if node.attr == "is_running":
|
|
175
|
+
has_is_running_check = True
|
|
176
|
+
|
|
177
|
+
# If both defensive checks are present, it's guarded
|
|
178
|
+
return has_get_running_loop and has_is_running_check
|
|
179
|
+
|
|
180
|
+
@staticmethod
|
|
181
|
+
def _find_containing_function(
|
|
182
|
+
node: ast.AST, parent_map: dict
|
|
183
|
+
) -> ast.FunctionDef | ast.AsyncFunctionDef | None:
|
|
184
|
+
"""Walk up the parent chain to find the containing function."""
|
|
185
|
+
current = node
|
|
186
|
+
while current in parent_map:
|
|
187
|
+
current = parent_map[current]
|
|
188
|
+
if isinstance(current, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
189
|
+
return current
|
|
190
|
+
return None
|
|
191
|
+
|
|
192
|
+
@staticmethod
|
|
193
|
+
# ID: b6ae62b2-abe5-404a-a607-40095adb556e
|
|
194
|
+
def check_no_import_time_async_singletons(
|
|
195
|
+
tree: ast.AST, disallowed_calls: list[str]
|
|
196
|
+
) -> list[str]:
|
|
197
|
+
"""Forbid loop-bound async resource creation at module import time."""
|
|
198
|
+
if not disallowed_calls:
|
|
199
|
+
return []
|
|
200
|
+
|
|
201
|
+
findings: list[str] = []
|
|
202
|
+
for stmt in ASTHelpers.iter_module_level_stmts(tree):
|
|
203
|
+
for node in ASTHelpers.walk_module_stmt_without_nested_scopes(stmt):
|
|
204
|
+
if isinstance(node, ast.Call):
|
|
205
|
+
fn = ASTHelpers.full_attr_name(node.func)
|
|
206
|
+
if not fn:
|
|
207
|
+
continue
|
|
208
|
+
if ASTHelpers.matches_call(fn, disallowed_calls):
|
|
209
|
+
findings.append(
|
|
210
|
+
f"Line {ASTHelpers.lineno(node)}: Import-time async singleton creation: '{fn}()'"
|
|
211
|
+
)
|
|
212
|
+
return findings
|
|
213
|
+
|
|
214
|
+
@staticmethod
|
|
215
|
+
# ID: ad987b5e-75c6-4e39-a44f-e349acf5fae2
|
|
216
|
+
def check_no_module_level_async_engine(tree: ast.AST) -> list[str]:
|
|
217
|
+
"""Forbid module-level create_async_engine assignment."""
|
|
218
|
+
findings: list[str] = []
|
|
219
|
+
disallowed = [
|
|
220
|
+
"create_async_engine",
|
|
221
|
+
"sqlalchemy.ext.asyncio.create_async_engine",
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
for stmt in ASTHelpers.iter_module_level_stmts(tree):
|
|
225
|
+
value: ast.AST | None
|
|
226
|
+
if isinstance(stmt, ast.Assign):
|
|
227
|
+
value = stmt.value
|
|
228
|
+
elif isinstance(stmt, ast.AnnAssign):
|
|
229
|
+
value = stmt.value
|
|
230
|
+
else:
|
|
231
|
+
continue
|
|
232
|
+
|
|
233
|
+
if value is None or not isinstance(value, ast.Call):
|
|
234
|
+
continue
|
|
235
|
+
|
|
236
|
+
fn = ASTHelpers.full_attr_name(value.func)
|
|
237
|
+
if not fn:
|
|
238
|
+
continue
|
|
239
|
+
|
|
240
|
+
if ASTHelpers.matches_call(fn, disallowed):
|
|
241
|
+
line = ASTHelpers.lineno(value)
|
|
242
|
+
findings.append(
|
|
243
|
+
f"Line {line}: Module-level async engine creation is forbidden: '{fn}()'"
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
return findings
|
|
247
|
+
|
|
248
|
+
@staticmethod
|
|
249
|
+
# ID: 55f1eafc-a82d-4f56-90d8-fc40d7a6eb2e
|
|
250
|
+
def check_no_task_return_from_sync_cli(tree: ast.AST) -> list[str]:
|
|
251
|
+
"""Forbid returning asyncio Tasks/Futures from sync functions."""
|
|
252
|
+
findings: list[str] = []
|
|
253
|
+
|
|
254
|
+
for node in ast.walk(tree):
|
|
255
|
+
if not isinstance(node, ast.FunctionDef):
|
|
256
|
+
continue
|
|
257
|
+
|
|
258
|
+
for inner in ast.walk(node):
|
|
259
|
+
if not isinstance(inner, ast.Return):
|
|
260
|
+
continue
|
|
261
|
+
if inner.value is None:
|
|
262
|
+
continue
|
|
263
|
+
|
|
264
|
+
if isinstance(inner.value, ast.Call):
|
|
265
|
+
fn = ASTHelpers.full_attr_name(inner.value.func) or ""
|
|
266
|
+
leaf = fn.split(".")[-1]
|
|
267
|
+
if leaf == "create_task":
|
|
268
|
+
findings.append(
|
|
269
|
+
f"Line {ASTHelpers.lineno(inner)}: Sync function '{node.name}' returns Task"
|
|
270
|
+
)
|
|
271
|
+
elif leaf == "ensure_future":
|
|
272
|
+
findings.append(
|
|
273
|
+
f"Line {ASTHelpers.lineno(inner)}: Sync function '{node.name}' returns Future"
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
return findings
|