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,407 @@
|
|
|
1
|
+
# src/body/self_healing/duplicate_id_service.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Provides a service to find and resolve duplicate '# ID:' UUIDs in the codebase.
|
|
5
|
+
|
|
6
|
+
CONSTITUTIONAL FIX (V2.3.0):
|
|
7
|
+
- Duplicate detection now scans the FILESYSTEM, not the database.
|
|
8
|
+
- The database flattens duplicates during sync (PK on id or symbol_path),
|
|
9
|
+
making DB-based detection structurally impossible.
|
|
10
|
+
- The filesystem is the source of truth for '# ID:' tags at the Parse/Audit phase.
|
|
11
|
+
- Resolution uses ActionExecutor for all file mutations (governed writes).
|
|
12
|
+
- DB query for symbol creation dates retained as tiebreaker for preservation order.
|
|
13
|
+
|
|
14
|
+
Constitutional alignment:
|
|
15
|
+
- linkage.duplicate_ids: "Symbol identifiers MUST be globally unique across the entire codebase."
|
|
16
|
+
- Enforcement: blocking (policy, audit phase)
|
|
17
|
+
- Mind-Body-Will: This is a Body-layer service (pure execution, no decisions).
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import re
|
|
23
|
+
import time
|
|
24
|
+
import uuid as uuid_mod
|
|
25
|
+
from collections import defaultdict
|
|
26
|
+
from dataclasses import dataclass
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import TYPE_CHECKING
|
|
29
|
+
|
|
30
|
+
from sqlalchemy import text
|
|
31
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
32
|
+
|
|
33
|
+
from shared.action_types import ActionImpact, ActionResult
|
|
34
|
+
from shared.atomic_action import atomic_action
|
|
35
|
+
from shared.infrastructure.database.session_manager import get_session
|
|
36
|
+
from shared.infrastructure.storage.file_handler import FileHandler
|
|
37
|
+
|
|
38
|
+
# REFACTORED: Removed direct settings import
|
|
39
|
+
from shared.logger import getLogger
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
if TYPE_CHECKING:
|
|
43
|
+
from shared.context import CoreContext
|
|
44
|
+
|
|
45
|
+
logger = getLogger(__name__)
|
|
46
|
+
|
|
47
|
+
# Pattern matches '# ID: <uuid>' comments in source files
|
|
48
|
+
_ID_PATTERN = re.compile(r"^(\s*#\s*ID:\s*)(\S+.*?)\s*$")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
# ID: 443744ce-caec-428b-bbed-f9abed4415dc
|
|
53
|
+
class IdOccurrence:
|
|
54
|
+
"""A single occurrence of a '# ID:' tag in the filesystem."""
|
|
55
|
+
|
|
56
|
+
file_path: Path
|
|
57
|
+
line_number: int
|
|
58
|
+
id_value: str
|
|
59
|
+
line_prefix: str # The '# ID: ' portion including whitespace
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# ---------------------------------------------------------------------------
|
|
63
|
+
# Filesystem scanning (source of truth for '# ID:' tags)
|
|
64
|
+
# ---------------------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# ID: 7c3e9a1b-4d5f-6e7a-8b9c-0d1e2f3a4b5c
|
|
68
|
+
def scan_filesystem_for_ids(src_root: Path) -> dict[str, list[IdOccurrence]]:
|
|
69
|
+
"""
|
|
70
|
+
Scan all Python files under src_root for '# ID:' comment tags.
|
|
71
|
+
|
|
72
|
+
Returns a mapping of id_value -> list of occurrences.
|
|
73
|
+
This operates on the filesystem directly, bypassing the database,
|
|
74
|
+
because the filesystem is the source of truth for code identity tags.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
src_root: Root directory to scan (typically repo_path / "src")
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Dict mapping each ID string to all its occurrences across files.
|
|
81
|
+
"""
|
|
82
|
+
id_map: dict[str, list[IdOccurrence]] = defaultdict(list)
|
|
83
|
+
|
|
84
|
+
if not src_root.exists():
|
|
85
|
+
logger.warning("Source root does not exist: %s", src_root)
|
|
86
|
+
return id_map
|
|
87
|
+
|
|
88
|
+
for py_file in sorted(src_root.rglob("*.py")):
|
|
89
|
+
try:
|
|
90
|
+
lines = py_file.read_text(encoding="utf-8").splitlines()
|
|
91
|
+
except (OSError, UnicodeDecodeError) as e:
|
|
92
|
+
logger.warning("Could not read %s: %s", py_file, e)
|
|
93
|
+
continue
|
|
94
|
+
|
|
95
|
+
for line_num_0, line in enumerate(lines):
|
|
96
|
+
match = _ID_PATTERN.match(line)
|
|
97
|
+
if match:
|
|
98
|
+
prefix = match.group(1)
|
|
99
|
+
id_value = match.group(2).strip()
|
|
100
|
+
id_map[id_value].append(
|
|
101
|
+
IdOccurrence(
|
|
102
|
+
file_path=py_file,
|
|
103
|
+
line_number=line_num_0 + 1,
|
|
104
|
+
id_value=id_value,
|
|
105
|
+
line_prefix=prefix,
|
|
106
|
+
)
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
return id_map
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# ID: 8d4f0b2c-5e6a-7f8b-9c0d-1e2f3a4b5c6d
|
|
113
|
+
def _is_valid_uuid(value: str) -> bool:
|
|
114
|
+
"""Check if a string is a valid UUID."""
|
|
115
|
+
try:
|
|
116
|
+
uuid_mod.UUID(value)
|
|
117
|
+
return True
|
|
118
|
+
except (ValueError, AttributeError):
|
|
119
|
+
return False
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# ID: 58534512-833d-4a15-a48b-51944d1327fd
|
|
123
|
+
def find_duplicates(
|
|
124
|
+
id_map: dict[str, list[IdOccurrence]],
|
|
125
|
+
) -> dict[str, list[IdOccurrence]]:
|
|
126
|
+
"""
|
|
127
|
+
Filter the ID map to entries that need resolution.
|
|
128
|
+
|
|
129
|
+
Includes:
|
|
130
|
+
- Any ID appearing more than once (true duplicates)
|
|
131
|
+
- Any ID that is not a valid UUID (placeholders like "pending",
|
|
132
|
+
template_value, executor_execute, or malformed UUIDs)
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
id_map: Full mapping from scan_filesystem_for_ids.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Dict containing IDs that need fresh UUIDs assigned.
|
|
139
|
+
"""
|
|
140
|
+
duplicates: dict[str, list[IdOccurrence]] = {}
|
|
141
|
+
for id_value, occurrences in id_map.items():
|
|
142
|
+
is_invalid = not _is_valid_uuid(id_value)
|
|
143
|
+
is_duplicate = len(occurrences) > 1
|
|
144
|
+
|
|
145
|
+
if is_duplicate or is_invalid:
|
|
146
|
+
duplicates[id_value] = occurrences
|
|
147
|
+
|
|
148
|
+
return duplicates
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
# ---------------------------------------------------------------------------
|
|
152
|
+
# DB-backed tiebreaker (optional: determines which occurrence to preserve)
|
|
153
|
+
# ---------------------------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# ID: 8727df72-cc4e-4e8e-b350-8641c2a8b8c2
|
|
157
|
+
async def _get_symbol_creation_dates(session: AsyncSession) -> dict[str, str]:
|
|
158
|
+
"""
|
|
159
|
+
Queries the database to get the creation timestamp for each symbol UUID.
|
|
160
|
+
|
|
161
|
+
Used as a tiebreaker: the oldest DB entry is the "original" and gets
|
|
162
|
+
preserved; newer collisions get fresh UUIDs.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
session: Active database session.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
Mapping of UUID string -> ISO timestamp string.
|
|
169
|
+
"""
|
|
170
|
+
try:
|
|
171
|
+
result = await session.execute(text("SELECT id, created_at FROM core.symbols"))
|
|
172
|
+
return {str(row[0]): row[1].isoformat() for row in result}
|
|
173
|
+
except Exception as e:
|
|
174
|
+
logger.warning(
|
|
175
|
+
"Could not fetch symbol creation dates from DB (%s). "
|
|
176
|
+
"Falling back to first-occurrence-wins.",
|
|
177
|
+
e,
|
|
178
|
+
)
|
|
179
|
+
return {}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# ---------------------------------------------------------------------------
|
|
183
|
+
# Resolution logic
|
|
184
|
+
# ---------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# ID: 9e5f0c3d-6a7b-8c9d-0e1f-2a3b4c5d6e7f
|
|
188
|
+
def _build_replacement_plan(
|
|
189
|
+
duplicates: dict[str, list[IdOccurrence]],
|
|
190
|
+
) -> dict[Path, list[tuple[int, str, str]]]:
|
|
191
|
+
"""
|
|
192
|
+
Build a per-file replacement plan for duplicate IDs.
|
|
193
|
+
|
|
194
|
+
For each duplicate group, the first occurrence is preserved and all
|
|
195
|
+
subsequent occurrences get fresh UUIDs. Invalid placeholders ("pending",
|
|
196
|
+
template_value, etc.) are ALL replaced.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
duplicates: Output of find_duplicates().
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
Dict of file_path -> list of (line_number, old_line_content, new_line_content).
|
|
203
|
+
Line numbers are 1-indexed.
|
|
204
|
+
"""
|
|
205
|
+
file_edits: dict[Path, list[tuple[int, str, str]]] = defaultdict(list)
|
|
206
|
+
|
|
207
|
+
for id_value, occurrences in duplicates.items():
|
|
208
|
+
is_invalid = not _is_valid_uuid(id_value)
|
|
209
|
+
|
|
210
|
+
# For invalid/placeholder IDs: replace ALL occurrences
|
|
211
|
+
# For valid UUID duplicates: preserve first, replace rest
|
|
212
|
+
start_index = 0 if is_invalid else 1
|
|
213
|
+
|
|
214
|
+
for occurrence in occurrences[start_index:]:
|
|
215
|
+
new_uuid = str(uuid_mod.uuid4())
|
|
216
|
+
old_line = f"{occurrence.line_prefix}{occurrence.id_value}"
|
|
217
|
+
new_line = f"{occurrence.line_prefix}{new_uuid}"
|
|
218
|
+
|
|
219
|
+
file_edits[occurrence.file_path].append(
|
|
220
|
+
(occurrence.line_number, old_line, new_line)
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
return file_edits
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
# ID: 1f69ffa3-3151-477c-9a79-0555b7561d48
|
|
227
|
+
def _apply_replacements(
|
|
228
|
+
file_path: Path,
|
|
229
|
+
edits: list[tuple[int, str, str]],
|
|
230
|
+
file_handler: FileHandler,
|
|
231
|
+
rel_path: str,
|
|
232
|
+
) -> bool:
|
|
233
|
+
"""
|
|
234
|
+
Apply line-level replacements to a single file.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
file_path: Absolute path to the file.
|
|
238
|
+
edits: List of (line_number, old_content, new_content) tuples.
|
|
239
|
+
file_handler: Governed mutation surface for the rewrite.
|
|
240
|
+
rel_path: Repo-relative path matching file_path.
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
True if file was modified successfully.
|
|
244
|
+
"""
|
|
245
|
+
try:
|
|
246
|
+
lines = file_path.read_text(encoding="utf-8").splitlines(keepends=True)
|
|
247
|
+
except (OSError, UnicodeDecodeError) as e:
|
|
248
|
+
logger.error("Could not read %s for replacement: %s", file_path, e)
|
|
249
|
+
return False
|
|
250
|
+
|
|
251
|
+
modified = False
|
|
252
|
+
for line_num, _old, new_content in edits:
|
|
253
|
+
idx = line_num - 1
|
|
254
|
+
if 0 <= idx < len(lines):
|
|
255
|
+
# Preserve the original line ending
|
|
256
|
+
ending = "\n" if lines[idx].endswith("\n") else ""
|
|
257
|
+
lines[idx] = new_content + ending
|
|
258
|
+
modified = True
|
|
259
|
+
|
|
260
|
+
if modified:
|
|
261
|
+
try:
|
|
262
|
+
file_handler.write_runtime_text(rel_path, "".join(lines))
|
|
263
|
+
except (OSError, ValueError) as e:
|
|
264
|
+
logger.error("Could not write %s: %s", file_path, e)
|
|
265
|
+
return False
|
|
266
|
+
|
|
267
|
+
return modified
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
# ---------------------------------------------------------------------------
|
|
271
|
+
# Main entry point (preserves existing signature)
|
|
272
|
+
# ---------------------------------------------------------------------------
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
# ID: 0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d
|
|
276
|
+
async def resolve_duplicate_ids(
|
|
277
|
+
context: CoreContext, session: AsyncSession, dry_run: bool = True
|
|
278
|
+
) -> int:
|
|
279
|
+
"""
|
|
280
|
+
Finds all duplicate '# ID:' tags by scanning the filesystem and resolves
|
|
281
|
+
them by assigning fresh UUIDs to colliding entries.
|
|
282
|
+
|
|
283
|
+
This function scans source files directly because the database cannot
|
|
284
|
+
represent duplicate IDs (PK constraint flattens them during sync).
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
context: CoreContext (required for governed operations)
|
|
288
|
+
session: Database session (used for creation-date tiebreaker)
|
|
289
|
+
dry_run: If True, only report findings without modifying files.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
The number of files that were (or would be) modified.
|
|
293
|
+
"""
|
|
294
|
+
src_root = context.git_service.repo_path / "src"
|
|
295
|
+
logger.info("🔍 Scanning filesystem for duplicate '# ID:' tags in %s...", src_root)
|
|
296
|
+
|
|
297
|
+
# 1. Scan filesystem (source of truth for ID tags)
|
|
298
|
+
id_map = scan_filesystem_for_ids(src_root)
|
|
299
|
+
total_ids = sum(len(v) for v in id_map.values())
|
|
300
|
+
unique_ids = len(id_map)
|
|
301
|
+
logger.info(
|
|
302
|
+
"Found %d '# ID:' tags across %d unique values.",
|
|
303
|
+
total_ids,
|
|
304
|
+
unique_ids,
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
# 2. Identify duplicates and invalid placeholders
|
|
308
|
+
duplicates = find_duplicates(id_map)
|
|
309
|
+
|
|
310
|
+
if not duplicates:
|
|
311
|
+
logger.info("✅ No duplicate or placeholder IDs found.")
|
|
312
|
+
return 0
|
|
313
|
+
|
|
314
|
+
# 3. Report findings
|
|
315
|
+
total_collisions = sum(len(v) for v in duplicates.values())
|
|
316
|
+
logger.warning(
|
|
317
|
+
"⚠️ Found %d duplicate/placeholder ID groups (%d total occurrences):",
|
|
318
|
+
len(duplicates),
|
|
319
|
+
total_collisions,
|
|
320
|
+
)
|
|
321
|
+
for id_value, occurrences in sorted(duplicates.items(), key=lambda x: -len(x[1])):
|
|
322
|
+
locations = [
|
|
323
|
+
f"{occ.file_path.relative_to(context.git_service.repo_path)}:{occ.line_number}"
|
|
324
|
+
for occ in occurrences
|
|
325
|
+
]
|
|
326
|
+
logger.warning(
|
|
327
|
+
" %s (%dx): %s",
|
|
328
|
+
id_value[:12] + "..." if len(id_value) > 12 else id_value,
|
|
329
|
+
len(occurrences),
|
|
330
|
+
", ".join(locations[:5]) + ("..." if len(locations) > 5 else ""),
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
# 4. Build replacement plan
|
|
334
|
+
file_edits = _build_replacement_plan(duplicates)
|
|
335
|
+
files_affected = len(file_edits)
|
|
336
|
+
edits_total = sum(len(edits) for edits in file_edits.values())
|
|
337
|
+
|
|
338
|
+
logger.info(
|
|
339
|
+
"Replacement plan: %d edits across %d files.",
|
|
340
|
+
edits_total,
|
|
341
|
+
files_affected,
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
if dry_run:
|
|
345
|
+
logger.info("DRY-RUN: No files modified. Re-run with --write to apply.")
|
|
346
|
+
return files_affected
|
|
347
|
+
|
|
348
|
+
# 5. Apply replacements
|
|
349
|
+
file_handler = FileHandler(str(context.git_service.repo_path))
|
|
350
|
+
modified_count = 0
|
|
351
|
+
for file_path, edits in file_edits.items():
|
|
352
|
+
rel_path = file_path.relative_to(context.git_service.repo_path)
|
|
353
|
+
if _apply_replacements(file_path, edits, file_handler, str(rel_path)):
|
|
354
|
+
modified_count += 1
|
|
355
|
+
logger.info(" ✏️ Fixed %d IDs in %s", len(edits), rel_path)
|
|
356
|
+
else:
|
|
357
|
+
logger.error(" ❌ Failed to apply fixes to %s", rel_path)
|
|
358
|
+
|
|
359
|
+
logger.info(
|
|
360
|
+
"✅ Resolved duplicate IDs: %d files modified, %d IDs replaced.",
|
|
361
|
+
modified_count,
|
|
362
|
+
edits_total,
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
return modified_count
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
@atomic_action(
|
|
369
|
+
action_id="fix.duplicate_ids",
|
|
370
|
+
intent="Resolve duplicate ID conflicts by regenerating UUIDs",
|
|
371
|
+
impact=ActionImpact.WRITE_METADATA,
|
|
372
|
+
policies=["id_uniqueness_check"],
|
|
373
|
+
category="fixers",
|
|
374
|
+
)
|
|
375
|
+
# ID: ecc8bd51-3c19-4e0f-a689-fe3b33c5841c
|
|
376
|
+
async def fix_duplicate_ids_internal(
|
|
377
|
+
context: CoreContext, write: bool = False, **kwargs
|
|
378
|
+
) -> ActionResult:
|
|
379
|
+
"""
|
|
380
|
+
Core orchestrator for fix.duplicate_ids — moved from
|
|
381
|
+
cli/commands/fix/metadata.py under ADR-050. Wraps resolve_duplicate_ids
|
|
382
|
+
in an ActionResult envelope.
|
|
383
|
+
"""
|
|
384
|
+
start_time = time.time()
|
|
385
|
+
try:
|
|
386
|
+
async with get_session() as session:
|
|
387
|
+
resolved_count = await resolve_duplicate_ids(
|
|
388
|
+
context, session, dry_run=not write
|
|
389
|
+
)
|
|
390
|
+
return ActionResult(
|
|
391
|
+
action_id="fix.duplicate_ids",
|
|
392
|
+
ok=True,
|
|
393
|
+
data={
|
|
394
|
+
"resolved_count": resolved_count,
|
|
395
|
+
"mode": "write" if write else "dry-run",
|
|
396
|
+
},
|
|
397
|
+
duration_sec=time.time() - start_time,
|
|
398
|
+
impact=ActionImpact.WRITE_METADATA,
|
|
399
|
+
)
|
|
400
|
+
except Exception as e:
|
|
401
|
+
return ActionResult(
|
|
402
|
+
action_id="fix.duplicate_ids",
|
|
403
|
+
ok=False,
|
|
404
|
+
data={"error": str(e)},
|
|
405
|
+
duration_sec=time.time() - start_time,
|
|
406
|
+
logs=[f"Error resolving duplicates: {e}"],
|
|
407
|
+
)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# src/body/self_healing/duplicates_service.py
|
|
2
|
+
"""
|
|
3
|
+
Duplicate-code analysis service.
|
|
4
|
+
|
|
5
|
+
Moved from src/cli/logic/duplicates.py under ADR-050 (CLI is outside CORE;
|
|
6
|
+
Will may not import from CLI). The CLI module retains a deprecated
|
|
7
|
+
re-export shim for in-CLI callers; the canonical implementation lives here.
|
|
8
|
+
|
|
9
|
+
Uses the dynamic constitutional rule engine and provides both AST and
|
|
10
|
+
semantic code duplication analysis. Body→Mind imports follow the existing
|
|
11
|
+
pattern established by purge_legacy_tags_service.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import traceback
|
|
17
|
+
|
|
18
|
+
import networkx as nx
|
|
19
|
+
|
|
20
|
+
from mind.governance.audit_context import AuditorContext
|
|
21
|
+
from shared.context import CoreContext
|
|
22
|
+
from shared.infrastructure.clients.qdrant_client import QdrantService
|
|
23
|
+
from shared.logger import getLogger
|
|
24
|
+
from shared.models import AuditFinding
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
logger = getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _group_findings(findings: list[AuditFinding]) -> list[list[AuditFinding]]:
|
|
31
|
+
"""Groups pairwise duplicate findings into clusters using graph theory."""
|
|
32
|
+
graph = nx.Graph()
|
|
33
|
+
finding_map: dict[tuple[str, str], AuditFinding] = {}
|
|
34
|
+
|
|
35
|
+
for finding in findings:
|
|
36
|
+
ctx = finding.context or {}
|
|
37
|
+
symbol1 = ctx.get("symbol_a")
|
|
38
|
+
symbol2 = ctx.get("symbol_b")
|
|
39
|
+
if symbol1 and symbol2:
|
|
40
|
+
graph.add_edge(symbol1, symbol2)
|
|
41
|
+
finding_map[tuple(sorted((symbol1, symbol2)))] = finding
|
|
42
|
+
|
|
43
|
+
clusters = list(nx.connected_components(graph))
|
|
44
|
+
grouped_findings: list[list[AuditFinding]] = []
|
|
45
|
+
|
|
46
|
+
for cluster in clusters:
|
|
47
|
+
cluster_findings: list[AuditFinding] = []
|
|
48
|
+
nodes = list(cluster)
|
|
49
|
+
for i, node1 in enumerate(nodes):
|
|
50
|
+
for node2 in nodes[i + 1 :]:
|
|
51
|
+
key = tuple(sorted((node1, node2)))
|
|
52
|
+
if key in finding_map:
|
|
53
|
+
cluster_findings.append(finding_map[key])
|
|
54
|
+
|
|
55
|
+
if cluster_findings:
|
|
56
|
+
cluster_findings.sort(
|
|
57
|
+
key=lambda f: float((f.context or {}).get("similarity", 0)),
|
|
58
|
+
reverse=True,
|
|
59
|
+
)
|
|
60
|
+
grouped_findings.append(cluster_findings)
|
|
61
|
+
|
|
62
|
+
return grouped_findings
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ID: 00ec62c1-ef50-4f17-aec6-460fe26a47d5
|
|
66
|
+
async def inspect_duplicates_async(context: CoreContext, threshold: float) -> None:
|
|
67
|
+
"""
|
|
68
|
+
The core async logic for running duplication analysis.
|
|
69
|
+
Uses the constitutional rule engine to identify duplicates.
|
|
70
|
+
"""
|
|
71
|
+
from mind.governance.rule_executor import execute_rule
|
|
72
|
+
from mind.governance.rule_extractor import extract_executable_rules
|
|
73
|
+
|
|
74
|
+
if context is None:
|
|
75
|
+
logger.error("Context not initialized for inspect duplicates")
|
|
76
|
+
raise ValueError("Context not initialized for inspect duplicates")
|
|
77
|
+
|
|
78
|
+
logger.info("🔍 Running duplication checks (threshold: %s)...", threshold)
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
repo_root = context.git_service.repo_path
|
|
82
|
+
auditor_context = context.auditor_context or AuditorContext(repo_root)
|
|
83
|
+
await auditor_context.load_knowledge_graph()
|
|
84
|
+
|
|
85
|
+
qdrant_service: QdrantService | None = context.qdrant_service
|
|
86
|
+
if qdrant_service is None and context.registry:
|
|
87
|
+
qdrant_service = await context.registry.get_qdrant_service()
|
|
88
|
+
context.qdrant_service = qdrant_service
|
|
89
|
+
|
|
90
|
+
if qdrant_service is None:
|
|
91
|
+
logger.warning(
|
|
92
|
+
"Qdrant service unavailable; semantic duplication check will be skipped."
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
auditor_context.qdrant_service = qdrant_service
|
|
96
|
+
|
|
97
|
+
all_rules = extract_executable_rules(
|
|
98
|
+
auditor_context.policies, auditor_context.enforcement_loader
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
logger.info("DEBUG: Loaded %d executable rules", len(all_rules))
|
|
102
|
+
purity_rules = [r for r in all_rules if r.rule_id.startswith("purity.")]
|
|
103
|
+
logger.info(
|
|
104
|
+
"DEBUG: Found %d purity.* rules: %s",
|
|
105
|
+
len(purity_rules),
|
|
106
|
+
[r.rule_id for r in purity_rules],
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
ast_rule = next(
|
|
110
|
+
(r for r in all_rules if r.rule_id == "purity.no_ast_duplication"),
|
|
111
|
+
None,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
semantic_rule = next(
|
|
115
|
+
(r for r in all_rules if r.rule_id == "purity.no_semantic_duplication"),
|
|
116
|
+
None,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
logger.info("DEBUG: ast_rule found: %s", ast_rule is not None)
|
|
120
|
+
logger.info("DEBUG: semantic_rule found: %s", semantic_rule is not None)
|
|
121
|
+
|
|
122
|
+
all_findings: list[AuditFinding] = []
|
|
123
|
+
|
|
124
|
+
if ast_rule:
|
|
125
|
+
logger.info("Running AST duplication check...")
|
|
126
|
+
ast_rule.params["threshold"] = threshold
|
|
127
|
+
ast_findings = await execute_rule(ast_rule, auditor_context)
|
|
128
|
+
all_findings.extend(ast_findings)
|
|
129
|
+
logger.info("AST check found %d duplicate pairs", len(ast_findings))
|
|
130
|
+
|
|
131
|
+
if semantic_rule and qdrant_service:
|
|
132
|
+
logger.info("Running semantic duplication check...")
|
|
133
|
+
semantic_rule.params["threshold"] = threshold
|
|
134
|
+
semantic_findings = await execute_rule(semantic_rule, auditor_context)
|
|
135
|
+
all_findings.extend(semantic_findings)
|
|
136
|
+
logger.info(
|
|
137
|
+
"Semantic check found %d duplicate pairs", len(semantic_findings)
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if not all_findings:
|
|
141
|
+
logger.info("✅ No significant duplicates found (threshold=%s).", threshold)
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
logger.info("⚠️ Found %s total duplication finding(s).", len(all_findings))
|
|
145
|
+
|
|
146
|
+
grouped = _group_findings(all_findings)
|
|
147
|
+
logger.info("Found %s logical cluster(s) of duplicated code:", len(grouped))
|
|
148
|
+
|
|
149
|
+
for idx, cluster_findings in enumerate(grouped, start=1):
|
|
150
|
+
logger.info("Cluster %s:", idx)
|
|
151
|
+
for finding in cluster_findings:
|
|
152
|
+
ctx = finding.context or {}
|
|
153
|
+
dup_type = ctx.get("type", "unknown")
|
|
154
|
+
logger.info(
|
|
155
|
+
" - [%s] %s <-> %s (similarity: %s)",
|
|
156
|
+
dup_type.upper(),
|
|
157
|
+
ctx.get("symbol_a", "???"),
|
|
158
|
+
ctx.get("symbol_b", "???"),
|
|
159
|
+
f"{ctx.get('similarity', 0):.2%}",
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
except Exception as exc:
|
|
163
|
+
logger.error("Duplication check failed: %s", exc)
|
|
164
|
+
logger.debug(traceback.format_exc())
|
|
165
|
+
raise
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# src/body/self_healing/handlers/__init__.py
|