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,118 @@
|
|
|
1
|
+
# src/body/self_healing/test_target_analyzer.py
|
|
2
|
+
"""
|
|
3
|
+
Analyzes Python source files to identify and classify functions as test targets.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import ast
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Literal
|
|
12
|
+
|
|
13
|
+
from radon.visitors import ComplexityVisitor
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Classification = Literal["SIMPLE", "COMPLEX"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
# ID: 4be9923d-aa4d-4fc6-83ff-1bc1c1918f09
|
|
21
|
+
class TestTarget:
|
|
22
|
+
"""Represents a potential function to be tested."""
|
|
23
|
+
|
|
24
|
+
__test__ = False
|
|
25
|
+
|
|
26
|
+
name: str
|
|
27
|
+
complexity: int
|
|
28
|
+
classification: Classification
|
|
29
|
+
reason: str
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# ID: e1e93bfa-852d-4673-85e3-ffc827419c8c
|
|
33
|
+
class TestTargetAnalyzer:
|
|
34
|
+
"""Analyzes a Python file and classifies its functions for testability."""
|
|
35
|
+
|
|
36
|
+
__test__ = False
|
|
37
|
+
|
|
38
|
+
def __init__(self, complexity_threshold: int = 5):
|
|
39
|
+
self.complexity_threshold = complexity_threshold
|
|
40
|
+
self.complex_arg_types = {"CoreContext", "AsyncSession"}
|
|
41
|
+
self.io_imports = {"httpx", "sqlalchemy", "get_session"}
|
|
42
|
+
|
|
43
|
+
# ID: f268fe3a-a735-46bc-8438-b0197dcbca8f
|
|
44
|
+
def analyze_file(self, file_path: Path) -> list[TestTarget]:
|
|
45
|
+
"""
|
|
46
|
+
Analyzes a single Python file and returns a list of classified test targets.
|
|
47
|
+
"""
|
|
48
|
+
try:
|
|
49
|
+
content = file_path.read_text("utf-8")
|
|
50
|
+
tree = ast.parse(content)
|
|
51
|
+
complexity_visitor = ComplexityVisitor.from_code(content)
|
|
52
|
+
except Exception:
|
|
53
|
+
return []
|
|
54
|
+
|
|
55
|
+
imports = self._get_imports(tree)
|
|
56
|
+
targets = []
|
|
57
|
+
|
|
58
|
+
for func in complexity_visitor.functions:
|
|
59
|
+
is_public = not func.name.startswith("_")
|
|
60
|
+
if not is_public:
|
|
61
|
+
continue
|
|
62
|
+
|
|
63
|
+
node = self._find_func_node(tree, func.name)
|
|
64
|
+
if not node:
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
classification, reason = self._classify_function(func, node, imports)
|
|
68
|
+
targets.append(
|
|
69
|
+
TestTarget(
|
|
70
|
+
name=func.name,
|
|
71
|
+
complexity=func.complexity,
|
|
72
|
+
classification=classification,
|
|
73
|
+
reason=reason,
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
return sorted(targets, key=lambda t: t.complexity)
|
|
78
|
+
|
|
79
|
+
def _get_imports(self, tree: ast.AST) -> set[str]:
|
|
80
|
+
"""Extracts top-level import names from an AST."""
|
|
81
|
+
imports = set()
|
|
82
|
+
for node in ast.walk(tree):
|
|
83
|
+
if isinstance(node, ast.Import):
|
|
84
|
+
for alias in node.names:
|
|
85
|
+
imports.add(alias.name.split(".")[0])
|
|
86
|
+
elif isinstance(node, ast.ImportFrom) and node.module:
|
|
87
|
+
imports.add(node.module.split(".")[0])
|
|
88
|
+
return imports
|
|
89
|
+
|
|
90
|
+
def _find_func_node(
|
|
91
|
+
self, tree: ast.AST, func_name: str
|
|
92
|
+
) -> ast.FunctionDef | ast.AsyncFunctionDef | None:
|
|
93
|
+
"""Finds the AST node for a function by name."""
|
|
94
|
+
for node in ast.walk(tree):
|
|
95
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
96
|
+
if node.name == func_name:
|
|
97
|
+
return node
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
def _classify_function(
|
|
101
|
+
self,
|
|
102
|
+
func_metrics,
|
|
103
|
+
node: ast.FunctionDef | ast.AsyncFunctionDef,
|
|
104
|
+
file_imports: set[str],
|
|
105
|
+
) -> tuple[Classification, str]:
|
|
106
|
+
"""Applies heuristics to classify a function as SIMPLE or COMPLEX."""
|
|
107
|
+
if func_metrics.complexity > self.complexity_threshold:
|
|
108
|
+
return "COMPLEX", f"High complexity ({func_metrics.complexity})"
|
|
109
|
+
|
|
110
|
+
for arg in node.args.args:
|
|
111
|
+
if arg.annotation and isinstance(arg.annotation, ast.Name):
|
|
112
|
+
if arg.annotation.id in self.complex_arg_types:
|
|
113
|
+
return "COMPLEX", f"Depends on complex type '{arg.annotation.id}'"
|
|
114
|
+
|
|
115
|
+
if self.io_imports.intersection(file_imports):
|
|
116
|
+
return "COMPLEX", "File involves I/O operations"
|
|
117
|
+
|
|
118
|
+
return "SIMPLE", "Low complexity, no complex dependencies"
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# src/body/self_healing/vulture_healer.py
|
|
2
|
+
"""Surgical cleanup of Vulture dead-code findings.
|
|
3
|
+
|
|
4
|
+
Uses local LLM intelligence to safely remove unused variables and functions
|
|
5
|
+
identified by the Vulture static analyser.
|
|
6
|
+
|
|
7
|
+
Relocated from src/will/self_healing/vulture_healer.py under ADR-055 D6
|
|
8
|
+
Stage B reopen #6: this module has no will/* dependencies (only
|
|
9
|
+
body/services/file_service + shared.*), so its previous will/ placement
|
|
10
|
+
was a layer misfit. Registration as fix.vulture_heal in
|
|
11
|
+
body/atomic/fix_actions.py expects this module to live under body/.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
from body.services.file_service import FileService
|
|
20
|
+
from shared.ai.prompt_model import PromptModel
|
|
21
|
+
from shared.logger import getLogger
|
|
22
|
+
from shared.path_resolver import PathResolver
|
|
23
|
+
from shared.utils.parsing import extract_python_code_from_response
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
logger = getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# ID: 515a5f31-deb3-41bc-9736-4e29e1989a0f
|
|
30
|
+
async def heal_dead_code(
|
|
31
|
+
context,
|
|
32
|
+
file_handler: FileService,
|
|
33
|
+
repo_root: Path,
|
|
34
|
+
write: bool = False,
|
|
35
|
+
) -> None:
|
|
36
|
+
"""Surgical cleanup of Vulture findings using local intelligence.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
context: CoreContext providing cognitive_service.
|
|
40
|
+
file_handler: Governed file mutation surface.
|
|
41
|
+
repo_root: Repository root path.
|
|
42
|
+
write: If False, dry-run only. If True, applies deletions.
|
|
43
|
+
"""
|
|
44
|
+
path_resolver = PathResolver(repo_root)
|
|
45
|
+
|
|
46
|
+
# Canonical path via PathResolver — never hardcoded.
|
|
47
|
+
evidence_path = path_resolver.audit_findings_path
|
|
48
|
+
|
|
49
|
+
if not evidence_path.exists():
|
|
50
|
+
logger.error(
|
|
51
|
+
"No audit evidence found at %s. Run 'core-admin check audit' first.",
|
|
52
|
+
evidence_path,
|
|
53
|
+
)
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
findings = json.loads(evidence_path.read_text(encoding="utf-8"))
|
|
58
|
+
except (json.JSONDecodeError, OSError) as e:
|
|
59
|
+
logger.error("Failed to read audit findings from %s: %s", evidence_path, e)
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
dead_code_targets = [
|
|
63
|
+
f for f in findings if f.get("check_id") == "workflow.dead_code_check"
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
if not dead_code_targets:
|
|
67
|
+
logger.info("No dead code findings in the ledger.")
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
# Ensure artifact directory exists via governed channel.
|
|
71
|
+
artifact_rel = "work/artifacts/healer"
|
|
72
|
+
file_handler.ensure_dir(artifact_rel)
|
|
73
|
+
|
|
74
|
+
logger.info(
|
|
75
|
+
"Found %d dead code targets — beginning surgical cleanup (write=%s)",
|
|
76
|
+
len(dead_code_targets),
|
|
77
|
+
write,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
cognitive_service = getattr(context, "cognitive_service", None)
|
|
81
|
+
if cognitive_service is None:
|
|
82
|
+
logger.error(
|
|
83
|
+
"cognitive_service unavailable on CoreContext — cannot perform LLM-assisted healing."
|
|
84
|
+
)
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
healed = 0
|
|
88
|
+
skipped = 0
|
|
89
|
+
errors = 0
|
|
90
|
+
|
|
91
|
+
for finding in dead_code_targets:
|
|
92
|
+
file_path_str = finding.get("file_path")
|
|
93
|
+
line_number = finding.get("line_number")
|
|
94
|
+
message = finding.get("message", "")
|
|
95
|
+
|
|
96
|
+
if not file_path_str or not file_path_str.endswith(".py"):
|
|
97
|
+
skipped += 1
|
|
98
|
+
continue
|
|
99
|
+
|
|
100
|
+
abs_path = repo_root / file_path_str
|
|
101
|
+
if not abs_path.exists():
|
|
102
|
+
logger.warning("Dead code target not found: %s — skipping", abs_path)
|
|
103
|
+
skipped += 1
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
source = abs_path.read_text(encoding="utf-8")
|
|
108
|
+
except OSError as e:
|
|
109
|
+
logger.error("Could not read %s: %s", abs_path, e)
|
|
110
|
+
errors += 1
|
|
111
|
+
continue
|
|
112
|
+
|
|
113
|
+
prompt_model = PromptModel(cognitive_service=cognitive_service)
|
|
114
|
+
prompt = (
|
|
115
|
+
f"You are a precise Python refactoring tool.\n\n"
|
|
116
|
+
f"The following finding was reported by Vulture (dead code detector):\n"
|
|
117
|
+
f" File: {file_path_str}\n"
|
|
118
|
+
f" Line: {line_number}\n"
|
|
119
|
+
f" Finding: {message}\n\n"
|
|
120
|
+
f"Remove the dead code item identified above from the source file below. "
|
|
121
|
+
f"Do not modify any other code. "
|
|
122
|
+
f"Return only the complete updated Python file, no explanation.\n\n"
|
|
123
|
+
f"```python\n{source}\n```"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
response = await prompt_model.complete(prompt)
|
|
128
|
+
updated_code = extract_python_code_from_response(response)
|
|
129
|
+
except Exception as e:
|
|
130
|
+
logger.error("LLM healing failed for %s: %s", file_path_str, e)
|
|
131
|
+
errors += 1
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
if not updated_code or updated_code.strip() == source.strip():
|
|
135
|
+
logger.info("No change produced for %s — skipping", file_path_str)
|
|
136
|
+
skipped += 1
|
|
137
|
+
continue
|
|
138
|
+
|
|
139
|
+
if write:
|
|
140
|
+
try:
|
|
141
|
+
file_handler.write_runtime_text(file_path_str, updated_code)
|
|
142
|
+
logger.info("Healed: %s (line %s)", file_path_str, line_number)
|
|
143
|
+
healed += 1
|
|
144
|
+
except Exception as e:
|
|
145
|
+
logger.error("FileHandler write failed for %s: %s", file_path_str, e)
|
|
146
|
+
errors += 1
|
|
147
|
+
else:
|
|
148
|
+
logger.info(
|
|
149
|
+
"[DRY RUN] Would remove dead code in %s (line %s)",
|
|
150
|
+
file_path_str,
|
|
151
|
+
line_number,
|
|
152
|
+
)
|
|
153
|
+
healed += 1
|
|
154
|
+
|
|
155
|
+
logger.info(
|
|
156
|
+
"Vulture healer complete — healed=%d, skipped=%d, errors=%d (write=%s)",
|
|
157
|
+
healed,
|
|
158
|
+
skipped,
|
|
159
|
+
errors,
|
|
160
|
+
write,
|
|
161
|
+
)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# src/body/services/artifact_service.py
|
|
2
|
+
"""
|
|
3
|
+
ArtifactService - Data-access layer for core.repo_artifacts (embedding lifecycle).
|
|
4
|
+
|
|
5
|
+
Covers:
|
|
6
|
+
- RepoEmbedderWorker.run — fetch unembedded, mark empty, update chunk count
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from sqlalchemy import text
|
|
14
|
+
|
|
15
|
+
from shared.logger import getLogger
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# ID: beea8b47-3e24-45cf-af38-f2624f65d3b5
|
|
22
|
+
class ArtifactService:
|
|
23
|
+
"""
|
|
24
|
+
Body layer service. Exposes named methods for core.repo_artifacts
|
|
25
|
+
operations used by RepoEmbedderWorker.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
# ID: 5b5d1e10-9ee1-45da-971d-8c5663c445ff
|
|
29
|
+
async def fetch_unembedded_artifacts(self, batch_size: int) -> list[dict[str, Any]]:
|
|
30
|
+
"""
|
|
31
|
+
Return up to *batch_size* artifacts that have not yet been embedded
|
|
32
|
+
(chunk_count = 0), ordered by most recently crawled first.
|
|
33
|
+
Excludes permanently-skipped artifacts (chunk_count = -1).
|
|
34
|
+
|
|
35
|
+
Returns list of dicts with keys: id, file_path, artifact_type,
|
|
36
|
+
qdrant_collection.
|
|
37
|
+
|
|
38
|
+
Covers:
|
|
39
|
+
- RepoEmbedderWorker.run — SELECT from core.repo_artifacts WHERE chunk_count = 0
|
|
40
|
+
"""
|
|
41
|
+
from body.services.service_registry import ServiceRegistry
|
|
42
|
+
|
|
43
|
+
async with ServiceRegistry.session() as session:
|
|
44
|
+
result = await session.execute(
|
|
45
|
+
text(
|
|
46
|
+
"""
|
|
47
|
+
SELECT id, file_path, artifact_type, qdrant_collection
|
|
48
|
+
FROM core.repo_artifacts
|
|
49
|
+
WHERE chunk_count = 0
|
|
50
|
+
AND chunk_count != -1
|
|
51
|
+
ORDER BY last_crawled_at DESC
|
|
52
|
+
LIMIT :batch_size
|
|
53
|
+
"""
|
|
54
|
+
),
|
|
55
|
+
{"batch_size": batch_size},
|
|
56
|
+
)
|
|
57
|
+
return [
|
|
58
|
+
{
|
|
59
|
+
"id": str(row[0]),
|
|
60
|
+
"file_path": row[1],
|
|
61
|
+
"artifact_type": row[2],
|
|
62
|
+
"qdrant_collection": row[3],
|
|
63
|
+
}
|
|
64
|
+
for row in result.fetchall()
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
# ID: 5ca77ba6-4b34-46f3-a65b-29e0a29850ee
|
|
68
|
+
async def mark_artifact_empty(self, artifact_id: str) -> None:
|
|
69
|
+
"""
|
|
70
|
+
Set chunk_count = -1 to permanently skip an empty artifact.
|
|
71
|
+
|
|
72
|
+
Covers:
|
|
73
|
+
- RepoEmbedderWorker.run — UPDATE chunk_count = -1 (empty file branch)
|
|
74
|
+
"""
|
|
75
|
+
from body.services.service_registry import ServiceRegistry
|
|
76
|
+
|
|
77
|
+
async with ServiceRegistry.session() as session:
|
|
78
|
+
await session.execute(
|
|
79
|
+
text(
|
|
80
|
+
"UPDATE core.repo_artifacts SET chunk_count = -1 "
|
|
81
|
+
"WHERE id = cast(:artifact_id as uuid)"
|
|
82
|
+
),
|
|
83
|
+
{"artifact_id": artifact_id},
|
|
84
|
+
)
|
|
85
|
+
await session.commit()
|
|
86
|
+
|
|
87
|
+
# ID: 8ed59fa4-8696-4b39-848d-582949d7248b
|
|
88
|
+
async def update_artifact_chunk_count(
|
|
89
|
+
self, artifact_id: str, chunk_count: int
|
|
90
|
+
) -> None:
|
|
91
|
+
"""
|
|
92
|
+
Record the number of semantic chunks produced for an artifact
|
|
93
|
+
after a successful embedding pass.
|
|
94
|
+
|
|
95
|
+
Covers:
|
|
96
|
+
- RepoEmbedderWorker.run — UPDATE core.repo_artifacts SET chunk_count = :chunk_count
|
|
97
|
+
"""
|
|
98
|
+
from body.services.service_registry import ServiceRegistry
|
|
99
|
+
|
|
100
|
+
async with ServiceRegistry.session() as session:
|
|
101
|
+
await session.execute(
|
|
102
|
+
text(
|
|
103
|
+
"""
|
|
104
|
+
UPDATE core.repo_artifacts
|
|
105
|
+
SET chunk_count = :chunk_count
|
|
106
|
+
WHERE id = cast(:artifact_id as uuid)
|
|
107
|
+
"""
|
|
108
|
+
),
|
|
109
|
+
{"chunk_count": chunk_count, "artifact_id": artifact_id},
|
|
110
|
+
)
|
|
111
|
+
await session.commit()
|
|
112
|
+
|
|
113
|
+
# ID: c3d4e5f6-a7b8-9012-cdef-012345678901
|
|
114
|
+
async def count_pending_artifacts(self) -> int:
|
|
115
|
+
"""
|
|
116
|
+
Count repo_artifacts with chunk_count = 0 (unembedded, not permanently skipped).
|
|
117
|
+
|
|
118
|
+
Covers:
|
|
119
|
+
- sync_actions.action_sync_code_vectors — per-pass pending check
|
|
120
|
+
"""
|
|
121
|
+
from body.services.service_registry import ServiceRegistry
|
|
122
|
+
|
|
123
|
+
async with ServiceRegistry.session() as session:
|
|
124
|
+
result = await session.execute(
|
|
125
|
+
text(
|
|
126
|
+
"SELECT COUNT(*) FROM core.repo_artifacts "
|
|
127
|
+
"WHERE chunk_count = 0 AND chunk_count != -1"
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
return result.scalar() or 0
|
|
131
|
+
|
|
132
|
+
# ID: 1a8d7e2b-5c91-4f3a-9d6b-8e4c0a72f513
|
|
133
|
+
async def reset_pending_chunk_counts(self) -> int:
|
|
134
|
+
"""
|
|
135
|
+
Reset chunk_count to 0 on every artifact that has been embedded
|
|
136
|
+
(chunk_count > 0), forcing the next embed pass to treat them as
|
|
137
|
+
pending. Permanently-skipped artifacts (chunk_count = -1) are left
|
|
138
|
+
alone — they were determined empty and should not be re-queued.
|
|
139
|
+
|
|
140
|
+
Returns the number of rows reset.
|
|
141
|
+
|
|
142
|
+
Covers:
|
|
143
|
+
- sync.vectors_code force=True — pre-loop reset before re-embed.
|
|
144
|
+
"""
|
|
145
|
+
from body.services.service_registry import ServiceRegistry
|
|
146
|
+
|
|
147
|
+
async with ServiceRegistry.session() as session:
|
|
148
|
+
result = await session.execute(
|
|
149
|
+
text(
|
|
150
|
+
"UPDATE core.repo_artifacts SET chunk_count = 0 "
|
|
151
|
+
"WHERE chunk_count > 0"
|
|
152
|
+
)
|
|
153
|
+
)
|
|
154
|
+
await session.commit()
|
|
155
|
+
return result.rowcount or 0
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# src/body/services/blackboard_service/__init__.py
|
|
2
|
+
# blackboard_service/__init__.py
|
|
3
|
+
"""
|
|
4
|
+
Package split from blackboard_service.py.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from .blackboard_claim_service import BlackboardClaimService
|
|
10
|
+
from .blackboard_proposal_service import BlackboardProposalService
|
|
11
|
+
from .blackboard_query_service import BlackboardQueryService
|
|
12
|
+
from .blackboard_service import BlackboardService
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# ID: 88382dd0-e47a-4538-88b7-40c050a649f8
|
|
16
|
+
class BlackboardService(
|
|
17
|
+
BlackboardService,
|
|
18
|
+
BlackboardProposalService,
|
|
19
|
+
BlackboardQueryService,
|
|
20
|
+
BlackboardClaimService,
|
|
21
|
+
):
|
|
22
|
+
pass
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# src/body/services/blackboard_service/blackboard_claim_service.py
|
|
2
|
+
"""Atomic claiming methods — FOR UPDATE SKIP LOCKED, return claimed rows."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import uuid
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from sqlalchemy import text
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# ID: 9f135870-8e69-4c6b-a733-3c24cb8be8dc
|
|
14
|
+
class BlackboardClaimService:
|
|
15
|
+
# ID: 39ffce8c-7f06-40c0-b8e6-16183b788a56
|
|
16
|
+
async def claim_open_findings(
|
|
17
|
+
self, subject_prefix: str, limit: int
|
|
18
|
+
) -> list[dict[str, Any]]:
|
|
19
|
+
"""
|
|
20
|
+
Atomically claim up to *limit* open findings whose subject matches
|
|
21
|
+
*subject_prefix*. Uses FOR UPDATE SKIP LOCKED to prevent
|
|
22
|
+
double-claiming across concurrent worker instances.
|
|
23
|
+
|
|
24
|
+
Returns list of dicts with keys: id, subject, payload.
|
|
25
|
+
|
|
26
|
+
Covers:
|
|
27
|
+
- PromptExtractorWorker._claim_open_findings
|
|
28
|
+
"""
|
|
29
|
+
from body.services.service_registry import ServiceRegistry
|
|
30
|
+
|
|
31
|
+
async with ServiceRegistry.session() as session:
|
|
32
|
+
async with session.begin():
|
|
33
|
+
result = await session.execute(
|
|
34
|
+
text(
|
|
35
|
+
"""
|
|
36
|
+
UPDATE core.blackboard_entries
|
|
37
|
+
SET status = 'claimed',
|
|
38
|
+
claimed_at = now(),
|
|
39
|
+
updated_at = now()
|
|
40
|
+
WHERE id IN (
|
|
41
|
+
SELECT id FROM core.blackboard_entries
|
|
42
|
+
WHERE entry_type = 'finding'
|
|
43
|
+
AND subject LIKE :prefix
|
|
44
|
+
AND status = 'open'
|
|
45
|
+
ORDER BY created_at ASC
|
|
46
|
+
LIMIT :limit
|
|
47
|
+
FOR UPDATE SKIP LOCKED
|
|
48
|
+
)
|
|
49
|
+
RETURNING id, subject, payload
|
|
50
|
+
"""
|
|
51
|
+
),
|
|
52
|
+
{"prefix": subject_prefix, "limit": limit},
|
|
53
|
+
)
|
|
54
|
+
rows = result.fetchall()
|
|
55
|
+
|
|
56
|
+
findings = []
|
|
57
|
+
for row in rows:
|
|
58
|
+
raw_payload = row[2]
|
|
59
|
+
payload = (
|
|
60
|
+
raw_payload
|
|
61
|
+
if isinstance(raw_payload, dict)
|
|
62
|
+
else json.loads(raw_payload)
|
|
63
|
+
)
|
|
64
|
+
findings.append(
|
|
65
|
+
{
|
|
66
|
+
"id": str(row[0]),
|
|
67
|
+
"subject": row[1],
|
|
68
|
+
"payload": payload,
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
return findings
|
|
72
|
+
|
|
73
|
+
# ID: f3a8d1c2-7e45-4b09-a3f6-9d2c0e5b1a87
|
|
74
|
+
async def claim_violation_findings(
|
|
75
|
+
self, prefix: str, limit: int, claimed_by: uuid.UUID | None = None
|
|
76
|
+
) -> list[dict[str, Any]]:
|
|
77
|
+
"""
|
|
78
|
+
Atomically claim up to *limit* open findings whose subject matches
|
|
79
|
+
*prefix*, ordered by severity (critical first) then creation time.
|
|
80
|
+
Uses FOR UPDATE SKIP LOCKED to prevent double-claiming across
|
|
81
|
+
concurrent worker instances.
|
|
82
|
+
|
|
83
|
+
Returns list of dicts with keys: id, subject, payload.
|
|
84
|
+
|
|
85
|
+
Covers:
|
|
86
|
+
- ViolationRemediator._claim_open_findings
|
|
87
|
+
"""
|
|
88
|
+
from body.services.service_registry import ServiceRegistry
|
|
89
|
+
|
|
90
|
+
async with ServiceRegistry.session() as session:
|
|
91
|
+
async with session.begin():
|
|
92
|
+
result = await session.execute(
|
|
93
|
+
text(
|
|
94
|
+
"""
|
|
95
|
+
UPDATE core.blackboard_entries
|
|
96
|
+
SET status = 'claimed',
|
|
97
|
+
claimed_by = :claimed_by,
|
|
98
|
+
claimed_at = now(),
|
|
99
|
+
updated_at = now()
|
|
100
|
+
WHERE id IN (
|
|
101
|
+
SELECT id FROM core.blackboard_entries
|
|
102
|
+
WHERE entry_type = 'finding'
|
|
103
|
+
AND subject LIKE :prefix
|
|
104
|
+
AND status = 'open'
|
|
105
|
+
ORDER BY
|
|
106
|
+
CASE (payload->>'severity')
|
|
107
|
+
WHEN 'critical' THEN 1
|
|
108
|
+
WHEN 'error' THEN 2
|
|
109
|
+
WHEN 'warning' THEN 3
|
|
110
|
+
WHEN 'info' THEN 4
|
|
111
|
+
ELSE 5
|
|
112
|
+
END ASC,
|
|
113
|
+
created_at ASC
|
|
114
|
+
LIMIT :limit
|
|
115
|
+
FOR UPDATE SKIP LOCKED
|
|
116
|
+
)
|
|
117
|
+
RETURNING id, subject, payload
|
|
118
|
+
"""
|
|
119
|
+
),
|
|
120
|
+
{
|
|
121
|
+
"prefix": prefix,
|
|
122
|
+
"limit": limit,
|
|
123
|
+
"claimed_by": str(claimed_by) if claimed_by else None,
|
|
124
|
+
},
|
|
125
|
+
)
|
|
126
|
+
rows = result.fetchall()
|
|
127
|
+
|
|
128
|
+
findings = []
|
|
129
|
+
for row in rows:
|
|
130
|
+
raw_payload = row[2]
|
|
131
|
+
payload = (
|
|
132
|
+
raw_payload
|
|
133
|
+
if isinstance(raw_payload, dict)
|
|
134
|
+
else json.loads(raw_payload)
|
|
135
|
+
)
|
|
136
|
+
findings.append(
|
|
137
|
+
{
|
|
138
|
+
"id": str(row[0]),
|
|
139
|
+
"subject": row[1],
|
|
140
|
+
"payload": payload,
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
return findings
|
|
144
|
+
|
|
145
|
+
# ID: 8b1e6f3a-d42c-4e7a-9f05-b3c8a71d2e94
|
|
146
|
+
async def claim_unmapped_violation_findings(
|
|
147
|
+
self,
|
|
148
|
+
mapped_rule_ids: set[str],
|
|
149
|
+
limit: int,
|
|
150
|
+
claimed_by: uuid.UUID,
|
|
151
|
+
) -> list[dict[str, Any]]:
|
|
152
|
+
"""
|
|
153
|
+
Atomically claim open audit.violation findings whose rule is NOT
|
|
154
|
+
in the mapped_rule_ids set. Used by ViolationExecutorWorker (Will)
|
|
155
|
+
to claim findings that RemediatorWorker left unclaimed.
|
|
156
|
+
|
|
157
|
+
Returns a list of dicts: {id, subject, payload}.
|
|
158
|
+
"""
|
|
159
|
+
from body.services.service_registry import ServiceRegistry
|
|
160
|
+
|
|
161
|
+
if mapped_rule_ids:
|
|
162
|
+
rule_filter = "AND payload->>'rule' != ALL(:mapped_rules)"
|
|
163
|
+
params: dict[str, Any] = {
|
|
164
|
+
"limit": limit,
|
|
165
|
+
"claimed_by": str(claimed_by),
|
|
166
|
+
"mapped_rules": list(mapped_rule_ids),
|
|
167
|
+
}
|
|
168
|
+
else:
|
|
169
|
+
rule_filter = ""
|
|
170
|
+
params = {
|
|
171
|
+
"limit": limit,
|
|
172
|
+
"claimed_by": str(claimed_by),
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
sql = f"""
|
|
176
|
+
WITH to_claim AS (
|
|
177
|
+
SELECT id
|
|
178
|
+
FROM core.blackboard_entries
|
|
179
|
+
WHERE entry_type = 'finding'
|
|
180
|
+
AND subject LIKE 'audit.violation::%%'
|
|
181
|
+
AND status = 'open'
|
|
182
|
+
{rule_filter}
|
|
183
|
+
ORDER BY created_at ASC
|
|
184
|
+
LIMIT :limit
|
|
185
|
+
FOR UPDATE SKIP LOCKED
|
|
186
|
+
)
|
|
187
|
+
UPDATE core.blackboard_entries
|
|
188
|
+
SET status = 'claimed',
|
|
189
|
+
claimed_by = cast(:claimed_by as uuid),
|
|
190
|
+
claimed_at = now(),
|
|
191
|
+
updated_at = now()
|
|
192
|
+
WHERE id IN (SELECT id FROM to_claim)
|
|
193
|
+
RETURNING id, subject, payload
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
async with ServiceRegistry.session() as session:
|
|
197
|
+
async with session.begin():
|
|
198
|
+
result = await session.execute(text(sql), params)
|
|
199
|
+
rows = result.fetchall()
|
|
200
|
+
|
|
201
|
+
findings = []
|
|
202
|
+
for row in rows:
|
|
203
|
+
raw_payload = row[2]
|
|
204
|
+
payload = (
|
|
205
|
+
raw_payload
|
|
206
|
+
if isinstance(raw_payload, dict)
|
|
207
|
+
else json.loads(raw_payload)
|
|
208
|
+
)
|
|
209
|
+
findings.append(
|
|
210
|
+
{
|
|
211
|
+
"id": str(row[0]),
|
|
212
|
+
"subject": row[1],
|
|
213
|
+
"payload": payload,
|
|
214
|
+
}
|
|
215
|
+
)
|
|
216
|
+
return findings
|