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,182 @@
|
|
|
1
|
+
# src/shared/utils/embedding_utils.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Provides utilities for handling text embeddings, including chunking and aggregation.
|
|
5
|
+
|
|
6
|
+
CORE contract:
|
|
7
|
+
- "Embeddings" are produced by the Vectorizer role and are ALWAYS local.
|
|
8
|
+
- No provider switching (no OpenAI/DeepSeek here).
|
|
9
|
+
- No os.getenv/os.environ.
|
|
10
|
+
- No fallback chains. Missing required settings => error.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import asyncio
|
|
16
|
+
import hashlib
|
|
17
|
+
from typing import Protocol
|
|
18
|
+
|
|
19
|
+
import httpx
|
|
20
|
+
import numpy as np
|
|
21
|
+
|
|
22
|
+
from shared.config import settings
|
|
23
|
+
from shared.infrastructure.intent.operational_config import load_operational_config
|
|
24
|
+
from shared.logger import getLogger
|
|
25
|
+
from shared.utils.common_knowledge import normalize_text
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
logger = getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
_CFG_EMB = load_operational_config().embedding
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _require_setting(name: str) -> str:
|
|
34
|
+
"""
|
|
35
|
+
Strict settings read (CORE-style):
|
|
36
|
+
- only from shared.config.settings (+ model_extra if used as backing store)
|
|
37
|
+
- no fallback chains
|
|
38
|
+
- missing/empty => ValueError
|
|
39
|
+
"""
|
|
40
|
+
value = None
|
|
41
|
+
|
|
42
|
+
if hasattr(settings, name):
|
|
43
|
+
value = getattr(settings, name)
|
|
44
|
+
else:
|
|
45
|
+
extra = getattr(settings, "model_extra", {}) or {}
|
|
46
|
+
value = extra.get(name)
|
|
47
|
+
|
|
48
|
+
if value is None:
|
|
49
|
+
raise ValueError(f"Missing required setting: {name}")
|
|
50
|
+
if isinstance(value, str) and not value.strip():
|
|
51
|
+
raise ValueError(f"Setting '{name}' is empty")
|
|
52
|
+
|
|
53
|
+
return str(value)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ID: 0c956ad0-a9d9-4cdf-bc8d-af9bccc4e30c
|
|
57
|
+
class Embeddable(Protocol):
|
|
58
|
+
"""Defines the interface for any service that can create embeddings."""
|
|
59
|
+
|
|
60
|
+
# ID: 3ace367e-4136-4dd0-95b9-ec75462ff78d
|
|
61
|
+
async def get_embedding(self, text: str) -> list[float]: ...
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class _Adapter:
|
|
65
|
+
"""Internal adapter to make EmbeddingService conform to the Embeddable protocol."""
|
|
66
|
+
|
|
67
|
+
def __init__(self, service: Embeddable):
|
|
68
|
+
self._service = service
|
|
69
|
+
|
|
70
|
+
# ID: f6d67bd8-83e2-42d5-81d3-07c668642568
|
|
71
|
+
async def get_embedding(self, text: str) -> list[float]:
|
|
72
|
+
return await self._service.get_embedding(text)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _chunk_text(text: str, chunk_size: int, chunk_overlap: int) -> list[str]:
|
|
76
|
+
"""Splits text into overlapping chunks."""
|
|
77
|
+
if not text:
|
|
78
|
+
return []
|
|
79
|
+
chunks: list[str] = []
|
|
80
|
+
start = 0
|
|
81
|
+
while start < len(text):
|
|
82
|
+
end = start + chunk_size
|
|
83
|
+
chunks.append(text[start:end])
|
|
84
|
+
start += max(1, chunk_size - chunk_overlap)
|
|
85
|
+
return chunks
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# ID: 76aee7d7-fe49-4271-87b8-01fc9b074028
|
|
89
|
+
def sha256_hex(text: str) -> str:
|
|
90
|
+
"""Computes the SHA256 hex digest for a string."""
|
|
91
|
+
return hashlib.sha256(text.encode("utf-8")).hexdigest()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# ID: c3c32fe7-d434-43c6-b6a2-647afe213b4e
|
|
95
|
+
class EmbeddingService:
|
|
96
|
+
"""
|
|
97
|
+
Local-only embeddings client (Vectorizer role contract).
|
|
98
|
+
|
|
99
|
+
Expected settings (NO fallbacks):
|
|
100
|
+
- LOCAL_EMBEDDING_API_URL
|
|
101
|
+
- LOCAL_EMBEDDING_MODEL_NAME
|
|
102
|
+
|
|
103
|
+
Endpoint:
|
|
104
|
+
- POST {LOCAL_EMBEDDING_API_URL}/api/embed with {model, input} (Ollama 0.4+)
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
def __init__(self, timeout: float = _CFG_EMB.utils_request_timeout_sec) -> None:
|
|
108
|
+
self.base = _require_setting("LOCAL_EMBEDDING_API_URL").rstrip("/")
|
|
109
|
+
self.model = _require_setting("LOCAL_EMBEDDING_MODEL_NAME")
|
|
110
|
+
self.timeout = timeout
|
|
111
|
+
|
|
112
|
+
self.endpoint = "/api/embed"
|
|
113
|
+
self.headers: dict[str, str] = {"Content-Type": "application/json"}
|
|
114
|
+
|
|
115
|
+
logger.info(
|
|
116
|
+
"EmbeddingService initialized (local) base=%s model=%s",
|
|
117
|
+
self.base,
|
|
118
|
+
self.model,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# ID: b0db34ef-e89a-4910-b264-8e939cc14f9a
|
|
122
|
+
async def get_embedding(self, text: str) -> list[float]:
|
|
123
|
+
"""Return a single embedding vector for the given text."""
|
|
124
|
+
url = f"{self.base}{self.endpoint}"
|
|
125
|
+
payload = {"model": self.model, "input": text, "options": {"num_ctx": 8192}}
|
|
126
|
+
|
|
127
|
+
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
|
128
|
+
resp = await client.post(url, json=payload, headers=self.headers)
|
|
129
|
+
|
|
130
|
+
if resp.status_code != 200:
|
|
131
|
+
logger.error(
|
|
132
|
+
"HTTP error from local embedding API: %s - %s",
|
|
133
|
+
resp.status_code,
|
|
134
|
+
resp.text,
|
|
135
|
+
)
|
|
136
|
+
raise RuntimeError(f"Embedding API HTTP {resp.status_code}")
|
|
137
|
+
|
|
138
|
+
data = resp.json()
|
|
139
|
+
embeddings = data.get("embeddings")
|
|
140
|
+
if not embeddings or not embeddings[0]:
|
|
141
|
+
logger.error("Local embedding service returned no vector.")
|
|
142
|
+
raise RuntimeError("No vector returned from embedding service")
|
|
143
|
+
|
|
144
|
+
return embeddings[0]
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# ID: 14fd20cf-3101-4970-84b0-942ea9fffda3
|
|
148
|
+
def build_embedder_from_env() -> Embeddable:
|
|
149
|
+
"""
|
|
150
|
+
Backwards-compatible factory name.
|
|
151
|
+
|
|
152
|
+
CORE contract: this is settings-based and local-only.
|
|
153
|
+
"""
|
|
154
|
+
return _Adapter(EmbeddingService())
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
# ID: 31b34c50-e03b-4839-b588-d2a0c76a9004
|
|
158
|
+
async def chunk_and_embed(
|
|
159
|
+
embedder: Embeddable,
|
|
160
|
+
text: str,
|
|
161
|
+
chunk_size: int = _CFG_EMB.chunk_size,
|
|
162
|
+
chunk_overlap: int = _CFG_EMB.chunk_overlap,
|
|
163
|
+
) -> np.ndarray:
|
|
164
|
+
"""
|
|
165
|
+
Chunks text, gets embeddings for each chunk in parallel, and returns the
|
|
166
|
+
averaged embedding vector for the entire text.
|
|
167
|
+
"""
|
|
168
|
+
text = normalize_text(text)
|
|
169
|
+
chunks = _chunk_text(text, chunk_size, chunk_overlap)
|
|
170
|
+
if not chunks:
|
|
171
|
+
raise ValueError("Cannot generate embedding for empty text.")
|
|
172
|
+
|
|
173
|
+
chunk_vectors = await asyncio.gather(*(embedder.get_embedding(c) for c in chunks))
|
|
174
|
+
|
|
175
|
+
vector_array = np.array(chunk_vectors, dtype=np.float32)
|
|
176
|
+
mean_vector = np.mean(vector_array, axis=0)
|
|
177
|
+
|
|
178
|
+
norm = np.linalg.norm(mean_vector)
|
|
179
|
+
if norm == 0:
|
|
180
|
+
return mean_vector
|
|
181
|
+
|
|
182
|
+
return mean_vector / norm
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# src/shared/utils/glob_match.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Glob matching with gitignore semantics.
|
|
5
|
+
|
|
6
|
+
Single entry point for path-pattern evaluation across src/. Replaces
|
|
7
|
+
direct pathlib.Path.match() usage, which on Python 3.12 has two surprising
|
|
8
|
+
semantics that produced silent under-enforcement at security-sensitive
|
|
9
|
+
sites: ** is treated as single-segment *, and matching is suffix-only.
|
|
10
|
+
|
|
11
|
+
Per ADR-012, all in-scope src/ call sites use these helpers; the
|
|
12
|
+
audit_context.py compensation helpers (_include_matches, _is_excluded)
|
|
13
|
+
are out of scope for this ADR and migrate separately under issue #117.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from collections.abc import Iterable
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
from pathspec.patterns.gitignore.spec import GitIgnoreSpecPattern
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ID: 57255383-a41d-4c3e-b003-dd5ba8ce622f
|
|
25
|
+
def matches_glob(path: str | Path, pattern: str) -> bool:
|
|
26
|
+
"""
|
|
27
|
+
Test whether a path matches a glob pattern under gitignore semantics.
|
|
28
|
+
|
|
29
|
+
Uses pathspec's GitIgnoreSpecPattern. Patterns follow gitignore.5
|
|
30
|
+
conventions: leading or middle '/' anchors at root; '*' matches any
|
|
31
|
+
run of characters except '/'; '**' matches any number of path
|
|
32
|
+
segments including zero; trailing '/' restricts to directories.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
path: Path-like object or string. path inputs are treated as
|
|
36
|
+
repo-relative POSIX paths; absolute paths and ./ prefixes
|
|
37
|
+
are normalized to relative form. Converted to POSIX form for
|
|
38
|
+
consistent matching across platforms.
|
|
39
|
+
pattern: Glob pattern string. Empty patterns return False.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
True if the path matches the pattern, False otherwise.
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
>>> matches_glob("src/main.py", "src/**/*.py")
|
|
46
|
+
True
|
|
47
|
+
>>> matches_glob("src/api/sub/main.py", "src/**/*.py")
|
|
48
|
+
True
|
|
49
|
+
>>> matches_glob("var/secrets/k.txt", "**/secrets/**")
|
|
50
|
+
True
|
|
51
|
+
>>> matches_glob("var/secrets/k.txt", "secrets/*")
|
|
52
|
+
False
|
|
53
|
+
>>> matches_glob("/src/main.py", "src/**/*.py")
|
|
54
|
+
True
|
|
55
|
+
>>> matches_glob("./src/main.py", "src/**/*.py")
|
|
56
|
+
True
|
|
57
|
+
"""
|
|
58
|
+
if not pattern:
|
|
59
|
+
return False
|
|
60
|
+
|
|
61
|
+
if isinstance(path, Path):
|
|
62
|
+
path_str = path.as_posix()
|
|
63
|
+
else:
|
|
64
|
+
path_str = str(path).replace("\\", "/")
|
|
65
|
+
|
|
66
|
+
if path_str.startswith("./"):
|
|
67
|
+
path_str = path_str[2:]
|
|
68
|
+
path_str = path_str.lstrip("/")
|
|
69
|
+
|
|
70
|
+
compiled = GitIgnoreSpecPattern(pattern)
|
|
71
|
+
regex = compiled.regex
|
|
72
|
+
if regex is None:
|
|
73
|
+
return False
|
|
74
|
+
return bool(regex.match(path_str))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# ID: b5d94dcf-5791-41a0-834f-8b2aa25b32f2
|
|
78
|
+
def matches_any_glob(path: str | Path, patterns: Iterable[str]) -> bool:
|
|
79
|
+
"""
|
|
80
|
+
Test whether a path matches any of multiple glob patterns.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
path: Path-like object or string.
|
|
84
|
+
patterns: Iterable of pattern strings.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
True if the path matches at least one pattern.
|
|
88
|
+
|
|
89
|
+
Examples:
|
|
90
|
+
>>> matches_any_glob("var/secrets/k.txt", ["**/.env", "**/secrets/**"])
|
|
91
|
+
True
|
|
92
|
+
"""
|
|
93
|
+
return any(matches_glob(path, pat) for pat in patterns)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# src/shared/utils/header_tools.py
|
|
2
|
+
"""
|
|
3
|
+
Provides a deterministic tool for parsing and reconstructing Python file headers
|
|
4
|
+
according to CORE's constitutional style guide.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import ast
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
# ID: 4a498b02-ef0b-4ce2-bd66-d8289669cd8f
|
|
15
|
+
class HeaderComponents:
|
|
16
|
+
"""A data class to hold the parsed components of a Python file header."""
|
|
17
|
+
|
|
18
|
+
location: str | None = None
|
|
19
|
+
module_description: str | None = None
|
|
20
|
+
has_future_import: bool = False
|
|
21
|
+
other_imports: list[str] = field(default_factory=list)
|
|
22
|
+
body: list[str] = field(default_factory=list)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _HeaderTools:
|
|
26
|
+
"""A stateless utility class for parsing and reconstructing file headers."""
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
# ID: 8f8fa33d-1ab8-4ee8-8dc7-a71355167611
|
|
30
|
+
def parse(source_code: str) -> HeaderComponents:
|
|
31
|
+
"""Parses the source code and extracts header components."""
|
|
32
|
+
components = HeaderComponents()
|
|
33
|
+
lines = source_code.splitlines()
|
|
34
|
+
if not lines:
|
|
35
|
+
return components
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
tree = ast.parse(source_code)
|
|
39
|
+
except SyntaxError:
|
|
40
|
+
components.body = lines
|
|
41
|
+
return components
|
|
42
|
+
|
|
43
|
+
# Find the end of the header section (last docstring or import)
|
|
44
|
+
last_header_line = 0
|
|
45
|
+
header_nodes = []
|
|
46
|
+
for node in tree.body:
|
|
47
|
+
is_docstring = isinstance(node, ast.Expr) and isinstance(
|
|
48
|
+
node.value, ast.Constant
|
|
49
|
+
)
|
|
50
|
+
is_import = isinstance(node, (ast.Import, ast.ImportFrom))
|
|
51
|
+
if is_docstring or is_import:
|
|
52
|
+
# FIXED: Added null-safety for MyPy
|
|
53
|
+
node_end = getattr(node, "end_lineno", node.lineno)
|
|
54
|
+
last_header_line = node_end if node_end is not None else 0
|
|
55
|
+
header_nodes.append(node)
|
|
56
|
+
else:
|
|
57
|
+
# First non-header node marks the end of the header
|
|
58
|
+
break
|
|
59
|
+
|
|
60
|
+
# Body starts after the header, skipping blank lines
|
|
61
|
+
body_start_index = last_header_line
|
|
62
|
+
while body_start_index < len(lines) and not lines[body_start_index].strip():
|
|
63
|
+
body_start_index += 1
|
|
64
|
+
|
|
65
|
+
components.body = lines[body_start_index:]
|
|
66
|
+
|
|
67
|
+
# Process Header Content
|
|
68
|
+
if lines and lines[0].strip().startswith("#"):
|
|
69
|
+
components.location = lines[0]
|
|
70
|
+
|
|
71
|
+
# Extract docstring directly from source lines to preserve original quotes
|
|
72
|
+
docstring_node = (
|
|
73
|
+
tree.body[0] if tree.body and isinstance(tree.body[0], ast.Expr) else None
|
|
74
|
+
)
|
|
75
|
+
if (
|
|
76
|
+
docstring_node
|
|
77
|
+
and hasattr(docstring_node, "lineno")
|
|
78
|
+
and hasattr(docstring_node, "end_lineno")
|
|
79
|
+
):
|
|
80
|
+
# FIXED: Added null-safety for MyPy arithmetic
|
|
81
|
+
s_lineno = docstring_node.lineno
|
|
82
|
+
e_lineno = docstring_node.end_lineno
|
|
83
|
+
if s_lineno is not None and e_lineno is not None:
|
|
84
|
+
start_line = s_lineno - 1
|
|
85
|
+
end_line = e_lineno - 1
|
|
86
|
+
|
|
87
|
+
# Extract lines including quotes
|
|
88
|
+
docstring_lines = lines[start_line : end_line + 1]
|
|
89
|
+
|
|
90
|
+
# Preserve original formatting by joining lines
|
|
91
|
+
if docstring_lines:
|
|
92
|
+
# Detect if it's a multi-line docstring
|
|
93
|
+
first_line = docstring_lines[0].strip()
|
|
94
|
+
last_line = docstring_lines[-1].strip()
|
|
95
|
+
|
|
96
|
+
# Check if it starts and ends with quotes
|
|
97
|
+
if first_line.startswith(
|
|
98
|
+
('"""', "'''", '"', "'")
|
|
99
|
+
) and last_line.endswith(('"""', "'''", '"', "'")):
|
|
100
|
+
# For single-line docstrings
|
|
101
|
+
if len(docstring_lines) == 1:
|
|
102
|
+
components.module_description = docstring_lines[0].strip()
|
|
103
|
+
else:
|
|
104
|
+
# For multi-line docstrings, preserve all lines
|
|
105
|
+
# Find the indentation level
|
|
106
|
+
base_indent = len(docstring_lines[0]) - len(
|
|
107
|
+
docstring_lines[0].lstrip()
|
|
108
|
+
)
|
|
109
|
+
# Strip consistent indentation
|
|
110
|
+
stripped_lines = []
|
|
111
|
+
for line in docstring_lines:
|
|
112
|
+
if line.startswith(" " * base_indent):
|
|
113
|
+
stripped_lines.append(line[base_indent:])
|
|
114
|
+
else:
|
|
115
|
+
stripped_lines.append(line)
|
|
116
|
+
components.module_description = "\n".join(stripped_lines)
|
|
117
|
+
|
|
118
|
+
for node in header_nodes:
|
|
119
|
+
if isinstance(node, (ast.Import, ast.ImportFrom)):
|
|
120
|
+
import_line = ast.unparse(node)
|
|
121
|
+
if "from __future__ import annotations" in import_line:
|
|
122
|
+
components.has_future_import = True
|
|
123
|
+
else:
|
|
124
|
+
components.other_imports.append(import_line)
|
|
125
|
+
|
|
126
|
+
return components
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
# ID: e85d9dde-b46f-43f7-b83f-106a63103c48
|
|
130
|
+
def reconstruct(components: HeaderComponents) -> str:
|
|
131
|
+
"""Reconstructs the source code from its parsed components."""
|
|
132
|
+
parts = []
|
|
133
|
+
|
|
134
|
+
if components.location:
|
|
135
|
+
parts.append(components.location)
|
|
136
|
+
|
|
137
|
+
if components.module_description:
|
|
138
|
+
if parts and parts[-1].strip():
|
|
139
|
+
parts.append("")
|
|
140
|
+
parts.append(components.module_description)
|
|
141
|
+
|
|
142
|
+
imports_present = components.has_future_import or components.other_imports
|
|
143
|
+
if imports_present:
|
|
144
|
+
if parts and parts[-1].strip():
|
|
145
|
+
parts.append("")
|
|
146
|
+
|
|
147
|
+
if components.has_future_import:
|
|
148
|
+
parts.append("from __future__ import annotations")
|
|
149
|
+
|
|
150
|
+
if components.other_imports:
|
|
151
|
+
# Add a blank line between future import and other imports
|
|
152
|
+
if components.has_future_import:
|
|
153
|
+
parts.append("")
|
|
154
|
+
parts.extend(sorted(components.other_imports))
|
|
155
|
+
|
|
156
|
+
if components.body:
|
|
157
|
+
# If there was any header content, ensure two blank lines before the body
|
|
158
|
+
if parts:
|
|
159
|
+
while parts and not parts[-1].strip():
|
|
160
|
+
parts.pop()
|
|
161
|
+
parts.append("")
|
|
162
|
+
parts.append("")
|
|
163
|
+
|
|
164
|
+
# Remove leading and trailing blank lines from body
|
|
165
|
+
body_lines = components.body[:]
|
|
166
|
+
while body_lines and not body_lines[0].strip():
|
|
167
|
+
body_lines.pop(0)
|
|
168
|
+
while body_lines and not body_lines[-1].strip():
|
|
169
|
+
body_lines.pop()
|
|
170
|
+
|
|
171
|
+
parts.extend(body_lines)
|
|
172
|
+
|
|
173
|
+
return "\n".join(parts) + "\n"
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# Public alias to satisfy callers and tests expecting `HeaderTools`.
|
|
177
|
+
HeaderTools = _HeaderTools
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# src/shared/utils/parallel_processor.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Provides a reusable, throttled parallel processor for running async tasks
|
|
5
|
+
concurrently.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
from collections.abc import Awaitable, Callable
|
|
12
|
+
from typing import TypeVar
|
|
13
|
+
|
|
14
|
+
from shared.config import settings
|
|
15
|
+
from shared.logger import getLogger
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = getLogger(__name__)
|
|
19
|
+
T = TypeVar("T")
|
|
20
|
+
R = TypeVar("R")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# ID: 08955ac4-99b0-4bac-b3e4-3c9deb938e68
|
|
24
|
+
class ThrottledParallelProcessor:
|
|
25
|
+
"""
|
|
26
|
+
A dedicated executor for running a worker function over a list of items
|
|
27
|
+
in parallel, with concurrency limited by the constitution.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, description: str = "Processing items..."):
|
|
31
|
+
self.concurrency_limit = settings.CORE_MAX_CONCURRENT_REQUESTS
|
|
32
|
+
self.description = description
|
|
33
|
+
logger.info(
|
|
34
|
+
"ThrottledParallelProcessor initialized with concurrency limit: %s",
|
|
35
|
+
self.concurrency_limit,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
async def _process_items_async(
|
|
39
|
+
self, items: list[T], worker_fn: Callable[[T], Awaitable[R]]
|
|
40
|
+
) -> list[R]:
|
|
41
|
+
semaphore = asyncio.Semaphore(self.concurrency_limit)
|
|
42
|
+
results: list[R] = []
|
|
43
|
+
|
|
44
|
+
async def _worker(item: T) -> R:
|
|
45
|
+
async with semaphore:
|
|
46
|
+
return await worker_fn(item)
|
|
47
|
+
|
|
48
|
+
tasks = [asyncio.create_task(_worker(item)) for item in items]
|
|
49
|
+
|
|
50
|
+
logger.debug("%s", self.description)
|
|
51
|
+
for task in asyncio.as_completed(tasks):
|
|
52
|
+
results.append(await task)
|
|
53
|
+
|
|
54
|
+
return results
|
|
55
|
+
|
|
56
|
+
# ID: d64f09ac-d05d-4a32-ad5d-87bf95d0efcf
|
|
57
|
+
async def run_async(
|
|
58
|
+
self, items: list[T], worker_fn: Callable[[T], Awaitable[R]]
|
|
59
|
+
) -> list[R]:
|
|
60
|
+
return await self._process_items_async(items, worker_fn)
|
shared/utils/parsing.py
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# src/shared/utils/parsing.py
|
|
2
|
+
"""
|
|
3
|
+
Shared utilities for parsing structured data from unstructured text,
|
|
4
|
+
primarily from Large Language Model (LLM) outputs.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import ast
|
|
10
|
+
import json
|
|
11
|
+
import re
|
|
12
|
+
from typing import Any, cast
|
|
13
|
+
|
|
14
|
+
from shared.infrastructure.intent.operational_config import load_operational_config
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
_CFG = load_operational_config().parsing
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# ID: 03987fc0-13ec-460a-a399-a89c7289eac6
|
|
21
|
+
def extract_json_from_response(text: str) -> dict[Any, Any] | list[Any] | None:
|
|
22
|
+
"""
|
|
23
|
+
Extracts a JSON object or array from a raw text response, making it robust
|
|
24
|
+
against common LLM formatting issues like introductory text.
|
|
25
|
+
"""
|
|
26
|
+
# 1. Try to extract JSON from markdown code blocks
|
|
27
|
+
json_data = _extract_from_markdown(text)
|
|
28
|
+
if json_data is not None:
|
|
29
|
+
return cast(dict[Any, Any] | list[Any], json_data)
|
|
30
|
+
|
|
31
|
+
# 2. Fallback: Find raw JSON by matching braces/brackets
|
|
32
|
+
return cast(dict[Any, Any] | list[Any] | None, _extract_raw_json(text))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _extract_from_markdown(text: str) -> dict[Any, Any] | list[Any] | None:
|
|
36
|
+
pattern = r"```(?:json)?\s*(\{[\s\S]*?\}|\[[\s\S]*?\])\s*```"
|
|
37
|
+
match = re.search(pattern, text, re.DOTALL)
|
|
38
|
+
|
|
39
|
+
if not match:
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
return cast(dict[Any, Any] | list[Any], json.loads(match.group(1)))
|
|
44
|
+
except json.JSONDecodeError:
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _extract_raw_json(text: str) -> dict[Any, Any] | list[Any] | None:
|
|
49
|
+
first_brace = text.find("{")
|
|
50
|
+
first_bracket = text.find("[")
|
|
51
|
+
|
|
52
|
+
if first_brace == -1 and first_bracket == -1:
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
if first_brace != -1 and (first_bracket == -1 or first_brace < first_bracket):
|
|
56
|
+
end_char = "}"
|
|
57
|
+
start_index = first_brace
|
|
58
|
+
else:
|
|
59
|
+
end_char = "]"
|
|
60
|
+
start_index = first_bracket
|
|
61
|
+
|
|
62
|
+
last_index = text.rfind(end_char)
|
|
63
|
+
if last_index <= start_index:
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
json_str = text[start_index : last_index + 1]
|
|
68
|
+
return cast(dict[Any, Any] | list[Any], json.loads(json_str))
|
|
69
|
+
except (json.JSONDecodeError, ValueError):
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# ID: d4c82c76-0762-4358-b7b4-13d4819fce6c
|
|
74
|
+
def parse_write_blocks(text: str) -> dict[str, str]:
|
|
75
|
+
"""
|
|
76
|
+
Parses a string for one or more [[write:file_path]]...[[/write]] blocks.
|
|
77
|
+
"""
|
|
78
|
+
pattern = r"\[\[write:(.+?)\]\]\s*\n(.*?)\n\s*\[\[/write\]\]"
|
|
79
|
+
matches = re.findall(pattern, text, re.DOTALL)
|
|
80
|
+
return {path.strip(): content.strip() for path, content in matches}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _normalize_python_snippet(code: str) -> str:
|
|
84
|
+
"""
|
|
85
|
+
Normalize a Python snippet extracted from an LLM response.
|
|
86
|
+
"""
|
|
87
|
+
if not code:
|
|
88
|
+
return code
|
|
89
|
+
|
|
90
|
+
lines = code.splitlines()
|
|
91
|
+
if not lines:
|
|
92
|
+
return code
|
|
93
|
+
|
|
94
|
+
fixed_lines: list[str] = []
|
|
95
|
+
for idx, line in enumerate(lines):
|
|
96
|
+
if idx == 0:
|
|
97
|
+
stripped = line.lstrip()
|
|
98
|
+
if stripped.startswith(r"\n"):
|
|
99
|
+
stripped = stripped[2:]
|
|
100
|
+
if stripped.startswith("\\") and not stripped.startswith("\\\\"):
|
|
101
|
+
stripped = stripped.lstrip("\\")
|
|
102
|
+
fixed_lines.append(stripped)
|
|
103
|
+
else:
|
|
104
|
+
fixed_lines.append(line)
|
|
105
|
+
|
|
106
|
+
normalized = "\n".join(fixed_lines).strip()
|
|
107
|
+
try:
|
|
108
|
+
ast.parse(normalized)
|
|
109
|
+
return normalized
|
|
110
|
+
except SyntaxError:
|
|
111
|
+
return code
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _is_valid_python_block(code: str) -> bool:
|
|
115
|
+
"""
|
|
116
|
+
Heuristic check to see if a block contains actual Python logic.
|
|
117
|
+
Filters out blocks that are just comments or lack keywords.
|
|
118
|
+
"""
|
|
119
|
+
if not code or not code.strip():
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
lines = [line.strip() for line in code.splitlines() if line.strip()]
|
|
123
|
+
if not lines:
|
|
124
|
+
return False
|
|
125
|
+
|
|
126
|
+
# Reject if every line is a comment
|
|
127
|
+
if all(line.startswith("#") for line in lines):
|
|
128
|
+
return False
|
|
129
|
+
|
|
130
|
+
# Must contain at least one structural keyword
|
|
131
|
+
keywords = {
|
|
132
|
+
"def ",
|
|
133
|
+
"class ",
|
|
134
|
+
"import ",
|
|
135
|
+
"from ",
|
|
136
|
+
"@",
|
|
137
|
+
"async def ",
|
|
138
|
+
"return ",
|
|
139
|
+
"assert ",
|
|
140
|
+
}
|
|
141
|
+
return any(any(k in line for k in keywords) for line in lines)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# ID: 44c9f1bf-9a35-46d1-8059-f0d82b745a58
|
|
145
|
+
def extract_python_code_from_response(text: str) -> str | None:
|
|
146
|
+
"""
|
|
147
|
+
Extract Python code from an LLM response using a prioritized scoring strategy.
|
|
148
|
+
"""
|
|
149
|
+
if not text:
|
|
150
|
+
return None
|
|
151
|
+
|
|
152
|
+
candidates = []
|
|
153
|
+
|
|
154
|
+
pattern = r"```(\w*)\s*\n(.*?)\n\s*```"
|
|
155
|
+
matches = re.findall(pattern, text, re.DOTALL)
|
|
156
|
+
|
|
157
|
+
for lang, content in matches:
|
|
158
|
+
cleaned = content.strip()
|
|
159
|
+
if lang and lang.lower() not in ("python", "py", ""):
|
|
160
|
+
continue
|
|
161
|
+
|
|
162
|
+
if len(cleaned) > _CFG.min_block_len and _is_valid_python_block(cleaned):
|
|
163
|
+
candidates.append(cleaned)
|
|
164
|
+
|
|
165
|
+
if not candidates:
|
|
166
|
+
stripped = text.strip()
|
|
167
|
+
if _is_valid_python_block(stripped):
|
|
168
|
+
candidates.append(stripped)
|
|
169
|
+
|
|
170
|
+
if not candidates:
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
# ID: 46c042d9-977d-4567-9dff-4bb63bb042b0
|
|
174
|
+
def score_candidate(code: str) -> float:
|
|
175
|
+
score = 0.0
|
|
176
|
+
if "def test_" in code:
|
|
177
|
+
score += _CFG.score_test_fn
|
|
178
|
+
if "class Test" in code:
|
|
179
|
+
score += _CFG.score_test_class
|
|
180
|
+
if "import " in code or "from " in code:
|
|
181
|
+
score += _CFG.score_import
|
|
182
|
+
if "pytest" in code or "unittest" in code:
|
|
183
|
+
score += _CFG.score_pytest
|
|
184
|
+
score += min(len(code), 5000) / 10000.0
|
|
185
|
+
return score
|
|
186
|
+
|
|
187
|
+
candidates.sort(key=score_candidate, reverse=True)
|
|
188
|
+
|
|
189
|
+
return cast(str, _normalize_python_snippet(candidates[0]))
|