codd-dev 2.12.0__tar.gz → 2.13.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.13.0}/PKG-INFO +4 -3
- {codd_dev-2.12.0 → codd_dev-2.13.0}/README.md +3 -2
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/cli.py +20 -2
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/coverage_metrics.py +11 -1
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/__init__.py +41 -1
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/ci_health.py +68 -8
- codd_dev-2.13.0/codd/dag/checks/opt_out.py +265 -0
- codd_dev-2.13.0/codd/dag/runner.py +146 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployer.py +25 -4
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/validator.py +30 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/pyproject.toml +1 -1
- codd_dev-2.12.0/codd/dag/runner.py +0 -79
- {codd_dev-2.12.0 → codd_dev-2.13.0}/.gitignore +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/LICENSE +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/__main__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/_git_helper.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/ask_user_question_adapter.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/assembler.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/bridge.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/brownfield/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/brownfield/pipeline.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/clustering.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/coherence_adapters.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/coherence_engine.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/config.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/contracts.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/coverage_auditor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/builder.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/depends_on_consistency.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/deployment_completeness.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/edge_validity.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/environment_coverage.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/implementation_coverage.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/node_completeness.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/task_completion.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/transitive_closure.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/user_journey_coherence.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/coverage_axes.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/cli.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/cpp_embedded.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/csharp.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/elixir.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/generic.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/iot.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/java.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/kotlin.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/mobile.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/ruby.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/rust.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/scala.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/swift.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/test_frameworks.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/web.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/defaults.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deploy_targets/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deploy_targets/app_service.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deploy_targets/base.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deploy_targets/docker_compose.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/checks/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/defaults/deploy_targets.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/defaults/runtime_capability_inference.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/defaults/schema_providers.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/defaults/verification_templates.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/ai_command.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/llm_consideration.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/schema/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/schema/prisma.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/target/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/target/docker_compose.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/assertion_handlers.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_browser.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_engines.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_launchers.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_wire.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/curl.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/form_strategies.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/means_catalog.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/playwright.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/design_md.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/diff/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/diff/apply.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/diff/engine.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/diff/persistence.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/diff/templates/diff_prompt.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/drift.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/e2e_extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/e2e_generator.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/e2e_runner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/apply.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/engine.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/finding.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/formatters/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/formatters/base.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/formatters/interactive.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/formatters/json_fmt.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/formatters/md.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/lexicon_loader.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/persistence.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/templates/elicit_prompt_L0.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/env_refs.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/extract_ai.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixer.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixup_drift.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/design_token_drift.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/lexicon_violation.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/url_drift.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/generator.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/graph.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hitl_session.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/pre-commit +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/recipes/claude_settings_example.json +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/recipes/codex_hook.sh +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/recipes/git_post_commit.sh +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/recipes/git_pre_commit.sh +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/implementer/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/implementer/chunked_runner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/implementer/typecheck_loop.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/implementer.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/inheritance.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/init/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/init/lexicon_suggest.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/init/llm_lexicon_suggester.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/init/stack_detector.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/knowledge_fetcher.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/html.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/json_fmt.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/md.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/inspector.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/manager.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/reporter.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/threshold.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/approval.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/best_practice_augmenter.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/criteria_expander.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/design_doc_extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/impl_step_deriver.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/means_catalog_loader.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/parser.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/plan_deriver.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/prompt_builder.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/strategy_validator.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/best_practice_augment_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/criteria_expand_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/design_doc_extract_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/impl_step_derive_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/implementation_step_catalog.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/meta_instruction.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/plan_derive_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/verification_means_catalog.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/mcp_server.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/measure.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/parsing.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/planner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/policy.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/preflight/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/preflight/defaults/cli.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/preflight/defaults/iot.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/preflight/defaults/mobile.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/preflight/defaults/web.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/propagate.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/propagator.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/registry.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/approval_repair.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/engine.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/git_patcher.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/history.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/llm_repair_engine.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/loop.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/primary_picker.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/proof_breaks.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/repair_result.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/repairability_classifier.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/schema.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/templates/analyze_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/templates/propose_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/templates/repair_strategy_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/templates/repairability_meta.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/verify_runner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair_slice.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/require.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/require_plugins.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/require_propagate.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/cli.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/iot.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/mobile.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/web.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/required_artifacts_deriver.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/cli.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/iot.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/mobile.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/web.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/requirement_completeness_auditor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/restore.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/routes_extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/scanner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/schema_refs.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/screen_flow_validator.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/screen_transition_extractor.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/screen_transitions/defaults.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/synth.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/codd.yaml.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/conventions.yaml.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/data_dependencies.yaml.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/doc_links.yaml.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extract_ai_prompt_baseline.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extracted/api-contract.md.j2 +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extracted/architecture-overview.md.j2 +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extracted/module-detail.md.j2 +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extracted/schema-design.md.j2 +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extracted/system-context.md.j2 +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/gitignore.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/lexicon_questions.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/lexicon_schema.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/overrides.yaml.tmpl +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/traceability.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/__init__.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/events.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/propagation_log.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/propagation_pipeline.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/test_runner.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/watcher.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/wiring.py +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/coverage_matrix.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/elicit_extend.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/lexicon.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/manifest.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/recommended_kinds.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/severity_rules.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/stack_map.yaml +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/docs/cookbook/cdp_browser/README.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.0}/docs/requirements/README.md +0 -0
- {codd_dev-2.12.0 → codd_dev-2.13.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.13.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.13.0 (current)** — 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).
|
|
157
|
+
- **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
158
|
- **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
159
|
- **v2.10.0** — Lexicon-driven completeness, 38 plug-ins, LLM-enhanced init, scope/phase filter, auto-repair across the full DAG.
|
|
159
|
-
- **v2.
|
|
160
|
+
- **v2.14.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.13.0 (current)** — 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).
|
|
117
|
+
- **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
118
|
- **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
119
|
- **v2.10.0** — Lexicon-driven completeness, 38 plug-ins, LLM-enhanced init, scope/phase filter, auto-repair across the full DAG.
|
|
119
|
-
- **v2.
|
|
120
|
+
- **v2.14.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
|
|
|
@@ -4901,10 +4901,13 @@ def dag_verify(project_path: str, check_names: tuple[str, ...], output_format: s
|
|
|
4901
4901
|
click.echo(f"Error: {exc}")
|
|
4902
4902
|
raise SystemExit(1)
|
|
4903
4903
|
|
|
4904
|
+
opt_out_results = [result for result in results if _dag_result_status(result) == "opt_out"]
|
|
4904
4905
|
failed_red = [
|
|
4905
4906
|
result
|
|
4906
4907
|
for result in results
|
|
4907
|
-
if not _dag_result_passed(result)
|
|
4908
|
+
if not _dag_result_passed(result)
|
|
4909
|
+
and _dag_result_severity(result) == "red"
|
|
4910
|
+
and _dag_result_status(result) != "opt_out"
|
|
4908
4911
|
]
|
|
4909
4912
|
amber_findings = [
|
|
4910
4913
|
result
|
|
@@ -4917,7 +4920,10 @@ def dag_verify(project_path: str, check_names: tuple[str, ...], output_format: s
|
|
|
4917
4920
|
else:
|
|
4918
4921
|
for result in results:
|
|
4919
4922
|
severity = _dag_result_severity(result)
|
|
4920
|
-
|
|
4923
|
+
status_value = _dag_result_status(result)
|
|
4924
|
+
if status_value == "opt_out":
|
|
4925
|
+
status = "OPT_OUT"
|
|
4926
|
+
elif _dag_result_passed(result):
|
|
4921
4927
|
status = "PASS"
|
|
4922
4928
|
else:
|
|
4923
4929
|
status = "WARN" if severity == "amber" else "FAIL"
|
|
@@ -4929,6 +4935,10 @@ def dag_verify(project_path: str, check_names: tuple[str, ...], output_format: s
|
|
|
4929
4935
|
click.echo(f"\n{len(failed_red)} check(s) FAILED (severity=red)")
|
|
4930
4936
|
elif amber_findings:
|
|
4931
4937
|
click.echo(f"\n{len(amber_findings)} check(s) WARN (severity=amber, deploy allowed)")
|
|
4938
|
+
if opt_out_results:
|
|
4939
|
+
click.echo(f"\n{len(opt_out_results)} active opt-out(s) (deploy allowed):")
|
|
4940
|
+
for result in opt_out_results:
|
|
4941
|
+
click.echo(f" - {_dag_result_name(result)}: {_dag_result_message(result)}")
|
|
4932
4942
|
|
|
4933
4943
|
raise SystemExit(1 if failed_red else 0)
|
|
4934
4944
|
|
|
@@ -5185,6 +5195,14 @@ def _dag_result_passed(result: Any) -> bool:
|
|
|
5185
5195
|
return _dag_result_value(result, "passed") is not False
|
|
5186
5196
|
|
|
5187
5197
|
|
|
5198
|
+
def _dag_result_status(result: Any) -> str:
|
|
5199
|
+
return str(_dag_result_value(result, "status") or "")
|
|
5200
|
+
|
|
5201
|
+
|
|
5202
|
+
def _dag_result_message(result: Any) -> str:
|
|
5203
|
+
return str(_dag_result_value(result, "message") or "")
|
|
5204
|
+
|
|
5205
|
+
|
|
5188
5206
|
def _dag_result_has_findings(result: Any) -> bool:
|
|
5189
5207
|
for key in (
|
|
5190
5208
|
"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
|
|
|
@@ -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(
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"""Generic opt-out policy for DAG checks.
|
|
2
|
+
|
|
3
|
+
This module introduces a single, check-agnostic representation of "the user
|
|
4
|
+
has explicitly asked this gate to stand down". It is the only sanctioned way
|
|
5
|
+
to disable a registered DAG check; per-check ad-hoc flags (e.g. legacy
|
|
6
|
+
``ci.provider: none`` style) must be re-routed through this policy via the
|
|
7
|
+
:meth:`DagCheck.detect_opt_out` hook.
|
|
8
|
+
|
|
9
|
+
A valid opt-out requires:
|
|
10
|
+
|
|
11
|
+
* an explicit ``opt_outs`` entry in ``codd.yaml`` whose ``check`` matches a
|
|
12
|
+
registered DAG check name;
|
|
13
|
+
* a non-empty ``reason``;
|
|
14
|
+
* an ISO ``expires_at`` date strictly in the future at evaluation time.
|
|
15
|
+
|
|
16
|
+
Anything else is rejected. ``codd validate`` surfaces the policy errors as
|
|
17
|
+
configuration problems; ``codd dag verify`` aggregates active and expired
|
|
18
|
+
opt-outs separately from the normal pass/fail counts so the cost of a
|
|
19
|
+
standing opt-out is always visible.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from dataclasses import dataclass, field
|
|
25
|
+
from datetime import date, datetime
|
|
26
|
+
from typing import Any, Iterable, Mapping
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
OPT_OUT_STATUS = "opt_out"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class OptOutDeclaration:
|
|
34
|
+
"""One opt-out entry parsed from ``codd.yaml``."""
|
|
35
|
+
|
|
36
|
+
check: str
|
|
37
|
+
reason: str
|
|
38
|
+
expires_at: date
|
|
39
|
+
approved_by: str | None = None
|
|
40
|
+
context: str | None = None
|
|
41
|
+
|
|
42
|
+
def is_expired(self, today: date) -> bool:
|
|
43
|
+
return self.expires_at <= today
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True)
|
|
47
|
+
class OptOutSignal:
|
|
48
|
+
"""Emitted by a check when its config indicates an explicit opt-out request."""
|
|
49
|
+
|
|
50
|
+
check_name: str
|
|
51
|
+
source: str
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass(frozen=True)
|
|
55
|
+
class OptOutPolicyError:
|
|
56
|
+
"""A configuration-level violation of the opt-out policy."""
|
|
57
|
+
|
|
58
|
+
code: str
|
|
59
|
+
message: str
|
|
60
|
+
check: str | None = None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class OptOutPolicy:
|
|
65
|
+
"""Resolved opt-out declarations for a project."""
|
|
66
|
+
|
|
67
|
+
declarations: list[OptOutDeclaration] = field(default_factory=list)
|
|
68
|
+
parse_errors: list[OptOutPolicyError] = field(default_factory=list)
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def from_config(cls, codd_config: Mapping[str, Any] | None) -> "OptOutPolicy":
|
|
72
|
+
"""Build a policy from the parsed ``codd.yaml`` mapping.
|
|
73
|
+
|
|
74
|
+
Unknown / unparseable shapes are recorded as ``parse_errors`` rather
|
|
75
|
+
than raised — this lets ``codd validate`` report them alongside other
|
|
76
|
+
validation issues.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
if not isinstance(codd_config, Mapping):
|
|
80
|
+
return cls()
|
|
81
|
+
|
|
82
|
+
raw = codd_config.get("opt_outs")
|
|
83
|
+
if raw is None:
|
|
84
|
+
return cls()
|
|
85
|
+
if not isinstance(raw, list):
|
|
86
|
+
return cls(
|
|
87
|
+
parse_errors=[
|
|
88
|
+
OptOutPolicyError(
|
|
89
|
+
code="invalid_opt_outs_section",
|
|
90
|
+
message="opt_outs must be a list of mappings",
|
|
91
|
+
)
|
|
92
|
+
]
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
declarations: list[OptOutDeclaration] = []
|
|
96
|
+
errors: list[OptOutPolicyError] = []
|
|
97
|
+
for index, entry in enumerate(raw):
|
|
98
|
+
if not isinstance(entry, Mapping):
|
|
99
|
+
errors.append(
|
|
100
|
+
OptOutPolicyError(
|
|
101
|
+
code="invalid_opt_out_entry",
|
|
102
|
+
message=f"opt_outs[{index}] must be a mapping",
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
continue
|
|
106
|
+
decl, entry_errors = _build_declaration(entry, index)
|
|
107
|
+
errors.extend(entry_errors)
|
|
108
|
+
if decl is not None:
|
|
109
|
+
declarations.append(decl)
|
|
110
|
+
|
|
111
|
+
return cls(declarations=declarations, parse_errors=errors)
|
|
112
|
+
|
|
113
|
+
def lookup(self, check_name: str) -> OptOutDeclaration | None:
|
|
114
|
+
"""Return the raw declaration for ``check_name`` (regardless of expiry).
|
|
115
|
+
|
|
116
|
+
Expiry handling is the caller's responsibility: a declaration may be
|
|
117
|
+
present but expired, and the caller decides whether that is treated as
|
|
118
|
+
a hard failure or a warning. This keeps the policy itself stateless
|
|
119
|
+
with respect to "today".
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
for declaration in self.declarations:
|
|
123
|
+
if declaration.check == check_name:
|
|
124
|
+
return declaration
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
def validate(
|
|
128
|
+
self,
|
|
129
|
+
today: date,
|
|
130
|
+
registered_check_names: Iterable[str],
|
|
131
|
+
) -> list[OptOutPolicyError]:
|
|
132
|
+
"""Return all opt-out policy errors at the given evaluation date.
|
|
133
|
+
|
|
134
|
+
Errors include parse errors discovered at ``from_config`` time,
|
|
135
|
+
unknown check names, duplicates, and expired declarations.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
errors: list[OptOutPolicyError] = list(self.parse_errors)
|
|
139
|
+
registered = set(registered_check_names)
|
|
140
|
+
seen_checks: set[str] = set()
|
|
141
|
+
|
|
142
|
+
for declaration in self.declarations:
|
|
143
|
+
if declaration.check in seen_checks:
|
|
144
|
+
errors.append(
|
|
145
|
+
OptOutPolicyError(
|
|
146
|
+
code="duplicate",
|
|
147
|
+
check=declaration.check,
|
|
148
|
+
message=(
|
|
149
|
+
f"opt_outs has more than one entry for check "
|
|
150
|
+
f"{declaration.check!r}"
|
|
151
|
+
),
|
|
152
|
+
)
|
|
153
|
+
)
|
|
154
|
+
continue
|
|
155
|
+
seen_checks.add(declaration.check)
|
|
156
|
+
|
|
157
|
+
if declaration.check not in registered:
|
|
158
|
+
errors.append(
|
|
159
|
+
OptOutPolicyError(
|
|
160
|
+
code="unknown_check",
|
|
161
|
+
check=declaration.check,
|
|
162
|
+
message=(
|
|
163
|
+
f"opt_outs entry references unknown check "
|
|
164
|
+
f"{declaration.check!r}"
|
|
165
|
+
),
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
if declaration.is_expired(today):
|
|
169
|
+
errors.append(
|
|
170
|
+
OptOutPolicyError(
|
|
171
|
+
code="expired",
|
|
172
|
+
check=declaration.check,
|
|
173
|
+
message=(
|
|
174
|
+
f"opt_outs entry for {declaration.check!r} expired on "
|
|
175
|
+
f"{declaration.expires_at.isoformat()}; renew or remove"
|
|
176
|
+
),
|
|
177
|
+
)
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
return errors
|
|
181
|
+
|
|
182
|
+
def active(self, today: date) -> list[OptOutDeclaration]:
|
|
183
|
+
return [decl for decl in self.declarations if not decl.is_expired(today)]
|
|
184
|
+
|
|
185
|
+
def expired(self, today: date) -> list[OptOutDeclaration]:
|
|
186
|
+
return [decl for decl in self.declarations if decl.is_expired(today)]
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _build_declaration(
|
|
190
|
+
entry: Mapping[str, Any],
|
|
191
|
+
index: int,
|
|
192
|
+
) -> tuple[OptOutDeclaration | None, list[OptOutPolicyError]]:
|
|
193
|
+
errors: list[OptOutPolicyError] = []
|
|
194
|
+
check_value = entry.get("check")
|
|
195
|
+
check_name: str | None = None
|
|
196
|
+
if isinstance(check_value, str) and check_value.strip():
|
|
197
|
+
check_name = check_value.strip()
|
|
198
|
+
else:
|
|
199
|
+
errors.append(
|
|
200
|
+
OptOutPolicyError(
|
|
201
|
+
code="missing_check",
|
|
202
|
+
message=f"opt_outs[{index}] is missing a non-empty 'check' name",
|
|
203
|
+
)
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
reason_value = entry.get("reason")
|
|
207
|
+
reason = reason_value.strip() if isinstance(reason_value, str) else ""
|
|
208
|
+
if not reason:
|
|
209
|
+
errors.append(
|
|
210
|
+
OptOutPolicyError(
|
|
211
|
+
code="missing_reason",
|
|
212
|
+
check=check_name,
|
|
213
|
+
message=(
|
|
214
|
+
f"opt_outs[{index}] requires a non-empty 'reason' "
|
|
215
|
+
"(briefly explain why this gate is disabled)"
|
|
216
|
+
),
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
expires_at = _coerce_expires_at(entry.get("expires_at"))
|
|
221
|
+
if expires_at is None:
|
|
222
|
+
errors.append(
|
|
223
|
+
OptOutPolicyError(
|
|
224
|
+
code="missing_expires_at",
|
|
225
|
+
check=check_name,
|
|
226
|
+
message=(
|
|
227
|
+
f"opt_outs[{index}] requires 'expires_at' as an ISO date "
|
|
228
|
+
"(YYYY-MM-DD) so the opt-out cannot be permanent"
|
|
229
|
+
),
|
|
230
|
+
)
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
if check_name is None or expires_at is None or not reason:
|
|
234
|
+
return None, errors
|
|
235
|
+
|
|
236
|
+
approved_by = entry.get("approved_by")
|
|
237
|
+
approved_by = approved_by.strip() if isinstance(approved_by, str) and approved_by.strip() else None
|
|
238
|
+
|
|
239
|
+
context = entry.get("context")
|
|
240
|
+
context = context.strip() if isinstance(context, str) and context.strip() else None
|
|
241
|
+
|
|
242
|
+
declaration = OptOutDeclaration(
|
|
243
|
+
check=check_name,
|
|
244
|
+
reason=reason,
|
|
245
|
+
expires_at=expires_at,
|
|
246
|
+
approved_by=approved_by,
|
|
247
|
+
context=context,
|
|
248
|
+
)
|
|
249
|
+
return declaration, errors
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _coerce_expires_at(value: Any) -> date | None:
|
|
253
|
+
if isinstance(value, date) and not isinstance(value, datetime):
|
|
254
|
+
return value
|
|
255
|
+
if isinstance(value, datetime):
|
|
256
|
+
return value.date()
|
|
257
|
+
if isinstance(value, str):
|
|
258
|
+
text = value.strip()
|
|
259
|
+
if not text:
|
|
260
|
+
return None
|
|
261
|
+
try:
|
|
262
|
+
return date.fromisoformat(text)
|
|
263
|
+
except ValueError:
|
|
264
|
+
return None
|
|
265
|
+
return None
|