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,521 @@
|
|
|
1
|
+
# src/body/atomic/modularity_splitter.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Deterministic modularization splitter.
|
|
5
|
+
|
|
6
|
+
Given a source file and a validated SplitPlan, produces a SplitResult
|
|
7
|
+
describing every file that *would* be written — without writing anything.
|
|
8
|
+
The Execution phase decides whether to persist.
|
|
9
|
+
|
|
10
|
+
Constitutional note:
|
|
11
|
+
Body layer — read-only. SplitResult is a proposal, not an action.
|
|
12
|
+
No settings access, no file writes.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import ast
|
|
18
|
+
from collections.abc import Iterable
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
from body.atomic.import_resolver import ImportResolver
|
|
23
|
+
from body.atomic.split_plan import ModuleSpec, SplitPlan, SplitPlanError
|
|
24
|
+
from shared.logger import getLogger
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
logger = getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Issue #213 / Failure 5 in CORE-ModularityLessons.md.
|
|
31
|
+
# Names that are public-by-syntax (no leading underscore) but private-by-
|
|
32
|
+
# convention. They must not be re-exported from a split package's
|
|
33
|
+
# __init__.py — doing so leaks implementation details (e.g. each module's
|
|
34
|
+
# logger instance) into the package's public API surface.
|
|
35
|
+
_PRIVATE_BY_CONVENTION: frozenset[str] = frozenset({"logger", "log", "_logger", "_log"})
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _filter_public_reexports(names: Iterable[str]) -> list[str]:
|
|
39
|
+
"""Drop underscore-prefixed and convention-private names from a re-export
|
|
40
|
+
symbol list. Used at every __init__.py emission site so both passes apply
|
|
41
|
+
the same predicate. See issue #213.
|
|
42
|
+
"""
|
|
43
|
+
return [
|
|
44
|
+
n for n in names if not n.startswith("_") and n not in _PRIVATE_BY_CONVENTION
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
# ID: 9b77fadf-6869-44bd-a1fd-12a8f24d830c
|
|
50
|
+
class SplitResult:
|
|
51
|
+
"""Describes the files a modularization split would produce."""
|
|
52
|
+
|
|
53
|
+
files: list[tuple[Path, str]] = field(default_factory=list)
|
|
54
|
+
original_path: Path = field(default_factory=lambda: Path())
|
|
55
|
+
package_path: Path = field(default_factory=lambda: Path())
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# ID: 6a9c0d1e-2f3b-4c5d-8e7f-0a1b2c3d4e5f
|
|
59
|
+
class ModularitySplitter:
|
|
60
|
+
"""Split a single source file into a package according to a SplitPlan.
|
|
61
|
+
|
|
62
|
+
All work is AST-based and deterministic. The returned SplitResult
|
|
63
|
+
contains *proposed* file contents; nothing is written to disk.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(self) -> None:
|
|
67
|
+
self._resolver = ImportResolver()
|
|
68
|
+
|
|
69
|
+
# ID: 4e7f8a9b-0c1d-2e3f-4a5b-6c7d8e9f0a1b
|
|
70
|
+
def split(self, source_path: Path, plan: SplitPlan) -> SplitResult:
|
|
71
|
+
"""Produce a SplitResult from *source_path* and a validated *plan*.
|
|
72
|
+
|
|
73
|
+
Parameters
|
|
74
|
+
----------
|
|
75
|
+
source_path:
|
|
76
|
+
Absolute path to the file being split.
|
|
77
|
+
plan:
|
|
78
|
+
A validated ``SplitPlan`` (caller must have called ``validate()``).
|
|
79
|
+
|
|
80
|
+
Returns
|
|
81
|
+
-------
|
|
82
|
+
SplitResult
|
|
83
|
+
Proposed files. Nothing is written to disk.
|
|
84
|
+
|
|
85
|
+
Raises
|
|
86
|
+
------
|
|
87
|
+
SplitPlanError
|
|
88
|
+
If a symbol listed in the plan cannot be found in the source AST.
|
|
89
|
+
"""
|
|
90
|
+
source = source_path.read_text(encoding="utf-8")
|
|
91
|
+
source_lines = source.splitlines(keepends=True)
|
|
92
|
+
tree = ast.parse(source)
|
|
93
|
+
|
|
94
|
+
package_path = source_path.parent / plan.new_package_name
|
|
95
|
+
|
|
96
|
+
# Build name → AST-node index for top-level definitions
|
|
97
|
+
top_level: dict[str, ast.stmt] = {}
|
|
98
|
+
for node in ast.iter_child_nodes(tree):
|
|
99
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
|
|
100
|
+
top_level[node.name] = node
|
|
101
|
+
|
|
102
|
+
# Also index top-level assignments (constants, module-level vars)
|
|
103
|
+
for node in ast.iter_child_nodes(tree):
|
|
104
|
+
if isinstance(node, ast.Assign):
|
|
105
|
+
for target in node.targets:
|
|
106
|
+
if isinstance(target, ast.Name):
|
|
107
|
+
top_level[target.id] = node
|
|
108
|
+
|
|
109
|
+
# Determine up-front whether the plan targets class members.
|
|
110
|
+
is_class_split_plan = any(m.is_class_split for m in plan.modules)
|
|
111
|
+
|
|
112
|
+
# Second indexing pass: detect the single-dominant-class case.
|
|
113
|
+
# If one top-level ClassDef contains more than half the total symbols
|
|
114
|
+
# in the plan, build a method-name → AST-node index for that class.
|
|
115
|
+
class_methods: dict[str, ast.stmt] = {}
|
|
116
|
+
dominant_class_name: str | None = None
|
|
117
|
+
class_defs = [
|
|
118
|
+
n for n in ast.iter_child_nodes(tree) if isinstance(n, ast.ClassDef)
|
|
119
|
+
]
|
|
120
|
+
total_plan_symbols = sum(len(m.symbols) for m in plan.modules)
|
|
121
|
+
if class_defs and total_plan_symbols > 0:
|
|
122
|
+
largest = max(
|
|
123
|
+
class_defs,
|
|
124
|
+
key=lambda c: sum(
|
|
125
|
+
1
|
|
126
|
+
for n in c.body
|
|
127
|
+
if isinstance(
|
|
128
|
+
n,
|
|
129
|
+
(
|
|
130
|
+
ast.FunctionDef,
|
|
131
|
+
ast.AsyncFunctionDef,
|
|
132
|
+
ast.AnnAssign,
|
|
133
|
+
ast.Assign,
|
|
134
|
+
),
|
|
135
|
+
)
|
|
136
|
+
),
|
|
137
|
+
)
|
|
138
|
+
largest_member_count = sum(
|
|
139
|
+
1
|
|
140
|
+
for n in largest.body
|
|
141
|
+
if isinstance(
|
|
142
|
+
n,
|
|
143
|
+
(ast.FunctionDef, ast.AsyncFunctionDef, ast.AnnAssign, ast.Assign),
|
|
144
|
+
)
|
|
145
|
+
)
|
|
146
|
+
if is_class_split_plan or 2 * largest_member_count > total_plan_symbols:
|
|
147
|
+
dominant_class_name = largest.name
|
|
148
|
+
for member in largest.body:
|
|
149
|
+
if isinstance(member, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
150
|
+
class_methods[member.name] = member
|
|
151
|
+
elif isinstance(member, ast.AnnAssign) and isinstance(
|
|
152
|
+
member.target, ast.Name
|
|
153
|
+
):
|
|
154
|
+
class_methods[member.target.id] = member
|
|
155
|
+
elif isinstance(member, ast.Assign):
|
|
156
|
+
for target in member.targets:
|
|
157
|
+
if isinstance(target, ast.Name):
|
|
158
|
+
class_methods[target.id] = member
|
|
159
|
+
|
|
160
|
+
# Build symbol → module_name map for cross-module resolution
|
|
161
|
+
symbol_to_module: dict[str, str] = {}
|
|
162
|
+
for mod in plan.modules:
|
|
163
|
+
for sym in mod.symbols:
|
|
164
|
+
symbol_to_module[sym] = mod.module_name
|
|
165
|
+
|
|
166
|
+
# Collect all module-level assignment names from original source
|
|
167
|
+
module_assigns: set[str] = set()
|
|
168
|
+
for node in ast.iter_child_nodes(tree):
|
|
169
|
+
if isinstance(node, ast.Assign):
|
|
170
|
+
for target in node.targets:
|
|
171
|
+
if isinstance(target, ast.Name):
|
|
172
|
+
module_assigns.add(target.id)
|
|
173
|
+
elif isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name):
|
|
174
|
+
module_assigns.add(node.target.id)
|
|
175
|
+
|
|
176
|
+
result = SplitResult(
|
|
177
|
+
files=[],
|
|
178
|
+
original_path=source_path,
|
|
179
|
+
package_path=package_path,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
init_lines: list[str] = [
|
|
183
|
+
f"# {plan.new_package_name}/__init__.py",
|
|
184
|
+
'"""',
|
|
185
|
+
f"Package split from {source_path.name}.",
|
|
186
|
+
'"""',
|
|
187
|
+
"",
|
|
188
|
+
"from __future__ import annotations",
|
|
189
|
+
"",
|
|
190
|
+
]
|
|
191
|
+
|
|
192
|
+
# ----- class-split branch ----------------------------------------
|
|
193
|
+
if is_class_split_plan:
|
|
194
|
+
# Order modules so that the one containing __init__ comes first;
|
|
195
|
+
# multiple inheritance MRO will use its constructor.
|
|
196
|
+
primary_idx = next(
|
|
197
|
+
(i for i, m in enumerate(plan.modules) if "__init__" in m.symbols),
|
|
198
|
+
0,
|
|
199
|
+
)
|
|
200
|
+
ordered = [plan.modules[primary_idx]] + [
|
|
201
|
+
m for i, m in enumerate(plan.modules) if i != primary_idx
|
|
202
|
+
]
|
|
203
|
+
|
|
204
|
+
parent_classes: list[str] = []
|
|
205
|
+
for mod in ordered:
|
|
206
|
+
content = self._build_module(
|
|
207
|
+
source,
|
|
208
|
+
source_lines,
|
|
209
|
+
tree,
|
|
210
|
+
top_level,
|
|
211
|
+
mod,
|
|
212
|
+
symbol_to_module,
|
|
213
|
+
class_methods=class_methods,
|
|
214
|
+
)
|
|
215
|
+
target = package_path / f"{mod.module_name}.py"
|
|
216
|
+
result.files.append((target, content))
|
|
217
|
+
|
|
218
|
+
class_name = self._to_title_case(mod.module_name)
|
|
219
|
+
init_lines.append(f"from .{mod.module_name} import {class_name}")
|
|
220
|
+
parent_classes.append(class_name)
|
|
221
|
+
|
|
222
|
+
# Re-export the original class name for backward compatibility
|
|
223
|
+
# by composing the new per-module classes via multiple inheritance.
|
|
224
|
+
if dominant_class_name and parent_classes:
|
|
225
|
+
init_lines.append("")
|
|
226
|
+
init_lines.append("")
|
|
227
|
+
init_lines.append(
|
|
228
|
+
f"class {dominant_class_name}({', '.join(parent_classes)}):"
|
|
229
|
+
)
|
|
230
|
+
init_lines.append(" pass")
|
|
231
|
+
|
|
232
|
+
init_lines.append("") # trailing newline
|
|
233
|
+
result.files.append((package_path / "__init__.py", "\n".join(init_lines)))
|
|
234
|
+
return result
|
|
235
|
+
|
|
236
|
+
# ----- regular (top-level symbol) branch -------------------------
|
|
237
|
+
plan_symbols: set[str] = set()
|
|
238
|
+
for mod in plan.modules:
|
|
239
|
+
plan_symbols.update(mod.symbols)
|
|
240
|
+
|
|
241
|
+
# Track which module first includes each module-level assignment
|
|
242
|
+
assign_to_first_module: dict[str, str] = {}
|
|
243
|
+
|
|
244
|
+
for mod in plan.modules:
|
|
245
|
+
content = self._build_module(
|
|
246
|
+
source, source_lines, tree, top_level, mod, symbol_to_module
|
|
247
|
+
)
|
|
248
|
+
target = package_path / f"{mod.module_name}.py"
|
|
249
|
+
result.files.append((target, content))
|
|
250
|
+
|
|
251
|
+
# __init__.py re-export line for plan symbols (issue #213:
|
|
252
|
+
# filter underscore-prefixed and convention-private names; skip
|
|
253
|
+
# the line entirely if filtering empties the symbol set,
|
|
254
|
+
# otherwise we'd emit malformed `from .mod import` syntax).
|
|
255
|
+
public_symbols = _filter_public_reexports(mod.symbols)
|
|
256
|
+
if public_symbols:
|
|
257
|
+
init_lines.append(
|
|
258
|
+
f"from .{mod.module_name} import {', '.join(public_symbols)}"
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
# Track module-level assigns referenced by this module's symbols
|
|
262
|
+
refs = self._collect_all_refs(top_level, mod.symbols)
|
|
263
|
+
for assign_name in module_assigns:
|
|
264
|
+
if (
|
|
265
|
+
assign_name in refs
|
|
266
|
+
and assign_name not in plan_symbols
|
|
267
|
+
and assign_name not in assign_to_first_module
|
|
268
|
+
):
|
|
269
|
+
assign_to_first_module[assign_name] = mod.module_name
|
|
270
|
+
|
|
271
|
+
# Re-export public module-level assignments in __init__.py (issue
|
|
272
|
+
# #213: same convention-private filter as plan-symbol pass; skip
|
|
273
|
+
# empty groups so we never emit a malformed `from .X import` line).
|
|
274
|
+
reexport_by_module: dict[str, list[str]] = {}
|
|
275
|
+
for name, mod_name in assign_to_first_module.items():
|
|
276
|
+
if name.startswith("_") or name in _PRIVATE_BY_CONVENTION:
|
|
277
|
+
continue
|
|
278
|
+
reexport_by_module.setdefault(mod_name, []).append(name)
|
|
279
|
+
|
|
280
|
+
for mod_name, names in sorted(reexport_by_module.items()):
|
|
281
|
+
if not names:
|
|
282
|
+
continue
|
|
283
|
+
init_lines.append(f"from .{mod_name} import {', '.join(sorted(names))}")
|
|
284
|
+
|
|
285
|
+
init_lines.append("") # trailing newline
|
|
286
|
+
result.files.append((package_path / "__init__.py", "\n".join(init_lines)))
|
|
287
|
+
|
|
288
|
+
return result
|
|
289
|
+
|
|
290
|
+
# ------------------------------------------------------------------
|
|
291
|
+
# Internal helpers
|
|
292
|
+
# ------------------------------------------------------------------
|
|
293
|
+
|
|
294
|
+
def _build_module(
|
|
295
|
+
self,
|
|
296
|
+
source: str,
|
|
297
|
+
source_lines: list[str],
|
|
298
|
+
tree: ast.Module,
|
|
299
|
+
top_level: dict[str, ast.stmt],
|
|
300
|
+
mod: ModuleSpec,
|
|
301
|
+
symbol_to_module: dict[str, str],
|
|
302
|
+
*,
|
|
303
|
+
class_methods: dict[str, ast.stmt] | None = None,
|
|
304
|
+
) -> str:
|
|
305
|
+
"""Compose the content for a single target module file."""
|
|
306
|
+
# Branch on is_class_split BEFORE choosing which index to use.
|
|
307
|
+
if mod.is_class_split:
|
|
308
|
+
symbol_index: dict[str, ast.stmt] = class_methods or {}
|
|
309
|
+
else:
|
|
310
|
+
symbol_index = top_level
|
|
311
|
+
|
|
312
|
+
# Validate that every symbol exists in the chosen index
|
|
313
|
+
missing = [s for s in mod.symbols if s not in symbol_index]
|
|
314
|
+
if missing:
|
|
315
|
+
raise SplitPlanError(f"Symbols not found in source AST: {missing}")
|
|
316
|
+
|
|
317
|
+
# Resolve imports
|
|
318
|
+
if mod.is_class_split:
|
|
319
|
+
method_nodes = [symbol_index[s] for s in mod.symbols]
|
|
320
|
+
import_lines = self._resolve_imports_for_methods(source, method_nodes)
|
|
321
|
+
# Methods reach each other via ``self.x``; no relative imports
|
|
322
|
+
cross_import_lines: list[str] = []
|
|
323
|
+
else:
|
|
324
|
+
import_lines = self._resolver.resolve(source, mod.symbols)
|
|
325
|
+
|
|
326
|
+
# Compute cross-module imports for symbols in other split modules
|
|
327
|
+
cross_imports: dict[str, set[str]] = {}
|
|
328
|
+
for sym_name in mod.symbols:
|
|
329
|
+
node = top_level[sym_name]
|
|
330
|
+
for child in ast.walk(node):
|
|
331
|
+
if isinstance(child, ast.Name) and child.id in symbol_to_module:
|
|
332
|
+
other_mod = symbol_to_module[child.id]
|
|
333
|
+
if other_mod != mod.module_name:
|
|
334
|
+
cross_imports.setdefault(other_mod, set()).add(child.id)
|
|
335
|
+
|
|
336
|
+
cross_import_lines = []
|
|
337
|
+
for other_mod, syms in sorted(cross_imports.items()):
|
|
338
|
+
cross_import_lines.append(
|
|
339
|
+
f"from .{other_mod} import {', '.join(sorted(syms))}"
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Extract symbol source text, preserving originals
|
|
343
|
+
symbol_blocks: list[str] = []
|
|
344
|
+
for sym_name in mod.symbols:
|
|
345
|
+
node = symbol_index[sym_name]
|
|
346
|
+
block = self._extract_node_source(node, source_lines)
|
|
347
|
+
symbol_blocks.append(block)
|
|
348
|
+
|
|
349
|
+
# Compose file
|
|
350
|
+
parts: list[str] = []
|
|
351
|
+
|
|
352
|
+
# Header comment
|
|
353
|
+
parts.append(f"# {mod.module_name}.py")
|
|
354
|
+
parts.append(f'"""{mod.rationale}"""')
|
|
355
|
+
parts.append("")
|
|
356
|
+
|
|
357
|
+
# External imports + module-level assignments
|
|
358
|
+
for imp in import_lines:
|
|
359
|
+
parts.append(imp)
|
|
360
|
+
|
|
361
|
+
# Cross-module relative imports
|
|
362
|
+
if cross_import_lines:
|
|
363
|
+
if import_lines:
|
|
364
|
+
parts.append("")
|
|
365
|
+
for line in cross_import_lines:
|
|
366
|
+
parts.append(line)
|
|
367
|
+
|
|
368
|
+
if import_lines or cross_import_lines:
|
|
369
|
+
parts.append("")
|
|
370
|
+
parts.append("")
|
|
371
|
+
|
|
372
|
+
# Symbol bodies — wrap in a class for class splits, otherwise emit
|
|
373
|
+
# them as top-level definitions.
|
|
374
|
+
if mod.is_class_split:
|
|
375
|
+
class_name = self._to_title_case(mod.module_name)
|
|
376
|
+
parts.append(f"class {class_name}:")
|
|
377
|
+
# Methods are already indented for class scope in the original
|
|
378
|
+
# source, so we keep their text verbatim.
|
|
379
|
+
parts.append("\n\n".join(symbol_blocks))
|
|
380
|
+
else:
|
|
381
|
+
parts.append("\n\n".join(symbol_blocks))
|
|
382
|
+
parts.append("") # trailing newline
|
|
383
|
+
|
|
384
|
+
return "\n".join(parts)
|
|
385
|
+
|
|
386
|
+
@staticmethod
|
|
387
|
+
def _to_title_case(snake: str) -> str:
|
|
388
|
+
"""Convert ``snake_case`` → ``TitleCase``."""
|
|
389
|
+
return "".join(part.capitalize() for part in snake.split("_") if part)
|
|
390
|
+
|
|
391
|
+
def _resolve_imports_for_methods(
|
|
392
|
+
self, source: str, method_nodes: list[ast.stmt]
|
|
393
|
+
) -> list[str]:
|
|
394
|
+
"""Resolve minimal imports needed by a set of class method nodes.
|
|
395
|
+
|
|
396
|
+
Mirrors :meth:`ImportResolver.resolve` but starts from arbitrary AST
|
|
397
|
+
nodes rather than top-level symbol names — required for class splits
|
|
398
|
+
where the "symbols" are methods nested inside a ClassDef.
|
|
399
|
+
"""
|
|
400
|
+
tree = ast.parse(source)
|
|
401
|
+
source_lines = source.splitlines(keepends=True)
|
|
402
|
+
|
|
403
|
+
# Collect top-level imports and any TYPE_CHECKING block
|
|
404
|
+
import_nodes: list[ast.stmt] = []
|
|
405
|
+
type_checking_block: list[ast.stmt] = []
|
|
406
|
+
for node in ast.iter_child_nodes(tree):
|
|
407
|
+
if isinstance(node, (ast.Import, ast.ImportFrom)):
|
|
408
|
+
import_nodes.append(node)
|
|
409
|
+
elif isinstance(node, ast.If) and self._resolver._is_type_checking_guard(
|
|
410
|
+
node
|
|
411
|
+
):
|
|
412
|
+
type_checking_block.append(node)
|
|
413
|
+
|
|
414
|
+
# Module-level assignments
|
|
415
|
+
module_assigns: dict[str, ast.stmt] = {}
|
|
416
|
+
for node in ast.iter_child_nodes(tree):
|
|
417
|
+
if isinstance(node, ast.Assign):
|
|
418
|
+
for target in node.targets:
|
|
419
|
+
if isinstance(target, ast.Name):
|
|
420
|
+
module_assigns[target.id] = node
|
|
421
|
+
elif isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name):
|
|
422
|
+
module_assigns[node.target.id] = node
|
|
423
|
+
|
|
424
|
+
# Classify imports
|
|
425
|
+
future_imports: list[str] = []
|
|
426
|
+
regular_imports: list[tuple[ast.stmt, str]] = []
|
|
427
|
+
for node in import_nodes:
|
|
428
|
+
stmt_text = self._resolver._node_source(node, source_lines)
|
|
429
|
+
if isinstance(node, ast.ImportFrom) and node.module == "__future__":
|
|
430
|
+
future_imports.append(stmt_text)
|
|
431
|
+
else:
|
|
432
|
+
regular_imports.append((node, stmt_text))
|
|
433
|
+
|
|
434
|
+
# Names referenced by the method bodies
|
|
435
|
+
needed_names: set[str] = set()
|
|
436
|
+
for mnode in method_nodes:
|
|
437
|
+
for child in ast.walk(mnode):
|
|
438
|
+
if isinstance(child, ast.Name):
|
|
439
|
+
needed_names.add(child.id)
|
|
440
|
+
elif isinstance(child, ast.Attribute):
|
|
441
|
+
root = self._resolver._attribute_root(child)
|
|
442
|
+
if root:
|
|
443
|
+
needed_names.add(root)
|
|
444
|
+
|
|
445
|
+
# Module-level assignments referenced by the method bodies
|
|
446
|
+
needed_assigns: dict[str, ast.stmt] = {}
|
|
447
|
+
for name, node in module_assigns.items():
|
|
448
|
+
if name in needed_names:
|
|
449
|
+
needed_assigns[name] = node
|
|
450
|
+
for node in needed_assigns.values():
|
|
451
|
+
for child in ast.walk(node):
|
|
452
|
+
if isinstance(child, ast.Name):
|
|
453
|
+
needed_names.add(child.id)
|
|
454
|
+
elif isinstance(child, ast.Attribute):
|
|
455
|
+
root = self._resolver._attribute_root(child)
|
|
456
|
+
if root:
|
|
457
|
+
needed_names.add(root)
|
|
458
|
+
|
|
459
|
+
# Match regular imports against expanded needed-name set
|
|
460
|
+
matched: list[str] = []
|
|
461
|
+
for node, stmt_text in regular_imports:
|
|
462
|
+
if self._resolver._import_provides(node, needed_names):
|
|
463
|
+
matched.append(stmt_text)
|
|
464
|
+
|
|
465
|
+
result: list[str] = list(future_imports)
|
|
466
|
+
if type_checking_block:
|
|
467
|
+
for block_node in type_checking_block:
|
|
468
|
+
result.append(self._resolver._node_source(block_node, source_lines))
|
|
469
|
+
result.extend(matched)
|
|
470
|
+
|
|
471
|
+
seen_lines: set[int] = set()
|
|
472
|
+
for node in needed_assigns.values():
|
|
473
|
+
if node.lineno not in seen_lines:
|
|
474
|
+
result.append("")
|
|
475
|
+
result.append(self._resolver._node_source(node, source_lines))
|
|
476
|
+
seen_lines.add(node.lineno)
|
|
477
|
+
|
|
478
|
+
return result
|
|
479
|
+
|
|
480
|
+
@staticmethod
|
|
481
|
+
def _collect_all_refs(
|
|
482
|
+
top_level: dict[str, ast.stmt], symbol_names: list[str]
|
|
483
|
+
) -> set[str]:
|
|
484
|
+
"""Collect all Name references from the bodies of *symbol_names*."""
|
|
485
|
+
refs: set[str] = set()
|
|
486
|
+
for sym_name in symbol_names:
|
|
487
|
+
node = top_level.get(sym_name)
|
|
488
|
+
if node is None:
|
|
489
|
+
continue
|
|
490
|
+
for child in ast.walk(node):
|
|
491
|
+
if isinstance(child, ast.Name):
|
|
492
|
+
refs.add(child.id)
|
|
493
|
+
return refs
|
|
494
|
+
|
|
495
|
+
def _extract_node_source(self, node: ast.stmt, source_lines: list[str]) -> str:
|
|
496
|
+
"""Extract the original source text of *node* including leading comments.
|
|
497
|
+
|
|
498
|
+
When *node* carries decorators, extraction starts at the first
|
|
499
|
+
decorator line so framework-registration decorators
|
|
500
|
+
(``@register_action``, ``@atomic_action``, …) survive a split.
|
|
501
|
+
``node.lineno`` points at the ``def``/``class`` line and would
|
|
502
|
+
silently drop the decorator block.
|
|
503
|
+
|
|
504
|
+
Preserves ``# ID:`` anchors that appear on the line before the
|
|
505
|
+
definition (above the decorator block when present) — required
|
|
506
|
+
by the constitutional symbol-ID rule.
|
|
507
|
+
"""
|
|
508
|
+
decorators: list[ast.expr] = getattr(node, "decorator_list", []) or []
|
|
509
|
+
if decorators:
|
|
510
|
+
start = decorators[0].lineno - 1 # 0-based
|
|
511
|
+
else:
|
|
512
|
+
start = node.lineno - 1
|
|
513
|
+
end = node.end_lineno if node.end_lineno is not None else node.lineno
|
|
514
|
+
|
|
515
|
+
# Look backwards for comment lines attached to this definition
|
|
516
|
+
# (e.g. ``# ID: ...`` or docstring preamble comments). With
|
|
517
|
+
# decorators present, this scans above the decorator block.
|
|
518
|
+
while start > 0 and source_lines[start - 1].strip().startswith("#"):
|
|
519
|
+
start -= 1
|
|
520
|
+
|
|
521
|
+
return "".join(source_lines[start:end]).rstrip()
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# src/body/atomic/proposal_lifecycle_actions.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Proposal lifecycle atomic actions. Per ADR-017, state mutations on
|
|
5
|
+
core.autonomous_proposals belong in governed atomic actions. This file
|
|
6
|
+
currently contains claim.proposal; future complete.proposal /
|
|
7
|
+
fail.proposal / approve.proposal / reject.proposal actions will live
|
|
8
|
+
here when the case for migrating them accumulates.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import time
|
|
14
|
+
from datetime import UTC, datetime
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
from uuid import UUID
|
|
17
|
+
|
|
18
|
+
from sqlalchemy import select, update
|
|
19
|
+
|
|
20
|
+
from body.atomic.registry import ActionCategory, register_action
|
|
21
|
+
from body.services.service_registry import service_registry
|
|
22
|
+
from shared.action_types import ActionImpact, ActionResult
|
|
23
|
+
from shared.atomic_action import atomic_action
|
|
24
|
+
from shared.logger import getLogger
|
|
25
|
+
from will.autonomy.proposal import ProposalStatus
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from shared.context import CoreContext
|
|
30
|
+
|
|
31
|
+
logger = getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@register_action(
|
|
35
|
+
action_id="claim.proposal",
|
|
36
|
+
description=(
|
|
37
|
+
"Atomically claim an approved proposal for execution under worker attribution"
|
|
38
|
+
),
|
|
39
|
+
category=ActionCategory.STATE,
|
|
40
|
+
policies=["rules/will/proposal_lifecycle"],
|
|
41
|
+
requires_db=True,
|
|
42
|
+
remediates=[],
|
|
43
|
+
)
|
|
44
|
+
@atomic_action(
|
|
45
|
+
action_id="claim.proposal",
|
|
46
|
+
intent="Atomically claim an approved proposal under worker attribution",
|
|
47
|
+
impact=ActionImpact.WRITE_DATA,
|
|
48
|
+
policies=["atomic_actions"],
|
|
49
|
+
)
|
|
50
|
+
# ID: 7d2f4a18-9c3e-4b50-8e21-3f6a5b8d1c04
|
|
51
|
+
async def action_claim_proposal(
|
|
52
|
+
core_context: CoreContext,
|
|
53
|
+
write: bool = False,
|
|
54
|
+
proposal_id: str | None = None,
|
|
55
|
+
claimed_by: UUID | None = None,
|
|
56
|
+
**kwargs,
|
|
57
|
+
) -> ActionResult:
|
|
58
|
+
"""Atomically claim an approved proposal for execution.
|
|
59
|
+
|
|
60
|
+
UPDATEs core.autonomous_proposals setting status='executing',
|
|
61
|
+
execution_started_at=NOW(), claimed_by=$claimed_by with a WHERE that
|
|
62
|
+
requires status='approved'. Single-claim atomicity rides on the
|
|
63
|
+
autonomous_proposals_executing_once partial unique index (ADR-017 D1).
|
|
64
|
+
|
|
65
|
+
write=False: read-only existence/status check; returns would_claim=True
|
|
66
|
+
on a row that could be claimed.
|
|
67
|
+
write=True: the UPDATE; rowcount==0 means lost-the-race or not-approved.
|
|
68
|
+
"""
|
|
69
|
+
start_time = time.time()
|
|
70
|
+
|
|
71
|
+
if not proposal_id:
|
|
72
|
+
return ActionResult(
|
|
73
|
+
action_id="claim.proposal",
|
|
74
|
+
ok=False,
|
|
75
|
+
data={"error": "proposal_id is required"},
|
|
76
|
+
duration_sec=time.time() - start_time,
|
|
77
|
+
)
|
|
78
|
+
if claimed_by is None:
|
|
79
|
+
return ActionResult(
|
|
80
|
+
action_id="claim.proposal",
|
|
81
|
+
ok=False,
|
|
82
|
+
data={"error": "claimed_by is required"},
|
|
83
|
+
duration_sec=time.time() - start_time,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
async with service_registry.session() as session:
|
|
88
|
+
from shared.infrastructure.database.models.autonomous_proposals import (
|
|
89
|
+
AutonomousProposal,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
if not write:
|
|
93
|
+
check_stmt = select(AutonomousProposal.proposal_id).where(
|
|
94
|
+
AutonomousProposal.proposal_id == proposal_id,
|
|
95
|
+
AutonomousProposal.status == ProposalStatus.APPROVED.value,
|
|
96
|
+
)
|
|
97
|
+
check_result = await session.execute(check_stmt)
|
|
98
|
+
if check_result.scalar_one_or_none() is None:
|
|
99
|
+
return ActionResult(
|
|
100
|
+
action_id="claim.proposal",
|
|
101
|
+
ok=False,
|
|
102
|
+
data={
|
|
103
|
+
"error": "proposal not found or not approved",
|
|
104
|
+
"proposal_id": proposal_id,
|
|
105
|
+
},
|
|
106
|
+
duration_sec=time.time() - start_time,
|
|
107
|
+
)
|
|
108
|
+
return ActionResult(
|
|
109
|
+
action_id="claim.proposal",
|
|
110
|
+
ok=True,
|
|
111
|
+
data={
|
|
112
|
+
"proposal_id": proposal_id,
|
|
113
|
+
"claimed_by": str(claimed_by),
|
|
114
|
+
"would_claim": True,
|
|
115
|
+
"dry_run": True,
|
|
116
|
+
},
|
|
117
|
+
duration_sec=time.time() - start_time,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
stmt = (
|
|
121
|
+
update(AutonomousProposal)
|
|
122
|
+
.where(
|
|
123
|
+
AutonomousProposal.proposal_id == proposal_id,
|
|
124
|
+
AutonomousProposal.status == ProposalStatus.APPROVED.value,
|
|
125
|
+
)
|
|
126
|
+
.values(
|
|
127
|
+
status=ProposalStatus.EXECUTING.value,
|
|
128
|
+
execution_started_at=datetime.now(UTC),
|
|
129
|
+
claimed_by=claimed_by,
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
result = await session.execute(stmt)
|
|
133
|
+
if result.rowcount == 0:
|
|
134
|
+
await session.rollback()
|
|
135
|
+
logger.warning(
|
|
136
|
+
"claim.proposal: %s already claimed or not approved",
|
|
137
|
+
proposal_id,
|
|
138
|
+
)
|
|
139
|
+
return ActionResult(
|
|
140
|
+
action_id="claim.proposal",
|
|
141
|
+
ok=False,
|
|
142
|
+
data={
|
|
143
|
+
"error": "proposal already claimed or not approved",
|
|
144
|
+
"proposal_id": proposal_id,
|
|
145
|
+
},
|
|
146
|
+
duration_sec=time.time() - start_time,
|
|
147
|
+
)
|
|
148
|
+
await session.commit()
|
|
149
|
+
logger.info("claim.proposal: claimed %s by %s", proposal_id, claimed_by)
|
|
150
|
+
return ActionResult(
|
|
151
|
+
action_id="claim.proposal",
|
|
152
|
+
ok=True,
|
|
153
|
+
data={
|
|
154
|
+
"proposal_id": proposal_id,
|
|
155
|
+
"claimed_by": str(claimed_by),
|
|
156
|
+
"claimed": True,
|
|
157
|
+
},
|
|
158
|
+
duration_sec=time.time() - start_time,
|
|
159
|
+
)
|
|
160
|
+
except Exception as e:
|
|
161
|
+
logger.exception("claim.proposal: failed for %s", proposal_id)
|
|
162
|
+
return ActionResult(
|
|
163
|
+
action_id="claim.proposal",
|
|
164
|
+
ok=False,
|
|
165
|
+
data={
|
|
166
|
+
"error": str(e),
|
|
167
|
+
"error_type": type(e).__name__,
|
|
168
|
+
"proposal_id": proposal_id,
|
|
169
|
+
},
|
|
170
|
+
duration_sec=time.time() - start_time,
|
|
171
|
+
)
|