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,421 @@
|
|
|
1
|
+
# src/mind/logic/engines/ast_gate/checks/purity_checks.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Purity Checks - Deterministic AST-based enforcement.
|
|
5
|
+
|
|
6
|
+
CONSTITUTIONAL FIX (V2.3.0):
|
|
7
|
+
- Modularized to reduce Modularity Debt (49.9 -> ~36.0).
|
|
8
|
+
- Delegated Path/Domain resolution to 'ASTHelpers'.
|
|
9
|
+
- Compressed 'Intelligence Layer' heuristics into data-driven patterns.
|
|
10
|
+
- Preserves all 7 distinct constitutional check types.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import ast
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import ClassVar
|
|
18
|
+
|
|
19
|
+
from shared.infrastructure.intent.filesystem_operations import FsOperationTaxonomy
|
|
20
|
+
|
|
21
|
+
from ..base import ASTHelpers
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ID: 318924b3-cfe8-4ae2-a856-88deacf02a9b
|
|
25
|
+
class PurityChecks:
|
|
26
|
+
"""
|
|
27
|
+
Stateless collection of purity and standard enforcement checks.
|
|
28
|
+
|
|
29
|
+
Refactored to be a 'Thin Neuron' that delegates structural facts to ASTHelpers.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
_ID_ANCHOR_PREFIXES: ClassVar[tuple[str, ...]] = ("# ID:",)
|
|
33
|
+
|
|
34
|
+
@staticmethod
|
|
35
|
+
# ID: d0d9b1d6-5849-486a-9f77-8333f4fd75a4
|
|
36
|
+
def check_stable_id_anchor(source: str) -> list[str]:
|
|
37
|
+
"""Ensures all PUBLIC symbols have an '# ID:' anchor above them."""
|
|
38
|
+
violations = []
|
|
39
|
+
try:
|
|
40
|
+
tree = ast.parse(source)
|
|
41
|
+
lines = source.splitlines()
|
|
42
|
+
for node in ast.walk(tree):
|
|
43
|
+
if isinstance(
|
|
44
|
+
node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)
|
|
45
|
+
):
|
|
46
|
+
if node.name.startswith("_"):
|
|
47
|
+
continue
|
|
48
|
+
|
|
49
|
+
# Identifies line immediately above definition
|
|
50
|
+
idx = node.lineno - 2
|
|
51
|
+
if idx < 0 or not lines[idx].strip().startswith(
|
|
52
|
+
PurityChecks._ID_ANCHOR_PREFIXES
|
|
53
|
+
):
|
|
54
|
+
violations.append(
|
|
55
|
+
f"Public symbol '{node.name}' missing stable ID anchor (line {node.lineno})."
|
|
56
|
+
)
|
|
57
|
+
except Exception:
|
|
58
|
+
pass
|
|
59
|
+
return violations
|
|
60
|
+
|
|
61
|
+
@staticmethod
|
|
62
|
+
# ID: 4bd29d4a-63e7-4132-8ab2-16865c9d500c
|
|
63
|
+
def check_docstrings_present(tree: ast.AST) -> list[str]:
|
|
64
|
+
"""Flags public functions and classes whose body lacks a docstring."""
|
|
65
|
+
for node in ast.walk(tree):
|
|
66
|
+
for child in ast.iter_child_nodes(node):
|
|
67
|
+
child._parent = node # type: ignore[attr-defined]
|
|
68
|
+
|
|
69
|
+
violations: list[str] = []
|
|
70
|
+
for node in ast.walk(tree):
|
|
71
|
+
if not isinstance(
|
|
72
|
+
node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)
|
|
73
|
+
):
|
|
74
|
+
continue
|
|
75
|
+
if node.name.startswith("_"):
|
|
76
|
+
continue
|
|
77
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
78
|
+
parent = getattr(node, "_parent", None)
|
|
79
|
+
if isinstance(parent, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
80
|
+
continue
|
|
81
|
+
if ast.get_docstring(node) is None:
|
|
82
|
+
kind = "Class" if isinstance(node, ast.ClassDef) else "Function"
|
|
83
|
+
violations.append(
|
|
84
|
+
f"{kind} '{node.name}' has no docstring (line {node.lineno})."
|
|
85
|
+
)
|
|
86
|
+
return violations
|
|
87
|
+
|
|
88
|
+
@staticmethod
|
|
89
|
+
# ID: 1cc2a7f3-5e21-4c10-9f93-5d2b7bdb3a65
|
|
90
|
+
def check_forbidden_decorators(tree: ast.AST, forbidden: list[str]) -> list[str]:
|
|
91
|
+
"""Prevents use of obsolete metadata decorators in source code."""
|
|
92
|
+
violations, forbidden_set = [], {d.strip() for d in forbidden if d.strip()}
|
|
93
|
+
for node in ast.walk(tree):
|
|
94
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
95
|
+
for dec in node.decorator_list:
|
|
96
|
+
name = ASTHelpers.full_attr_name(dec)
|
|
97
|
+
if name in forbidden_set:
|
|
98
|
+
violations.append(
|
|
99
|
+
f"Forbidden decorator '{name}' on '{node.name}' (line {ASTHelpers.lineno(dec)})."
|
|
100
|
+
)
|
|
101
|
+
return violations
|
|
102
|
+
|
|
103
|
+
@staticmethod
|
|
104
|
+
# ID: 8d7c6b5a-4e3f-2d1c-0b9a-8f7e6d5c4b3a
|
|
105
|
+
def check_forbidden_primitives(
|
|
106
|
+
tree: ast.AST,
|
|
107
|
+
forbidden: list[str],
|
|
108
|
+
file_path: Path | None = None,
|
|
109
|
+
allowed_domains: list[str] | None = None,
|
|
110
|
+
) -> list[str]:
|
|
111
|
+
"""Check for dangerous primitives (eval/exec) with trust-zone awareness.
|
|
112
|
+
|
|
113
|
+
Matches both bare-name primitives (eval, exec) and dotted forms
|
|
114
|
+
(os.system, subprocess.Popen). Bare-import forms (e.g.
|
|
115
|
+
`from os import system; system(...)`) are also caught: callees are
|
|
116
|
+
resolved through the import alias map and the qualified form is
|
|
117
|
+
matched against the forbidden set. Closes the sibling of #488
|
|
118
|
+
explicitly called out in governance_basics.yaml.
|
|
119
|
+
"""
|
|
120
|
+
violations, forbidden_set = [], {p.strip() for p in forbidden if p.strip()}
|
|
121
|
+
|
|
122
|
+
if file_path and allowed_domains:
|
|
123
|
+
domain = ASTHelpers.extract_domain_from_path(file_path)
|
|
124
|
+
if ASTHelpers.domain_matches(domain, allowed_domains):
|
|
125
|
+
return []
|
|
126
|
+
|
|
127
|
+
alias_map = ASTHelpers.build_import_alias_map(tree)
|
|
128
|
+
for node in ast.walk(tree):
|
|
129
|
+
name = None
|
|
130
|
+
if isinstance(node, ast.Name):
|
|
131
|
+
if node.id in forbidden_set:
|
|
132
|
+
name = node.id
|
|
133
|
+
else:
|
|
134
|
+
# Bare-import resolution: `from os import system` makes
|
|
135
|
+
# Name("system") resolve to "os.system" via alias map.
|
|
136
|
+
resolved = alias_map.get(node.id)
|
|
137
|
+
if resolved and resolved in forbidden_set:
|
|
138
|
+
name = resolved
|
|
139
|
+
elif isinstance(node, ast.Attribute):
|
|
140
|
+
full = ASTHelpers.full_attr_name(node)
|
|
141
|
+
if full in forbidden_set:
|
|
142
|
+
name = full
|
|
143
|
+
else:
|
|
144
|
+
# Module-alias resolution: `import os as o; o.system()`
|
|
145
|
+
# resolves "o.system" -> "os.system".
|
|
146
|
+
resolved = ASTHelpers.resolve_qualified_name(node, alias_map)
|
|
147
|
+
if resolved and resolved != full and resolved in forbidden_set:
|
|
148
|
+
name = resolved
|
|
149
|
+
|
|
150
|
+
if name:
|
|
151
|
+
violations.append(
|
|
152
|
+
f"Forbidden primitive '{name}' used (line {ASTHelpers.lineno(node)})."
|
|
153
|
+
)
|
|
154
|
+
return violations
|
|
155
|
+
|
|
156
|
+
@staticmethod
|
|
157
|
+
# ID: 5425f58f-517d-4f2e-b0db-1c4638565b73
|
|
158
|
+
def check_no_print_statements(tree: ast.AST) -> list[str]:
|
|
159
|
+
"""Enforces standard logging over print()."""
|
|
160
|
+
return [
|
|
161
|
+
f"Line {ASTHelpers.lineno(n)}: Replace print() with logger."
|
|
162
|
+
for n in ast.walk(tree)
|
|
163
|
+
if isinstance(n, ast.Call) and ASTHelpers.full_attr_name(n.func) == "print"
|
|
164
|
+
]
|
|
165
|
+
|
|
166
|
+
@staticmethod
|
|
167
|
+
# ID: a4b3c2d1-e0f9-8e7d-6c5b-4a3f2e1d0c9b
|
|
168
|
+
def check_required_decorator(
|
|
169
|
+
tree: ast.AST, decorator: str, file_path: Path | None = None, **kwargs
|
|
170
|
+
) -> list[str]:
|
|
171
|
+
"""Ensures state-modifying functions use governance decorators (e.g., @atomic_action)."""
|
|
172
|
+
# SANCTUARY ZONE: Core infrastructure and low-level processors are exempt
|
|
173
|
+
if file_path:
|
|
174
|
+
p_str = str(file_path).replace("\\", "/")
|
|
175
|
+
if any(
|
|
176
|
+
x in p_str
|
|
177
|
+
for x in [
|
|
178
|
+
"shared/infrastructure",
|
|
179
|
+
"shared/processors",
|
|
180
|
+
"repositories/db",
|
|
181
|
+
]
|
|
182
|
+
):
|
|
183
|
+
return []
|
|
184
|
+
|
|
185
|
+
violations = []
|
|
186
|
+
# Heuristic: Functions with these tools/methods are considered 'Armed and Acting'
|
|
187
|
+
mutating_tools = {"session", "db", "file_handler", "fs", "repo_path"}
|
|
188
|
+
mutating_methods = {
|
|
189
|
+
"write",
|
|
190
|
+
"delete",
|
|
191
|
+
"create",
|
|
192
|
+
"save",
|
|
193
|
+
"persist",
|
|
194
|
+
"apply",
|
|
195
|
+
"commit",
|
|
196
|
+
"add",
|
|
197
|
+
"update",
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
for fn in ast.walk(tree):
|
|
201
|
+
if not isinstance(
|
|
202
|
+
fn, (ast.FunctionDef, ast.AsyncFunctionDef)
|
|
203
|
+
) or fn.name.startswith(("_", "test_")):
|
|
204
|
+
continue
|
|
205
|
+
|
|
206
|
+
# 1. Tool Check (Arguments)
|
|
207
|
+
args = {a.arg.lower() for a in [*fn.args.args, *fn.args.kwonlyargs]}
|
|
208
|
+
if not any(t in args for t in mutating_tools):
|
|
209
|
+
continue
|
|
210
|
+
|
|
211
|
+
# 2. Action Check (Calls)
|
|
212
|
+
is_acting = any(
|
|
213
|
+
isinstance(c, ast.Call)
|
|
214
|
+
and isinstance(c.func, ast.Attribute)
|
|
215
|
+
and c.func.attr in mutating_methods
|
|
216
|
+
for c in ast.walk(fn)
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
# 3. Decision: Flag if acting without the required decorator
|
|
220
|
+
if is_acting and not any(
|
|
221
|
+
ASTHelpers.full_attr_name(d) == decorator for d in fn.decorator_list
|
|
222
|
+
):
|
|
223
|
+
violations.append(
|
|
224
|
+
f"Function '{fn.name}' appears state-modifying but lacks @{decorator} (line {fn.lineno})."
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
return violations
|
|
228
|
+
|
|
229
|
+
@staticmethod
|
|
230
|
+
# ID: 2dd7a4b8-fc4e-468e-9a1a-315acb2b3d6f
|
|
231
|
+
def check_decorator_args(
|
|
232
|
+
tree: ast.AST, decorator: str, required_args: list[str]
|
|
233
|
+
) -> list[str]:
|
|
234
|
+
"""Validates that specific decorators are called with mandatory keyword arguments."""
|
|
235
|
+
violations, required_set = [], {a.strip() for a in required_args if a.strip()}
|
|
236
|
+
for node in ast.walk(tree):
|
|
237
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
238
|
+
for dec in node.decorator_list:
|
|
239
|
+
if isinstance(dec, ast.Call):
|
|
240
|
+
if (
|
|
241
|
+
name := ASTHelpers.full_attr_name(dec.func)
|
|
242
|
+
) == decorator or (name and name.split(".")[-1] == decorator):
|
|
243
|
+
present = {kw.arg for kw in dec.keywords if kw.arg}
|
|
244
|
+
missing = sorted(list(required_set - present))
|
|
245
|
+
if missing:
|
|
246
|
+
violations.append(
|
|
247
|
+
f"@{decorator} on '{node.name}' missing required args {missing} (line {node.lineno})."
|
|
248
|
+
)
|
|
249
|
+
return violations
|
|
250
|
+
|
|
251
|
+
@staticmethod
|
|
252
|
+
# ID: b7d320ba-ce8b-4274-8576-a254eeb58bd0
|
|
253
|
+
def check_no_direct_writes(
|
|
254
|
+
tree: ast.AST,
|
|
255
|
+
taxonomy: FsOperationTaxonomy,
|
|
256
|
+
) -> list[str]:
|
|
257
|
+
"""Enforces the 'Governed Mutation Surface' by blocking raw filesystem writes.
|
|
258
|
+
|
|
259
|
+
Derives the forbidden set from ``taxonomy.all_entries`` filtered by
|
|
260
|
+
``op_class == "write"``. Match mode is read per-entry from the
|
|
261
|
+
taxonomy: ``leaf`` matches ``n.func.attr`` (catches the
|
|
262
|
+
variable-receiver form, e.g. ``p.write_text()`` where ``p`` is a
|
|
263
|
+
Path); ``qualified`` matches the dotted form recovered via
|
|
264
|
+
``ASTHelpers.resolve_qualified_name`` (collision-safe for ambiguous
|
|
265
|
+
attribute names like ``replace`` and ``rename`` which would
|
|
266
|
+
otherwise fire on ``str.replace`` and similar). The ``write_mode``
|
|
267
|
+
predicate, when declared, filters ``open()`` to write/append modes
|
|
268
|
+
via ``_is_write_mode``.
|
|
269
|
+
|
|
270
|
+
Star imports and dynamic imports remain out of reach (#488). The
|
|
271
|
+
variable-receiver bypass for the qualified-only leaves
|
|
272
|
+
(``p.replace(...)``, ``p.rename(...)``) is a pre-existing,
|
|
273
|
+
deliberately-accepted gap — leaf-match would collide with
|
|
274
|
+
``str.replace`` (143 src/ sites); see #489 migration trap.
|
|
275
|
+
|
|
276
|
+
ADR-077 §6 step 3 convergence (#489) — replaces the previous
|
|
277
|
+
hardcoded baseline + per-mapping ``forbidden_additional`` shape.
|
|
278
|
+
"""
|
|
279
|
+
write_entries = [e for e in taxonomy.all_entries if e.op_class == "write"]
|
|
280
|
+
leaf_entries = {e.name: e for e in write_entries if e.match == "leaf"}
|
|
281
|
+
# Qualified-match detection is sourced from the watched block only.
|
|
282
|
+
# pathlib_path qualified entries (`replace`, `rename`) exist for §3
|
|
283
|
+
# completeness compliance; their bare leaf names would otherwise
|
|
284
|
+
# match unrelated calls like `text.replace(...)` via
|
|
285
|
+
# full_attr_name's fallback to `node.attr` for unresolvable value
|
|
286
|
+
# chains. See #489 migration trap.
|
|
287
|
+
qualified_entries = {
|
|
288
|
+
e.name: e
|
|
289
|
+
for e in write_entries
|
|
290
|
+
if e.match == "qualified" and e.namespace == "watched"
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
alias_map = ASTHelpers.build_import_alias_map(tree)
|
|
294
|
+
violations: list[str] = []
|
|
295
|
+
|
|
296
|
+
for n in ast.walk(tree):
|
|
297
|
+
if not isinstance(n, ast.Call):
|
|
298
|
+
continue
|
|
299
|
+
|
|
300
|
+
attr_leaf = n.func.attr if isinstance(n.func, ast.Attribute) else None
|
|
301
|
+
qualified = ASTHelpers.resolve_qualified_name(n.func, alias_map)
|
|
302
|
+
|
|
303
|
+
candidates: list[tuple[str, str]] = []
|
|
304
|
+
if attr_leaf and attr_leaf in leaf_entries:
|
|
305
|
+
candidates.append((leaf_entries[attr_leaf].predicate or "", attr_leaf))
|
|
306
|
+
if qualified and qualified in qualified_entries:
|
|
307
|
+
candidates.append(
|
|
308
|
+
(qualified_entries[qualified].predicate or "", qualified)
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
for predicate, display in candidates:
|
|
312
|
+
if predicate == "write_mode" and not _is_write_mode(n):
|
|
313
|
+
continue
|
|
314
|
+
violations.append(
|
|
315
|
+
f"Direct write detected: '{display}' "
|
|
316
|
+
f"(line {ASTHelpers.lineno(n)}). Use FileHandler."
|
|
317
|
+
)
|
|
318
|
+
break
|
|
319
|
+
|
|
320
|
+
return violations
|
|
321
|
+
|
|
322
|
+
@staticmethod
|
|
323
|
+
# ID: f3a1c2d4-7e8b-4f9a-b6c5-2d3e4f5a6b7c
|
|
324
|
+
def check_forbidden_imports_and_calls(
|
|
325
|
+
tree: ast.AST,
|
|
326
|
+
forbidden_imports: list[str],
|
|
327
|
+
forbidden_calls: list[str],
|
|
328
|
+
) -> list[str]:
|
|
329
|
+
"""
|
|
330
|
+
Enforces architecture.channels rules by blocking terminal-rendering primitives
|
|
331
|
+
in non-UI modules.
|
|
332
|
+
|
|
333
|
+
Detects:
|
|
334
|
+
- Forbidden module imports (e.g. 'rich.console', 'rich.table')
|
|
335
|
+
- Forbidden call expressions (e.g. 'Console()', 'console.print()', 'Table()')
|
|
336
|
+
"""
|
|
337
|
+
violations: list[str] = []
|
|
338
|
+
forbidden_import_set = {m.strip() for m in forbidden_imports if m.strip()}
|
|
339
|
+
forbidden_call_set = {c.strip() for c in forbidden_calls if c.strip()}
|
|
340
|
+
|
|
341
|
+
for node in ast.walk(tree):
|
|
342
|
+
# Check imports: `import rich.console` or `from rich.console import ...`
|
|
343
|
+
if isinstance(node, ast.Import):
|
|
344
|
+
for alias in node.names:
|
|
345
|
+
if alias.name in forbidden_import_set:
|
|
346
|
+
violations.append(
|
|
347
|
+
f"Line {node.lineno}: Forbidden import '{alias.name}'."
|
|
348
|
+
)
|
|
349
|
+
elif isinstance(node, ast.ImportFrom) and node.module:
|
|
350
|
+
if node.module in forbidden_import_set:
|
|
351
|
+
violations.append(
|
|
352
|
+
f"Line {node.lineno}: Forbidden import-from '{node.module}'."
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
# Check calls: Console(), console.print(), Table(), etc.
|
|
356
|
+
elif isinstance(node, ast.Call):
|
|
357
|
+
name = ASTHelpers.full_attr_name(node.func)
|
|
358
|
+
if name in forbidden_call_set:
|
|
359
|
+
violations.append(
|
|
360
|
+
f"Line {ASTHelpers.lineno(node)}: Forbidden call '{name}()'."
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
return violations
|
|
364
|
+
|
|
365
|
+
_TEMPFILE_REQUIRES_DIR: ClassVar[frozenset[str]] = frozenset(
|
|
366
|
+
{
|
|
367
|
+
"tempfile.TemporaryDirectory",
|
|
368
|
+
"tempfile.NamedTemporaryFile",
|
|
369
|
+
"tempfile.mkdtemp",
|
|
370
|
+
"tempfile.mkstemp",
|
|
371
|
+
}
|
|
372
|
+
)
|
|
373
|
+
_TEMPFILE_FORBIDDEN: ClassVar[frozenset[str]] = frozenset({"tempfile.gettempdir"})
|
|
374
|
+
|
|
375
|
+
@staticmethod
|
|
376
|
+
# ID: 3b685f57-0f85-4e12-b21d-d86a9d76bd41
|
|
377
|
+
def check_tempfile_default_dir(tree: ast.AST) -> list[str]:
|
|
378
|
+
"""Detect tempfile.* calls that resolve to /tmp/.
|
|
379
|
+
|
|
380
|
+
Without an explicit `dir=` kwarg, tempfile.TemporaryDirectory,
|
|
381
|
+
NamedTemporaryFile, mkdtemp, and mkstemp fall through to
|
|
382
|
+
tempfile.gettempdir(), which is /tmp/ on Linux — prohibited by
|
|
383
|
+
CLAUDE.md. tempfile.gettempdir() is forbidden outright.
|
|
384
|
+
|
|
385
|
+
The check only verifies that `dir=` is *present*; the kwarg's value
|
|
386
|
+
is not statically validated. This is sound for the four real-world
|
|
387
|
+
siblings closed by #508 and matches how other purity rules trust
|
|
388
|
+
present-but-unverified kwargs (e.g. write_defaults_false).
|
|
389
|
+
"""
|
|
390
|
+
violations: list[str] = []
|
|
391
|
+
alias_map = ASTHelpers.build_import_alias_map(tree)
|
|
392
|
+
for node in ast.walk(tree):
|
|
393
|
+
if not isinstance(node, ast.Call):
|
|
394
|
+
continue
|
|
395
|
+
callee = ASTHelpers.full_attr_name(node.func)
|
|
396
|
+
resolved = ASTHelpers.resolve_qualified_name(node.func, alias_map) or callee
|
|
397
|
+
if resolved in PurityChecks._TEMPFILE_FORBIDDEN:
|
|
398
|
+
violations.append(
|
|
399
|
+
f"Line {ASTHelpers.lineno(node)}: '{resolved}()' is forbidden — "
|
|
400
|
+
"the system temp dir is prohibited by CLAUDE.md; use an explicit "
|
|
401
|
+
"repo-internal path under var/tmp/ instead."
|
|
402
|
+
)
|
|
403
|
+
elif resolved in PurityChecks._TEMPFILE_REQUIRES_DIR:
|
|
404
|
+
has_dir_kwarg = any(kw.arg == "dir" for kw in node.keywords)
|
|
405
|
+
if not has_dir_kwarg:
|
|
406
|
+
violations.append(
|
|
407
|
+
f"Line {ASTHelpers.lineno(node)}: '{resolved}' must pass an "
|
|
408
|
+
"explicit `dir=` keyword pointing under repo_root/var/tmp/ "
|
|
409
|
+
"(CLAUDE.md /tmp/ prohibition)."
|
|
410
|
+
)
|
|
411
|
+
return violations
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def _is_write_mode(node: ast.Call) -> bool:
|
|
415
|
+
"""Internal helper to detect 'w' or 'a' in file open() calls."""
|
|
416
|
+
# Check positional arguments and keyword 'mode' argument
|
|
417
|
+
for arg in node.args + [k.value for k in node.keywords if k.arg == "mode"]:
|
|
418
|
+
if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
|
|
419
|
+
if any(m in arg.value for m in "wa"):
|
|
420
|
+
return True
|
|
421
|
+
return False
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# src/mind/logic/engines/ast_gate/checks/purity_enforcement_check.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Enforces code purity rules via AST analysis.
|
|
5
|
+
|
|
6
|
+
Rules enforced:
|
|
7
|
+
- purity.stable_id_anchor: Public symbols must have # ID: <uuid> anchors
|
|
8
|
+
- purity.forbidden_decorators: No @capability, @meta, @owner decorators
|
|
9
|
+
- purity.forbidden_primitives: No eval/exec/compile/__import__ primitives
|
|
10
|
+
|
|
11
|
+
Ref: .intent/policies/code/purity.json
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import ClassVar
|
|
18
|
+
|
|
19
|
+
from mind.governance.checks.rule_enforcement_check import RuleEnforcementCheck
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
PURITY_POLICY = Path(".intent/policies/code/purity.json")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# ID: f9e2d7c5-8b4a-6e1f-3d9c-2a7b5e8f4c1d
|
|
26
|
+
class PurityEnforcementCheck(RuleEnforcementCheck):
|
|
27
|
+
"""
|
|
28
|
+
Enforces purity rules through AST-based constitutional checks.
|
|
29
|
+
|
|
30
|
+
These rules are enforced by ast_gate engine with specific check_types.
|
|
31
|
+
The engine handles the actual verification logic.
|
|
32
|
+
|
|
33
|
+
Why AST instead of LLM:
|
|
34
|
+
- Deterministic (no model variance)
|
|
35
|
+
- Fast (no API calls)
|
|
36
|
+
- Precise (exact pattern matching)
|
|
37
|
+
- Cacheable (same code = same result)
|
|
38
|
+
|
|
39
|
+
Ref: .intent/policies/code/purity.json
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
policy_rule_ids: ClassVar[list[str]] = [
|
|
43
|
+
"purity.stable_id_anchor",
|
|
44
|
+
"purity.forbidden_decorators",
|
|
45
|
+
"purity.forbidden_primitives",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
policy_file: ClassVar[Path] = PURITY_POLICY
|
|
49
|
+
|
|
50
|
+
# These rules are enforced via ast_gate engine dispatch
|
|
51
|
+
# No enforcement_methods needed - engine handles verification
|
|
52
|
+
enforcement_methods: ClassVar[list] = []
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def _is_concrete_check(self) -> bool:
|
|
56
|
+
return True
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# src/mind/logic/engines/ast_gate/checks/runtime_import_boundary.py
|
|
2
|
+
"""
|
|
3
|
+
Runtime Import Boundary Check — forbids cross-layer runtime imports.
|
|
4
|
+
|
|
5
|
+
Constitutional purpose:
|
|
6
|
+
Enforces layer-separation rules (mind/no_body_invocation,
|
|
7
|
+
will/no_database_access, shared/no_layer_imports, etc.) by detecting
|
|
8
|
+
forbidden imports at module top level and inside function bodies —
|
|
9
|
+
i.e. imports that actually run at process start or call time, creating
|
|
10
|
+
real layer coupling.
|
|
11
|
+
|
|
12
|
+
Type-level proprioception is allowed by default:
|
|
13
|
+
imports inside `if TYPE_CHECKING:` blocks are erased at runtime and do
|
|
14
|
+
not create execution coupling. The check skips them so that mind can
|
|
15
|
+
*know* a body type's name (for annotations) without *invoking* the body
|
|
16
|
+
module. Set ``params.type_checking_exempt: false`` to disable this
|
|
17
|
+
exemption for strict rules that must forbid even type-level references.
|
|
18
|
+
|
|
19
|
+
Renamed from ``import_boundary`` (issue #490, ADR-077). The previous
|
|
20
|
+
name described the mechanism (looks at imports); this one declares the
|
|
21
|
+
constitutional intent (forbids runtime invocation, allows proprioception).
|
|
22
|
+
The ``type_checking_exempt`` parameter is now visible in the rule YAML
|
|
23
|
+
rather than hidden in engine behaviour.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import ast
|
|
29
|
+
from typing import TYPE_CHECKING
|
|
30
|
+
|
|
31
|
+
from mind.logic.engines.ast_gate.base import ASTHelpers
|
|
32
|
+
from mind.logic.engines.base import EngineResult
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if TYPE_CHECKING:
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ID: 7f4a9b2c-8e1d-4f3a-9c2d-6b5e8a7f4c1d
|
|
40
|
+
class RuntimeImportBoundaryCheck:
|
|
41
|
+
"""
|
|
42
|
+
Detects forbidden runtime cross-layer imports.
|
|
43
|
+
|
|
44
|
+
Configuration (from YAML):
|
|
45
|
+
check_type: runtime_import_boundary
|
|
46
|
+
params:
|
|
47
|
+
forbidden:
|
|
48
|
+
- "src.body"
|
|
49
|
+
- "body"
|
|
50
|
+
type_checking_exempt: true # default; set false for strict rules
|
|
51
|
+
|
|
52
|
+
The ``type_checking_exempt`` flag controls whether imports inside
|
|
53
|
+
``if TYPE_CHECKING:`` blocks are skipped. Default true matches the
|
|
54
|
+
Kubernetes/mypy/OPA convention: type hints don't create runtime
|
|
55
|
+
coupling, so they don't violate runtime-invocation rules.
|
|
56
|
+
|
|
57
|
+
Set to false only for rules whose constitutional intent is to forbid
|
|
58
|
+
even compile-time references (e.g. "no part of mind shall name a
|
|
59
|
+
secrets-handling type, even in annotations"). No current CORE rule
|
|
60
|
+
needs this; the flag exists so the convention is configurable rather
|
|
61
|
+
than hardcoded.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
# ID: a3f7c9e1-4b2d-5e8f-a1c6-d9f4e7b2a8c3
|
|
66
|
+
def check(
|
|
67
|
+
filepath: Path,
|
|
68
|
+
tree: ast.Module,
|
|
69
|
+
params: dict,
|
|
70
|
+
) -> EngineResult:
|
|
71
|
+
"""Detect forbidden runtime imports based on constitutional boundaries."""
|
|
72
|
+
forbidden_patterns = params.get("forbidden", [])
|
|
73
|
+
if not forbidden_patterns:
|
|
74
|
+
return EngineResult(
|
|
75
|
+
ok=False,
|
|
76
|
+
message="runtime_import_boundary check requires 'forbidden' parameter",
|
|
77
|
+
violations=["Configuration error: no forbidden imports specified"],
|
|
78
|
+
engine_id="ast_gate:runtime_import_boundary",
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
type_checking_exempt = params.get("type_checking_exempt", True)
|
|
82
|
+
|
|
83
|
+
if type_checking_exempt:
|
|
84
|
+
type_checking_nodes = RuntimeImportBoundaryCheck._find_type_checking_blocks(
|
|
85
|
+
tree
|
|
86
|
+
)
|
|
87
|
+
else:
|
|
88
|
+
type_checking_nodes = set()
|
|
89
|
+
|
|
90
|
+
violations = []
|
|
91
|
+
|
|
92
|
+
for node in ast.walk(tree):
|
|
93
|
+
if node in type_checking_nodes:
|
|
94
|
+
continue
|
|
95
|
+
|
|
96
|
+
if isinstance(node, ast.ImportFrom):
|
|
97
|
+
violation = RuntimeImportBoundaryCheck._check_import_from(
|
|
98
|
+
node, forbidden_patterns, filepath
|
|
99
|
+
)
|
|
100
|
+
if violation:
|
|
101
|
+
violations.append(violation)
|
|
102
|
+
|
|
103
|
+
elif isinstance(node, ast.Import):
|
|
104
|
+
violation = RuntimeImportBoundaryCheck._check_import(
|
|
105
|
+
node, forbidden_patterns, filepath
|
|
106
|
+
)
|
|
107
|
+
if violation:
|
|
108
|
+
violations.append(violation)
|
|
109
|
+
|
|
110
|
+
if violations:
|
|
111
|
+
return EngineResult(
|
|
112
|
+
ok=False,
|
|
113
|
+
message=f"Detected {len(violations)} forbidden runtime cross-layer imports",
|
|
114
|
+
violations=violations,
|
|
115
|
+
engine_id="ast_gate:runtime_import_boundary",
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
return EngineResult(
|
|
119
|
+
ok=True,
|
|
120
|
+
message="No forbidden runtime imports detected",
|
|
121
|
+
violations=[],
|
|
122
|
+
engine_id="ast_gate:runtime_import_boundary",
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
@staticmethod
|
|
126
|
+
# ID: e5f9a2c7-d3b6-8e4f-c1a5-f7d2e9b4a6c8
|
|
127
|
+
def _find_type_checking_blocks(tree: ast.Module) -> set[ast.AST]:
|
|
128
|
+
"""Return the set of AST nodes inside ``if TYPE_CHECKING:`` blocks."""
|
|
129
|
+
type_checking_nodes: set[ast.AST] = set()
|
|
130
|
+
|
|
131
|
+
for node in ast.walk(tree):
|
|
132
|
+
if isinstance(node, ast.If) and ASTHelpers.is_type_checking_condition(
|
|
133
|
+
node.test
|
|
134
|
+
):
|
|
135
|
+
for stmt in node.body:
|
|
136
|
+
type_checking_nodes.add(stmt)
|
|
137
|
+
for nested in ast.walk(stmt):
|
|
138
|
+
type_checking_nodes.add(nested)
|
|
139
|
+
|
|
140
|
+
return type_checking_nodes
|
|
141
|
+
|
|
142
|
+
@staticmethod
|
|
143
|
+
# ID: b8e2f6d3-9c4a-5f1e-a7b9-c3d8e1f5a2b6
|
|
144
|
+
def _check_import_from(
|
|
145
|
+
node: ast.ImportFrom,
|
|
146
|
+
forbidden_patterns: list[str],
|
|
147
|
+
filepath: Path,
|
|
148
|
+
) -> str | None:
|
|
149
|
+
"""Check ``from X import Y`` statements against the forbidden list."""
|
|
150
|
+
if not node.module:
|
|
151
|
+
return None
|
|
152
|
+
|
|
153
|
+
lineno = ASTHelpers.lineno(node)
|
|
154
|
+
|
|
155
|
+
for name in node.names:
|
|
156
|
+
full_import = f"{node.module}.{name.name}"
|
|
157
|
+
for pattern in forbidden_patterns:
|
|
158
|
+
if RuntimeImportBoundaryCheck._matches_pattern(full_import, pattern):
|
|
159
|
+
return (
|
|
160
|
+
f"{filepath}:{lineno} - Forbidden import: "
|
|
161
|
+
f"'from {node.module} import {name.name}' "
|
|
162
|
+
f"(matches constitutional boundary rule: {pattern})"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
return None
|
|
166
|
+
|
|
167
|
+
@staticmethod
|
|
168
|
+
# ID: c9d4e7f2-a3b5-6e8c-b4d1-f8a7c2e5b3d9
|
|
169
|
+
def _check_import(
|
|
170
|
+
node: ast.Import,
|
|
171
|
+
forbidden_patterns: list[str],
|
|
172
|
+
filepath: Path,
|
|
173
|
+
) -> str | None:
|
|
174
|
+
"""Check ``import X`` statements against the forbidden list."""
|
|
175
|
+
lineno = ASTHelpers.lineno(node)
|
|
176
|
+
|
|
177
|
+
for alias in node.names:
|
|
178
|
+
for pattern in forbidden_patterns:
|
|
179
|
+
if RuntimeImportBoundaryCheck._matches_pattern(alias.name, pattern):
|
|
180
|
+
return (
|
|
181
|
+
f"{filepath}:{lineno} - Forbidden import: "
|
|
182
|
+
f"'import {alias.name}' "
|
|
183
|
+
f"(matches constitutional boundary rule: {pattern})"
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
return None
|
|
187
|
+
|
|
188
|
+
@staticmethod
|
|
189
|
+
# ID: d2f8e4c1-b5a7-9e3f-c6d2-a9f7e4b1c8d5
|
|
190
|
+
def _matches_pattern(import_path: str, pattern: str) -> bool:
|
|
191
|
+
"""Exact, prefix, or subpath match against the forbidden pattern."""
|
|
192
|
+
if import_path == pattern:
|
|
193
|
+
return True
|
|
194
|
+
if import_path.startswith(pattern + "."):
|
|
195
|
+
return True
|
|
196
|
+
if pattern.startswith(import_path + "."):
|
|
197
|
+
return True
|
|
198
|
+
return False
|