codd-dev 2.12.0__tar.gz → 2.14.0__tar.gz
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.
- {codd_dev-2.12.0 → codd_dev-2.14.0}/PKG-INFO +5 -4
- {codd_dev-2.12.0 → codd_dev-2.14.0}/README.md +4 -3
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/cli.py +56 -3
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/coverage_metrics.py +11 -1
- codd_dev-2.14.0/codd/dag/auto_repair.py +164 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/builder.py +90 -5
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/__init__.py +41 -1
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/ci_health.py +68 -8
- codd_dev-2.14.0/codd/dag/checks/opt_out.py +265 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/user_journey_coherence.py +36 -5
- codd_dev-2.14.0/codd/dag/runner.py +146 -0
- codd_dev-2.14.0/codd/defaults.py +32 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployer.py +25 -4
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/__init__.py +9 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/extractor.py +56 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/ai_command.py +5 -4
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/engine.py +15 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/lexicon.py +21 -9
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/required_artifacts_deriver.py +3 -1
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/requirement_completeness_auditor.py +3 -1
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/validator.py +30 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/pyproject.toml +1 -1
- codd_dev-2.12.0/codd/dag/runner.py +0 -79
- {codd_dev-2.12.0 → codd_dev-2.14.0}/.gitignore +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/LICENSE +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/__main__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/_git_helper.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/ask_user_question_adapter.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/assembler.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/bridge.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/brownfield/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/brownfield/pipeline.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/clustering.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/coherence_adapters.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/coherence_engine.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/config.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/contracts.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/coverage_auditor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/depends_on_consistency.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/deployment_completeness.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/edge_validity.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/environment_coverage.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/implementation_coverage.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/node_completeness.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/task_completion.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/checks/transitive_closure.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/coverage_axes.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/cli.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/cpp_embedded.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/csharp.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/elixir.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/generic.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/iot.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/java.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/kotlin.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/mobile.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/ruby.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/rust.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/scala.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/swift.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/test_frameworks.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/defaults/web.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/dag/extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/defaults.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deploy_targets/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deploy_targets/app_service.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deploy_targets/base.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deploy_targets/docker_compose.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/checks/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/defaults/deploy_targets.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/defaults/runtime_capability_inference.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/defaults/schema_providers.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/defaults/verification_templates.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/llm_consideration.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/schema/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/schema/prisma.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/target/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/target/docker_compose.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/verification/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/verification/assertion_handlers.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/verification/cdp_browser.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/verification/cdp_engines.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/verification/cdp_launchers.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/verification/cdp_wire.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/verification/curl.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/verification/form_strategies.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/verification/means_catalog.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/deployment/providers/verification/playwright.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/design_md.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/diff/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/diff/apply.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/diff/engine.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/diff/persistence.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/diff/templates/diff_prompt.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/drift.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/e2e_extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/e2e_generator.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/e2e_runner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/apply.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/finding.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/formatters/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/formatters/base.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/formatters/interactive.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/formatters/json_fmt.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/formatters/md.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/lexicon_loader.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/persistence.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/elicit/templates/elicit_prompt_L0.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/env_refs.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/extract_ai.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/fixer.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/fixup_drift.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/fixup_drift_strategies/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/fixup_drift_strategies/design_token_drift.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/fixup_drift_strategies/lexicon_violation.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/fixup_drift_strategies/url_drift.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/generator.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/graph.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/hitl_session.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/hooks/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/hooks/pre-commit +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/hooks/recipes/claude_settings_example.json +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/hooks/recipes/codex_hook.sh +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/hooks/recipes/git_post_commit.sh +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/hooks/recipes/git_pre_commit.sh +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/implementer/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/implementer/chunked_runner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/implementer/typecheck_loop.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/implementer.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/inheritance.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/init/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/init/lexicon_suggest.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/init/llm_lexicon_suggester.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/init/stack_detector.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/knowledge_fetcher.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/lexicon_cli/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/lexicon_cli/formatters/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/lexicon_cli/formatters/html.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/lexicon_cli/formatters/json_fmt.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/lexicon_cli/formatters/md.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/lexicon_cli/inspector.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/lexicon_cli/manager.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/lexicon_cli/reporter.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/lexicon_cli/threshold.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/approval.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/best_practice_augmenter.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/criteria_expander.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/design_doc_extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/impl_step_deriver.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/means_catalog_loader.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/parser.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/plan_deriver.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/prompt_builder.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/strategy_validator.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/templates/best_practice_augment_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/templates/criteria_expand_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/templates/design_doc_extract_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/templates/impl_step_derive_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/templates/implementation_step_catalog.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/templates/meta_instruction.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/templates/plan_derive_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/llm/templates/verification_means_catalog.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/mcp_server.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/measure.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/parsing.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/planner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/policy.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/preflight/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/preflight/defaults/cli.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/preflight/defaults/iot.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/preflight/defaults/mobile.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/preflight/defaults/web.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/propagate.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/propagator.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/registry.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/approval_repair.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/engine.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/git_patcher.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/history.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/llm_repair_engine.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/loop.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/primary_picker.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/proof_breaks.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/repair_result.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/repairability_classifier.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/schema.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/templates/analyze_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/templates/propose_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/templates/repair_strategy_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/templates/repairability_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair/verify_runner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/repair_slice.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/require.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/require_plugins.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/require_propagate.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/required_artifacts/defaults/cli.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/required_artifacts/defaults/iot.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/required_artifacts/defaults/mobile.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/required_artifacts/defaults/web.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/requirement_completeness/defaults/cli.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/requirement_completeness/defaults/iot.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/requirement_completeness/defaults/mobile.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/requirement_completeness/defaults/web.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/restore.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/routes_extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/scanner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/schema_refs.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/screen_flow_validator.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/screen_transition_extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/screen_transitions/defaults.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/synth.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/codd.yaml.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/conventions.yaml.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/data_dependencies.yaml.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/doc_links.yaml.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/extract_ai_prompt_baseline.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/extracted/api-contract.md.j2 +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/extracted/architecture-overview.md.j2 +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/extracted/module-detail.md.j2 +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/extracted/schema-design.md.j2 +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/extracted/system-context.md.j2 +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/gitignore.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/lexicon_questions.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/lexicon_schema.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/templates/overrides.yaml.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/traceability.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/watch/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/watch/events.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/watch/propagation_log.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/watch/propagation_pipeline.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/watch/test_runner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/watch/watcher.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd/wiring.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ai_governance_eu_act/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ai_governance_eu_act/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ai_governance_eu_act/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ai_governance_eu_act/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ai_governance_eu_act/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ai_governance_eu_act/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rate_limiting_caching/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rate_limiting_caching/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rate_limiting_caching/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rate_limiting_caching/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rate_limiting_caching/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rate_limiting_caching/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rest_openapi/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rest_openapi/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rest_openapi/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rest_openapi/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rest_openapi/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/api_rest_openapi/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/babok/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/babok/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/babok/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/babok/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/babok/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_event_cloudevents/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_event_cloudevents/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_event_cloudevents/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_event_cloudevents/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_event_cloudevents/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_event_cloudevents/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_graphql/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_graphql/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_graphql/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_graphql/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_graphql/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_graphql/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_grpc_proto/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_grpc_proto/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_grpc_proto/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_grpc_proto/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_grpc_proto/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/backend_grpc_proto/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_hipaa/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_hipaa/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_hipaa/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_hipaa/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_hipaa/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_hipaa/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_iso27001/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_iso27001/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_iso27001/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_iso27001/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_iso27001/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_iso27001/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_pci_dss_4/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_pci_dss_4/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_pci_dss_4/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_pci_dss_4/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_pci_dss_4/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/compliance_pci_dss_4/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_governance_appi_gdpr/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_governance_appi_gdpr/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_governance_appi_gdpr/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_governance_appi_gdpr/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_governance_appi_gdpr/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_governance_appi_gdpr/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_nosql_jsonschema/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_nosql_jsonschema/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_nosql_jsonschema/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_nosql_jsonschema/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_nosql_jsonschema/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_nosql_jsonschema/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_relational_iso_sql/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_relational_iso_sql/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_relational_iso_sql/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_relational_iso_sql/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_relational_iso_sql/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/data_relational_iso_sql/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ddd_domain_driven_design/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ddd_domain_driven_design/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ddd_domain_driven_design/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ddd_domain_driven_design/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ddd_domain_driven_design/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ddd_domain_driven_design/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/dora_sre_metrics/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/dora_sre_metrics/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/dora_sre_metrics/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/dora_sre_metrics/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/dora_sre_metrics/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/dora_sre_metrics/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/i18n_unicode_cldr/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/i18n_unicode_cldr/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/i18n_unicode_cldr/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/i18n_unicode_cldr/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/i18n_unicode_cldr/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/i18n_unicode_cldr/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ml_model_cards/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ml_model_cards/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ml_model_cards/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ml_model_cards/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ml_model_cards/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ml_model_cards/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_a11y_native/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_a11y_native/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_a11y_native/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_a11y_native/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_a11y_native/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_a11y_native/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_android_material3/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_android_material3/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_android_material3/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_android_material3/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_android_material3/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_android_material3/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_ios_hig/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_ios_hig/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_ios_hig/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_ios_hig/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_ios_hig/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_ios_hig/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_security_masvs/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_security_masvs/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_security_masvs/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_security_masvs/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_security_masvs/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/mobile_security_masvs/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_cicd_pipeline/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_cicd_pipeline/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_cicd_pipeline/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_cicd_pipeline/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_cicd_pipeline/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_cicd_pipeline/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_iac_terraform/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_iac_terraform/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_iac_terraform/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_iac_terraform/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_iac_terraform/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_iac_terraform/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_kubernetes/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_kubernetes/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_kubernetes/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_kubernetes/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_kubernetes/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_kubernetes/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_observability_otel/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_observability_otel/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_observability_otel/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_observability_otel/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_observability_otel/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/ops_observability_otel/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_iso25010/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_iso25010/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_iso25010/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_iso25010/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_iso25010/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_iso25010/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_test_iso29119/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_test_iso29119/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_test_iso29119/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_test_iso29119/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_test_iso29119/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/process_test_iso29119/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/twelve_factor_app/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/twelve_factor_app/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/twelve_factor_app/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/twelve_factor_app/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/twelve_factor_app/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/twelve_factor_app/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_authn_webauthn/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_authn_webauthn/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_authn_webauthn/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_authn_webauthn/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_authn_webauthn/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_authn_webauthn/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_browser_compat/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_browser_compat/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_browser_compat/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_browser_compat/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_browser_compat/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_browser_compat/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_forms_html5/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_forms_html5/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_forms_html5/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_forms_html5/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_forms_html5/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_forms_html5/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_performance_core_web_vitals/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_performance_core_web_vitals/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_performance_core_web_vitals/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_performance_core_web_vitals/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_performance_core_web_vitals/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_performance_core_web_vitals/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_pwa_manifest/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_pwa_manifest/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_pwa_manifest/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_pwa_manifest/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_pwa_manifest/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_pwa_manifest/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_responsive/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_responsive/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_responsive/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_responsive/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_responsive/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_responsive/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_security_owasp/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_security_owasp/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_security_owasp/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_security_owasp/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_security_owasp/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_security_owasp/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_seo_schemaorg/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_seo_schemaorg/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_seo_schemaorg/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_seo_schemaorg/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_seo_schemaorg/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/lexicons/web_seo_schemaorg/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/codd_plugins/stack_map.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/docs/cookbook/cdp_browser/README.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/docs/requirements/README.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.14.0}/tests/integration/standalone_repair_skeleton/README.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codd-dev
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.14.0
|
|
4
4
|
Summary: CoDD: Coherence-Driven Development — cross-artifact change impact analysis
|
|
5
5
|
Project-URL: Homepage, https://github.com/yohey-w/codd-dev
|
|
6
6
|
Project-URL: Repository, https://github.com/yohey-w/codd-dev
|
|
@@ -153,10 +153,11 @@ This is what lets CoDD ship one core that works for Next.js, Django, FastAPI, Ra
|
|
|
153
153
|
|
|
154
154
|
## 🧭 Roadmap
|
|
155
155
|
|
|
156
|
-
- **v2.
|
|
156
|
+
- **v2.14.0 (current)** — 8 structural gaps closed (cmd_466 dogfood). Sidecar `<test>.codd.yaml` with `verified_by:` (C6) and `axis_matrix:` (C9); lexicon schema SSoT; completeness_audit batch; `scan.exclude` bug fix (−52% amber noise); `codd dag verify --auto-repair`; elicit mock-AI sentinel; AI timeout → 3600 s SSoT. Dogfood re-run: red 22 → 0. See [CHANGELOG](CHANGELOG.md).
|
|
157
|
+
- **v2.13.0** — Opt-out protection: `OptOutPolicy` requires a `justification` + `expires_at` for every config-level opt-out (`ci.provider=none`, etc.). Silent SKIP abolished; severity preserved. `codd validate` reports policy violations. See [post-mortem](docs/post-mortems/optout_loophole.md).
|
|
158
|
+
- **v2.12.0** — Test-completeness gates: C7 `actors_without_journeys` amber promotion + new C8 `ci_health` static check (workflow presence, trigger coverage, verification-in-workflow). See [post-mortem](docs/post-mortems/test_completeness_gap.md).
|
|
157
159
|
- **v2.11.0** — Sprint-less `codd implement` (`--design <path> --output <dir>` directly; `implementation_plan.md` parser removed). See [migration guide](docs/migrations/v2.11.0-sprintless.md).
|
|
158
|
-
- **v2.
|
|
159
|
-
- **v2.13.0 (next)** — C8 `ci_health` runtime mode (opt-in `ci.runtime_check: true`) polling the CI provider for latest-run-on-default-branch success.
|
|
160
|
+
- **v2.15.0 (next)** — C8 `ci_health` runtime mode (opt-in `ci.runtime_check: true`) polling the CI provider for latest-run-on-default-branch success.
|
|
160
161
|
|
|
161
162
|
---
|
|
162
163
|
|
|
@@ -113,10 +113,11 @@ This is what lets CoDD ship one core that works for Next.js, Django, FastAPI, Ra
|
|
|
113
113
|
|
|
114
114
|
## 🧭 Roadmap
|
|
115
115
|
|
|
116
|
-
- **v2.
|
|
116
|
+
- **v2.14.0 (current)** — 8 structural gaps closed (cmd_466 dogfood). Sidecar `<test>.codd.yaml` with `verified_by:` (C6) and `axis_matrix:` (C9); lexicon schema SSoT; completeness_audit batch; `scan.exclude` bug fix (−52% amber noise); `codd dag verify --auto-repair`; elicit mock-AI sentinel; AI timeout → 3600 s SSoT. Dogfood re-run: red 22 → 0. See [CHANGELOG](CHANGELOG.md).
|
|
117
|
+
- **v2.13.0** — Opt-out protection: `OptOutPolicy` requires a `justification` + `expires_at` for every config-level opt-out (`ci.provider=none`, etc.). Silent SKIP abolished; severity preserved. `codd validate` reports policy violations. See [post-mortem](docs/post-mortems/optout_loophole.md).
|
|
118
|
+
- **v2.12.0** — Test-completeness gates: C7 `actors_without_journeys` amber promotion + new C8 `ci_health` static check (workflow presence, trigger coverage, verification-in-workflow). See [post-mortem](docs/post-mortems/test_completeness_gap.md).
|
|
117
119
|
- **v2.11.0** — Sprint-less `codd implement` (`--design <path> --output <dir>` directly; `implementation_plan.md` parser removed). See [migration guide](docs/migrations/v2.11.0-sprintless.md).
|
|
118
|
-
- **v2.
|
|
119
|
-
- **v2.13.0 (next)** — C8 `ci_health` runtime mode (opt-in `ci.runtime_check: true`) polling the CI provider for latest-run-on-default-branch success.
|
|
120
|
+
- **v2.15.0 (next)** — C8 `ci_health` runtime mode (opt-in `ci.runtime_check: true`) polling the CI provider for latest-run-on-default-branch success.
|
|
120
121
|
|
|
121
122
|
---
|
|
122
123
|
|
|
@@ -4890,7 +4890,28 @@ def dag_build(project_path: str, output_format: str, cache: bool, output: str |
|
|
|
4890
4890
|
type=click.Choice(["text", "json"]),
|
|
4891
4891
|
help="Output format",
|
|
4892
4892
|
)
|
|
4893
|
-
|
|
4893
|
+
@click.option(
|
|
4894
|
+
"--auto-repair",
|
|
4895
|
+
is_flag=True,
|
|
4896
|
+
default=False,
|
|
4897
|
+
help="Apply violation-output suggestions mechanically (e.g. append "
|
|
4898
|
+
"suggested_lexicon_entry to project_lexicon.yaml). Implies a dry-run "
|
|
4899
|
+
"preview unless --apply is also supplied.",
|
|
4900
|
+
)
|
|
4901
|
+
@click.option(
|
|
4902
|
+
"--apply",
|
|
4903
|
+
"apply_changes",
|
|
4904
|
+
is_flag=True,
|
|
4905
|
+
default=False,
|
|
4906
|
+
help="Write changes to disk when --auto-repair is set. Default: dry run.",
|
|
4907
|
+
)
|
|
4908
|
+
def dag_verify(
|
|
4909
|
+
project_path: str,
|
|
4910
|
+
check_names: tuple[str, ...],
|
|
4911
|
+
output_format: str,
|
|
4912
|
+
auto_repair: bool,
|
|
4913
|
+
apply_changes: bool,
|
|
4914
|
+
):
|
|
4894
4915
|
"""Run DAG completeness checks."""
|
|
4895
4916
|
from codd.dag.runner import run_all_checks
|
|
4896
4917
|
|
|
@@ -4901,10 +4922,13 @@ def dag_verify(project_path: str, check_names: tuple[str, ...], output_format: s
|
|
|
4901
4922
|
click.echo(f"Error: {exc}")
|
|
4902
4923
|
raise SystemExit(1)
|
|
4903
4924
|
|
|
4925
|
+
opt_out_results = [result for result in results if _dag_result_status(result) == "opt_out"]
|
|
4904
4926
|
failed_red = [
|
|
4905
4927
|
result
|
|
4906
4928
|
for result in results
|
|
4907
|
-
if not _dag_result_passed(result)
|
|
4929
|
+
if not _dag_result_passed(result)
|
|
4930
|
+
and _dag_result_severity(result) == "red"
|
|
4931
|
+
and _dag_result_status(result) != "opt_out"
|
|
4908
4932
|
]
|
|
4909
4933
|
amber_findings = [
|
|
4910
4934
|
result
|
|
@@ -4917,7 +4941,10 @@ def dag_verify(project_path: str, check_names: tuple[str, ...], output_format: s
|
|
|
4917
4941
|
else:
|
|
4918
4942
|
for result in results:
|
|
4919
4943
|
severity = _dag_result_severity(result)
|
|
4920
|
-
|
|
4944
|
+
status_value = _dag_result_status(result)
|
|
4945
|
+
if status_value == "opt_out":
|
|
4946
|
+
status = "OPT_OUT"
|
|
4947
|
+
elif _dag_result_passed(result):
|
|
4921
4948
|
status = "PASS"
|
|
4922
4949
|
else:
|
|
4923
4950
|
status = "WARN" if severity == "amber" else "FAIL"
|
|
@@ -4929,6 +4956,24 @@ def dag_verify(project_path: str, check_names: tuple[str, ...], output_format: s
|
|
|
4929
4956
|
click.echo(f"\n{len(failed_red)} check(s) FAILED (severity=red)")
|
|
4930
4957
|
elif amber_findings:
|
|
4931
4958
|
click.echo(f"\n{len(amber_findings)} check(s) WARN (severity=amber, deploy allowed)")
|
|
4959
|
+
if opt_out_results:
|
|
4960
|
+
click.echo(f"\n{len(opt_out_results)} active opt-out(s) (deploy allowed):")
|
|
4961
|
+
for result in opt_out_results:
|
|
4962
|
+
click.echo(f" - {_dag_result_name(result)}: {_dag_result_message(result)}")
|
|
4963
|
+
|
|
4964
|
+
if auto_repair:
|
|
4965
|
+
from codd.dag.auto_repair import apply_auto_repair
|
|
4966
|
+
|
|
4967
|
+
outcome = apply_auto_repair(project_root, results, dry_run=not apply_changes)
|
|
4968
|
+
click.echo("")
|
|
4969
|
+
verb = "Would apply" if not apply_changes else "Applied"
|
|
4970
|
+
click.echo(f"{verb} {len(outcome.applied)} repair(s):")
|
|
4971
|
+
for action in outcome.applied:
|
|
4972
|
+
click.echo(f" - {action.description}")
|
|
4973
|
+
if outcome.skipped:
|
|
4974
|
+
click.echo(f"\nSkipped {len(outcome.skipped)} non-repairable violation(s):")
|
|
4975
|
+
for action in outcome.skipped:
|
|
4976
|
+
click.echo(f" - {action.description}")
|
|
4932
4977
|
|
|
4933
4978
|
raise SystemExit(1 if failed_red else 0)
|
|
4934
4979
|
|
|
@@ -5185,6 +5230,14 @@ def _dag_result_passed(result: Any) -> bool:
|
|
|
5185
5230
|
return _dag_result_value(result, "passed") is not False
|
|
5186
5231
|
|
|
5187
5232
|
|
|
5233
|
+
def _dag_result_status(result: Any) -> str:
|
|
5234
|
+
return str(_dag_result_value(result, "status") or "")
|
|
5235
|
+
|
|
5236
|
+
|
|
5237
|
+
def _dag_result_message(result: Any) -> str:
|
|
5238
|
+
return str(_dag_result_value(result, "message") or "")
|
|
5239
|
+
|
|
5240
|
+
|
|
5188
5241
|
def _dag_result_has_findings(result: Any) -> bool:
|
|
5189
5242
|
for key in (
|
|
5190
5243
|
"violations",
|
|
@@ -183,12 +183,17 @@ def compute_dag_completeness(
|
|
|
183
183
|
return _exception_result("dag_completeness", threshold, exc)
|
|
184
184
|
|
|
185
185
|
red_results = [result for result in results if _dag_result_severity(result) == "red"]
|
|
186
|
-
failed_red = [
|
|
186
|
+
failed_red = [
|
|
187
|
+
result
|
|
188
|
+
for result in red_results
|
|
189
|
+
if _dag_result_passed(result) is False and _dag_result_status(result) != "opt_out"
|
|
190
|
+
]
|
|
187
191
|
amber_findings = [
|
|
188
192
|
result
|
|
189
193
|
for result in results
|
|
190
194
|
if _dag_result_severity(result) == "amber" and _dag_result_has_findings(result)
|
|
191
195
|
]
|
|
196
|
+
opt_outs = [result for result in results if _dag_result_status(result) == "opt_out"]
|
|
192
197
|
|
|
193
198
|
total = len(red_results)
|
|
194
199
|
uncovered = len(failed_red)
|
|
@@ -197,6 +202,7 @@ def compute_dag_completeness(
|
|
|
197
202
|
details = [f"checks: {len(results)}", f"red_failures: {uncovered}"]
|
|
198
203
|
details.extend(_format_dag_result(result) for result in failed_red[:5])
|
|
199
204
|
details.extend(f"warning: {_format_dag_result(result)}" for result in amber_findings[:5])
|
|
205
|
+
details.extend(f"opt_out: {_format_dag_result(result)}" for result in opt_outs[:5])
|
|
200
206
|
|
|
201
207
|
return CoverageResult(
|
|
202
208
|
metric="dag_completeness",
|
|
@@ -361,6 +367,10 @@ def _dag_result_passed(result: Any) -> bool:
|
|
|
361
367
|
return _dag_result_value(result, "passed") is not False
|
|
362
368
|
|
|
363
369
|
|
|
370
|
+
def _dag_result_status(result: Any) -> str:
|
|
371
|
+
return str(_dag_result_value(result, "status") or "")
|
|
372
|
+
|
|
373
|
+
|
|
364
374
|
def _dag_result_name(result: Any) -> str:
|
|
365
375
|
return str(_dag_result_value(result, "check_name") or result.__class__.__name__)
|
|
366
376
|
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Mechanical auto-repair for DAG-verify violations.
|
|
2
|
+
|
|
3
|
+
Reads the violation output produced by ``codd dag verify`` and applies the
|
|
4
|
+
``suggested_*`` payloads to the project's filesystem without invoking AI.
|
|
5
|
+
|
|
6
|
+
Currently supported repair types:
|
|
7
|
+
|
|
8
|
+
* ``missing_journey_lexicon`` — append the ``suggested_lexicon_entry`` to
|
|
9
|
+
``project_lexicon.yaml`` under ``required_artifacts``.
|
|
10
|
+
|
|
11
|
+
Repair types that need a project-specific anchor (e.g. ``no_plan_task_for_journey``
|
|
12
|
+
which requires the user to choose which plan section gets the new outputs)
|
|
13
|
+
are listed in ``RepairOutcome.skipped`` with a human-readable reason so the
|
|
14
|
+
operator knows what still has to be done by hand.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Any, Iterable
|
|
22
|
+
|
|
23
|
+
import yaml
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class RepairAction:
|
|
28
|
+
description: str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class RepairOutcome:
|
|
33
|
+
applied: list[RepairAction] = field(default_factory=list)
|
|
34
|
+
skipped: list[RepairAction] = field(default_factory=list)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def apply_auto_repair(
|
|
38
|
+
project_root: Path,
|
|
39
|
+
results: Iterable[Any],
|
|
40
|
+
*,
|
|
41
|
+
dry_run: bool = True,
|
|
42
|
+
) -> RepairOutcome:
|
|
43
|
+
"""Apply mechanical repairs derived from DAG verify violation output.
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
project_root
|
|
48
|
+
Project root used to resolve relative file paths.
|
|
49
|
+
results
|
|
50
|
+
Iterable of DAG check result objects (or dicts) as returned by
|
|
51
|
+
``codd.dag.runner.run_all_checks``.
|
|
52
|
+
dry_run
|
|
53
|
+
When True, the function reports what *would* be applied without
|
|
54
|
+
modifying the filesystem.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
outcome = RepairOutcome()
|
|
58
|
+
suggested_entries: list[dict[str, Any]] = []
|
|
59
|
+
|
|
60
|
+
for result in results:
|
|
61
|
+
violations = _result_value(result, "violations") or []
|
|
62
|
+
if not isinstance(violations, list):
|
|
63
|
+
continue
|
|
64
|
+
for violation in violations:
|
|
65
|
+
if not isinstance(violation, dict):
|
|
66
|
+
continue
|
|
67
|
+
v_type = violation.get("type")
|
|
68
|
+
if v_type == "missing_journey_lexicon":
|
|
69
|
+
entry = violation.get("suggested_lexicon_entry")
|
|
70
|
+
if isinstance(entry, dict) and entry.get("id"):
|
|
71
|
+
suggested_entries.append(entry)
|
|
72
|
+
else:
|
|
73
|
+
outcome.skipped.append(
|
|
74
|
+
RepairAction(
|
|
75
|
+
description=(
|
|
76
|
+
"missing_journey_lexicon without suggested_lexicon_entry; "
|
|
77
|
+
"violation cannot be auto-repaired"
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
continue
|
|
82
|
+
outcome.skipped.append(
|
|
83
|
+
RepairAction(
|
|
84
|
+
description=f"{v_type or '<unknown>'} — no mechanical repair available",
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if suggested_entries:
|
|
89
|
+
repaired_ids = _apply_lexicon_entries(
|
|
90
|
+
project_root, suggested_entries, dry_run=dry_run
|
|
91
|
+
)
|
|
92
|
+
for entry_id in repaired_ids:
|
|
93
|
+
verb = "would append" if dry_run else "appended"
|
|
94
|
+
outcome.applied.append(
|
|
95
|
+
RepairAction(
|
|
96
|
+
description=(
|
|
97
|
+
f"project_lexicon.yaml: {verb} required_artifacts entry "
|
|
98
|
+
f"'{entry_id}'"
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
skipped_existing = {entry["id"] for entry in suggested_entries} - set(repaired_ids)
|
|
103
|
+
for entry_id in sorted(skipped_existing):
|
|
104
|
+
outcome.skipped.append(
|
|
105
|
+
RepairAction(
|
|
106
|
+
description=(
|
|
107
|
+
f"project_lexicon.yaml: required_artifacts entry "
|
|
108
|
+
f"'{entry_id}' already declared"
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
return outcome
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _apply_lexicon_entries(
|
|
117
|
+
project_root: Path,
|
|
118
|
+
entries: list[dict[str, Any]],
|
|
119
|
+
*,
|
|
120
|
+
dry_run: bool,
|
|
121
|
+
) -> list[str]:
|
|
122
|
+
lexicon_path = project_root / "project_lexicon.yaml"
|
|
123
|
+
if not lexicon_path.is_file():
|
|
124
|
+
return []
|
|
125
|
+
|
|
126
|
+
payload = yaml.safe_load(lexicon_path.read_text(encoding="utf-8")) or {}
|
|
127
|
+
if not isinstance(payload, dict):
|
|
128
|
+
return []
|
|
129
|
+
|
|
130
|
+
required_artifacts = payload.get("required_artifacts")
|
|
131
|
+
if not isinstance(required_artifacts, list):
|
|
132
|
+
required_artifacts = []
|
|
133
|
+
|
|
134
|
+
existing_ids = {
|
|
135
|
+
entry.get("id")
|
|
136
|
+
for entry in required_artifacts
|
|
137
|
+
if isinstance(entry, dict) and entry.get("id")
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
added_ids: list[str] = []
|
|
141
|
+
for entry in entries:
|
|
142
|
+
entry_id = entry.get("id")
|
|
143
|
+
if not entry_id or entry_id in existing_ids:
|
|
144
|
+
continue
|
|
145
|
+
required_artifacts.append(dict(entry))
|
|
146
|
+
existing_ids.add(entry_id)
|
|
147
|
+
added_ids.append(entry_id)
|
|
148
|
+
|
|
149
|
+
if not added_ids:
|
|
150
|
+
return added_ids
|
|
151
|
+
|
|
152
|
+
payload["required_artifacts"] = required_artifacts
|
|
153
|
+
if not dry_run:
|
|
154
|
+
lexicon_path.write_text(
|
|
155
|
+
yaml.safe_dump(payload, sort_keys=False, allow_unicode=True),
|
|
156
|
+
encoding="utf-8",
|
|
157
|
+
)
|
|
158
|
+
return added_ids
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _result_value(result: Any, key: str) -> Any:
|
|
162
|
+
if isinstance(result, dict):
|
|
163
|
+
return result.get(key)
|
|
164
|
+
return getattr(result, key, None)
|
|
@@ -222,7 +222,11 @@ def _add_design_docs(dag: DAG, project_root: Path, settings: dict[str, Any]) ->
|
|
|
222
222
|
design_docs: dict[str, dict[str, Any]] = {}
|
|
223
223
|
aliases: dict[str, str] = {}
|
|
224
224
|
frontmatter_alias = _frontmatter_alias_settings(settings)
|
|
225
|
-
for md_path in _glob_project_paths(
|
|
225
|
+
for md_path in _glob_project_paths(
|
|
226
|
+
project_root,
|
|
227
|
+
settings.get("design_doc_patterns", []),
|
|
228
|
+
exclude_patterns=settings.get("scan_exclude_patterns"),
|
|
229
|
+
):
|
|
226
230
|
if not md_path.is_file():
|
|
227
231
|
continue
|
|
228
232
|
node_id = _relative_id(md_path, project_root)
|
|
@@ -256,7 +260,11 @@ def _add_impl_files(dag: DAG, project_root: Path, settings: dict[str, Any]) -> d
|
|
|
256
260
|
impl_nodes: dict[str, Path] = {}
|
|
257
261
|
capability_patterns = _capability_patterns(settings)
|
|
258
262
|
implementation_suffixes = _suffix_tuple(settings.get("implementation_suffixes")) or LEGACY_IMPLEMENTATION_SUFFIXES
|
|
259
|
-
for file_path in _glob_project_paths(
|
|
263
|
+
for file_path in _glob_project_paths(
|
|
264
|
+
project_root,
|
|
265
|
+
settings.get("impl_file_patterns", []),
|
|
266
|
+
exclude_patterns=settings.get("scan_exclude_patterns"),
|
|
267
|
+
):
|
|
260
268
|
if (
|
|
261
269
|
not file_path.is_file()
|
|
262
270
|
or file_path.suffix not in implementation_suffixes
|
|
@@ -284,7 +292,11 @@ def _add_impl_files(dag: DAG, project_root: Path, settings: dict[str, Any]) -> d
|
|
|
284
292
|
def _add_test_files(dag: DAG, project_root: Path, settings: dict[str, Any]) -> dict[str, Path]:
|
|
285
293
|
test_nodes: dict[str, Path] = {}
|
|
286
294
|
test_suffixes = _suffix_tuple(settings.get("test_suffixes")) or LEGACY_TEST_SUFFIXES
|
|
287
|
-
for file_path in _glob_project_paths(
|
|
295
|
+
for file_path in _glob_project_paths(
|
|
296
|
+
project_root,
|
|
297
|
+
settings.get("test_file_patterns", []),
|
|
298
|
+
exclude_patterns=settings.get("scan_exclude_patterns"),
|
|
299
|
+
):
|
|
288
300
|
if not file_path.is_file() or file_path.suffix not in test_suffixes or not _is_test_file(file_path, project_root):
|
|
289
301
|
continue
|
|
290
302
|
node_id = _relative_id(file_path, project_root)
|
|
@@ -1067,7 +1079,11 @@ def _alias_candidates(import_ref: str, project_root: Path, aliases: dict[str, li
|
|
|
1067
1079
|
return candidates
|
|
1068
1080
|
|
|
1069
1081
|
|
|
1070
|
-
def _glob_project_paths(
|
|
1082
|
+
def _glob_project_paths(
|
|
1083
|
+
project_root: Path,
|
|
1084
|
+
patterns: Any,
|
|
1085
|
+
exclude_patterns: Any = None,
|
|
1086
|
+
) -> list[Path]:
|
|
1071
1087
|
paths: dict[str, Path] = {}
|
|
1072
1088
|
for pattern in _as_list(patterns):
|
|
1073
1089
|
if not isinstance(pattern, str) or not pattern:
|
|
@@ -1075,7 +1091,69 @@ def _glob_project_paths(project_root: Path, patterns: Any) -> list[Path]:
|
|
|
1075
1091
|
for expanded in _expand_braces(pattern):
|
|
1076
1092
|
for path in project_root.glob(expanded):
|
|
1077
1093
|
paths[str(path.resolve())] = path.resolve()
|
|
1078
|
-
|
|
1094
|
+
excludes = [
|
|
1095
|
+
str(pattern)
|
|
1096
|
+
for pattern in _as_list(exclude_patterns)
|
|
1097
|
+
if isinstance(pattern, str) and pattern.strip()
|
|
1098
|
+
]
|
|
1099
|
+
if not excludes:
|
|
1100
|
+
return [paths[key] for key in sorted(paths)]
|
|
1101
|
+
project_root_resolved = project_root.resolve()
|
|
1102
|
+
filtered: list[Path] = []
|
|
1103
|
+
for key in sorted(paths):
|
|
1104
|
+
path = paths[key]
|
|
1105
|
+
if _path_matches_any_pattern(path, project_root_resolved, excludes):
|
|
1106
|
+
continue
|
|
1107
|
+
filtered.append(path)
|
|
1108
|
+
return filtered
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
def _path_matches_any_pattern(
|
|
1112
|
+
path: Path,
|
|
1113
|
+
project_root: Path,
|
|
1114
|
+
patterns: list[str],
|
|
1115
|
+
) -> bool:
|
|
1116
|
+
try:
|
|
1117
|
+
relative = path.resolve().relative_to(project_root)
|
|
1118
|
+
except ValueError:
|
|
1119
|
+
return False
|
|
1120
|
+
rel_text = relative.as_posix()
|
|
1121
|
+
parts = relative.parts
|
|
1122
|
+
|
|
1123
|
+
for pattern in patterns:
|
|
1124
|
+
if fnmatch.fnmatch(rel_text, pattern):
|
|
1125
|
+
return True
|
|
1126
|
+
# Honour shell-style "any depth" wildcards by stripping the outer
|
|
1127
|
+
# ``**/`` and ``/**`` decorations and looking for the inner pattern
|
|
1128
|
+
# against any path slice. Examples:
|
|
1129
|
+
# **/node_modules/** -> "node_modules" must appear as a path component
|
|
1130
|
+
# **/dist/** -> "dist" must appear as a path component
|
|
1131
|
+
# src/**/*.py -> not stripped here; falls back to fnmatch above
|
|
1132
|
+
inner = pattern
|
|
1133
|
+
stripped = True
|
|
1134
|
+
while stripped:
|
|
1135
|
+
stripped = False
|
|
1136
|
+
if inner.startswith("**/"):
|
|
1137
|
+
inner = inner[3:]
|
|
1138
|
+
stripped = True
|
|
1139
|
+
if inner.endswith("/**"):
|
|
1140
|
+
inner = inner[:-3]
|
|
1141
|
+
stripped = True
|
|
1142
|
+
if not inner or inner == pattern:
|
|
1143
|
+
continue
|
|
1144
|
+
if "/" not in inner and "*" not in inner:
|
|
1145
|
+
if inner in parts:
|
|
1146
|
+
return True
|
|
1147
|
+
continue
|
|
1148
|
+
# Inner still contains glob syntax: check every contiguous slice of
|
|
1149
|
+
# the relative path against ``inner`` so e.g. ``a/b/c/d`` matches
|
|
1150
|
+
# ``a/b`` or ``c/d`` etc.
|
|
1151
|
+
for start in range(len(parts)):
|
|
1152
|
+
for end in range(start + 1, len(parts) + 1):
|
|
1153
|
+
candidate = "/".join(parts[start:end])
|
|
1154
|
+
if fnmatch.fnmatch(candidate, inner):
|
|
1155
|
+
return True
|
|
1156
|
+
return False
|
|
1079
1157
|
|
|
1080
1158
|
|
|
1081
1159
|
def _expand_braces(pattern: str) -> list[str]:
|
|
@@ -1306,6 +1384,11 @@ def _apply_scan_patterns(settings: dict[str, Any], config: dict[str, Any]) -> No
|
|
|
1306
1384
|
source_dirs = _as_list(scan.get("source_dirs"))
|
|
1307
1385
|
test_dirs = _as_list(scan.get("test_dirs"))
|
|
1308
1386
|
doc_dirs = _as_list(scan.get("doc_dirs"))
|
|
1387
|
+
exclude_patterns = [
|
|
1388
|
+
str(pattern)
|
|
1389
|
+
for pattern in _as_list(scan.get("exclude"))
|
|
1390
|
+
if isinstance(pattern, str) and pattern.strip()
|
|
1391
|
+
]
|
|
1309
1392
|
|
|
1310
1393
|
if source_dirs:
|
|
1311
1394
|
_extend_unique(
|
|
@@ -1324,6 +1407,8 @@ def _apply_scan_patterns(settings: dict[str, Any], config: dict[str, Any]) -> No
|
|
|
1324
1407
|
)
|
|
1325
1408
|
if doc_dirs:
|
|
1326
1409
|
_extend_unique(settings, "design_doc_patterns", _file_patterns_for_dirs(doc_dirs, (".md",)))
|
|
1410
|
+
if exclude_patterns:
|
|
1411
|
+
_extend_unique(settings, "scan_exclude_patterns", exclude_patterns)
|
|
1327
1412
|
|
|
1328
1413
|
|
|
1329
1414
|
def _normalize_dag_section(section: dict[str, Any]) -> dict[str, Any]:
|
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
+
from datetime import date
|
|
6
7
|
from pathlib import Path
|
|
7
|
-
from typing import Any
|
|
8
|
+
from typing import Any, TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from codd.dag.checks.opt_out import OptOutDeclaration, OptOutPolicy, OptOutSignal
|
|
8
12
|
|
|
9
13
|
|
|
10
14
|
_REGISTRY: dict[str, type[Any]] = {}
|
|
@@ -34,14 +38,50 @@ class DagCheck:
|
|
|
34
38
|
dag: Any | None = None,
|
|
35
39
|
project_root: str | Path | None = None,
|
|
36
40
|
settings: dict[str, Any] | None = None,
|
|
41
|
+
opt_out_policy: "OptOutPolicy | None" = None,
|
|
42
|
+
today: date | None = None,
|
|
37
43
|
) -> None:
|
|
38
44
|
self.dag = dag
|
|
39
45
|
self.project_root = Path(project_root) if project_root is not None else None
|
|
40
46
|
self.settings = settings or {}
|
|
47
|
+
self.opt_out_policy = opt_out_policy
|
|
48
|
+
self.today = today or date.today()
|
|
41
49
|
|
|
42
50
|
def run(self, dag: Any | None = None) -> CheckResult:
|
|
43
51
|
raise NotImplementedError
|
|
44
52
|
|
|
53
|
+
def detect_opt_out(self, codd_config: dict[str, Any]) -> "OptOutSignal | None":
|
|
54
|
+
"""Return an OptOutSignal when this check's config requests an opt-out.
|
|
55
|
+
|
|
56
|
+
Default: no opt-out detection. Subclasses that own a config-level
|
|
57
|
+
opt-out flag (e.g. ``ci.provider: none``) override this and route the
|
|
58
|
+
request through :class:`OptOutPolicy` rather than handling it inline.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
del codd_config
|
|
62
|
+
return None
|
|
63
|
+
|
|
64
|
+
def resolve_opt_out(
|
|
65
|
+
self,
|
|
66
|
+
codd_config: dict[str, Any] | None = None,
|
|
67
|
+
) -> "tuple[OptOutSignal, OptOutDeclaration | None] | None":
|
|
68
|
+
"""Convenience helper: run detect_opt_out and look up a declaration.
|
|
69
|
+
|
|
70
|
+
Returns ``None`` when no opt-out signal is detected. Returns
|
|
71
|
+
``(signal, declaration_or_None)`` otherwise so the caller can decide
|
|
72
|
+
whether the missing-or-expired declaration should fail red or pass
|
|
73
|
+
through.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
config = codd_config if codd_config is not None else self.settings
|
|
77
|
+
signal = self.detect_opt_out(config)
|
|
78
|
+
if signal is None:
|
|
79
|
+
return None
|
|
80
|
+
declaration = (
|
|
81
|
+
self.opt_out_policy.lookup(signal.check_name) if self.opt_out_policy else None
|
|
82
|
+
)
|
|
83
|
+
return signal, declaration
|
|
84
|
+
|
|
45
85
|
|
|
46
86
|
def register_dag_check(name: str):
|
|
47
87
|
"""Register a DAG check class under ``name``."""
|
|
@@ -12,9 +12,15 @@ from typing import Any, Mapping
|
|
|
12
12
|
import yaml
|
|
13
13
|
|
|
14
14
|
from codd.dag.checks import DagCheck, register_dag_check
|
|
15
|
+
from codd.dag.checks.opt_out import (
|
|
16
|
+
OPT_OUT_STATUS,
|
|
17
|
+
OptOutDeclaration,
|
|
18
|
+
OptOutSignal,
|
|
19
|
+
)
|
|
15
20
|
|
|
16
21
|
|
|
17
22
|
_DEFAULT_PROVIDER = "github" + "_actions"
|
|
23
|
+
_OPT_OUT_PROVIDER = "none"
|
|
18
24
|
|
|
19
25
|
|
|
20
26
|
@dataclass
|
|
@@ -30,7 +36,11 @@ class CiConfig:
|
|
|
30
36
|
@classmethod
|
|
31
37
|
def from_mapping(cls, value: Mapping[str, Any] | None) -> "CiConfig":
|
|
32
38
|
if not isinstance(value, Mapping):
|
|
33
|
-
|
|
39
|
+
# Missing ``ci:`` section is no longer treated as a silent opt-out.
|
|
40
|
+
# The default provider applies; if no workflow files exist this
|
|
41
|
+
# surfaces as a normal red ``ci_workflow_missing`` finding rather
|
|
42
|
+
# than a free PASS.
|
|
43
|
+
return cls()
|
|
34
44
|
|
|
35
45
|
config = cls()
|
|
36
46
|
return cls(
|
|
@@ -87,17 +97,67 @@ class CiHealthCheck(DagCheck):
|
|
|
87
97
|
del dag
|
|
88
98
|
root = Path(project_root or self.project_root or ".").resolve()
|
|
89
99
|
active_settings = codd_config or settings or self.settings
|
|
90
|
-
|
|
100
|
+
config = CiConfig.from_mapping(_mapping_value(active_settings, "ci"))
|
|
101
|
+
return self.check(root, config)
|
|
102
|
+
|
|
103
|
+
def detect_opt_out(self, codd_config: dict[str, Any]) -> OptOutSignal | None:
|
|
104
|
+
config = CiConfig.from_mapping(_mapping_value(codd_config, "ci"))
|
|
105
|
+
if self._is_opt_out_provider(config):
|
|
106
|
+
return OptOutSignal(
|
|
107
|
+
check_name=self.check_name,
|
|
108
|
+
source="ci.provider=none",
|
|
109
|
+
)
|
|
110
|
+
return None
|
|
91
111
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
112
|
+
@staticmethod
|
|
113
|
+
def _is_opt_out_provider(config: CiConfig) -> bool:
|
|
114
|
+
return config.provider.strip().lower() == _OPT_OUT_PROVIDER
|
|
115
|
+
|
|
116
|
+
def _make_opt_out_result(self, declaration: OptOutDeclaration | None) -> CiHealthResult:
|
|
117
|
+
today = self.today
|
|
118
|
+
if declaration is None:
|
|
119
|
+
return CiHealthResult(
|
|
120
|
+
status="fail",
|
|
121
|
+
severity="red",
|
|
122
|
+
block_deploy=True,
|
|
123
|
+
message=(
|
|
124
|
+
"C8 ci_health: ci.provider=none requires an opt_outs declaration "
|
|
125
|
+
"in codd.yaml (check: ci_health, reason: ..., expires_at: "
|
|
126
|
+
"YYYY-MM-DD)."
|
|
127
|
+
),
|
|
128
|
+
passed=False,
|
|
129
|
+
)
|
|
130
|
+
if declaration.is_expired(today):
|
|
95
131
|
return CiHealthResult(
|
|
96
|
-
status="
|
|
97
|
-
|
|
98
|
-
|
|
132
|
+
status="fail",
|
|
133
|
+
severity="red",
|
|
134
|
+
block_deploy=True,
|
|
135
|
+
message=(
|
|
136
|
+
f"C8 ci_health: opt-out expired on "
|
|
137
|
+
f"{declaration.expires_at.isoformat()} "
|
|
138
|
+
f"(reason: {declaration.reason}); renew the entry or remove it."
|
|
139
|
+
),
|
|
140
|
+
passed=False,
|
|
99
141
|
)
|
|
142
|
+
return CiHealthResult(
|
|
143
|
+
status=OPT_OUT_STATUS,
|
|
144
|
+
severity=self.severity,
|
|
145
|
+
block_deploy=False,
|
|
146
|
+
message=(
|
|
147
|
+
f"C8 ci_health opt-out active "
|
|
148
|
+
f"(reason: {declaration.reason}, "
|
|
149
|
+
f"expires: {declaration.expires_at.isoformat()})"
|
|
150
|
+
),
|
|
151
|
+
passed=False,
|
|
152
|
+
)
|
|
100
153
|
|
|
154
|
+
def check(self, project_root: Path, config: CiConfig) -> CiHealthResult:
|
|
155
|
+
project_root = Path(project_root).resolve()
|
|
156
|
+
if self._is_opt_out_provider(config):
|
|
157
|
+
declaration = (
|
|
158
|
+
self.opt_out_policy.lookup(self.check_name) if self.opt_out_policy else None
|
|
159
|
+
)
|
|
160
|
+
return self._make_opt_out_result(declaration)
|
|
101
161
|
workflow_files = self._locate_workflows(project_root, config.workflow_glob)
|
|
102
162
|
if not workflow_files:
|
|
103
163
|
finding = CiHealthFinding(
|