codd-dev 2.13.0__tar.gz → 2.15.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.13.0 → codd_dev-2.15.0}/PKG-INFO +7 -6
- {codd_dev-2.13.0 → codd_dev-2.15.0}/README.md +6 -5
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/cli.py +39 -1
- codd_dev-2.15.0/codd/dag/auto_repair.py +164 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/builder.py +205 -8
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/transitive_closure.py +22 -3
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/user_journey_coherence.py +36 -5
- codd_dev-2.15.0/codd/defaults.py +32 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/__init__.py +9 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/extractor.py +56 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/ai_command.py +5 -4
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/engine.py +15 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/lexicon.py +21 -9
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/required_artifacts_deriver.py +3 -1
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/requirement_completeness_auditor.py +3 -1
- {codd_dev-2.13.0 → codd_dev-2.15.0}/pyproject.toml +1 -1
- {codd_dev-2.13.0 → codd_dev-2.15.0}/.gitignore +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/LICENSE +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/__main__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/_git_helper.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/ask_user_question_adapter.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/assembler.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/bridge.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/brownfield/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/brownfield/pipeline.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/clustering.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/coherence_adapters.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/coherence_engine.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/config.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/contracts.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/coverage_auditor.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/coverage_metrics.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/ci_health.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/depends_on_consistency.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/deployment_completeness.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/edge_validity.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/environment_coverage.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/implementation_coverage.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/node_completeness.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/opt_out.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/checks/task_completion.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/coverage_axes.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/cli.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/cpp_embedded.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/csharp.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/elixir.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/generic.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/iot.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/java.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/kotlin.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/mobile.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/ruby.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/rust.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/scala.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/swift.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/test_frameworks.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/defaults/web.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/extractor.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/dag/runner.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/defaults.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deploy_targets/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deploy_targets/app_service.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deploy_targets/base.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deploy_targets/docker_compose.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployer.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/checks/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/defaults/deploy_targets.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/defaults/runtime_capability_inference.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/defaults/schema_providers.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/defaults/verification_templates.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/llm_consideration.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/schema/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/schema/prisma.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/target/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/target/docker_compose.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/verification/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/verification/assertion_handlers.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/verification/cdp_browser.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/verification/cdp_engines.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/verification/cdp_launchers.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/verification/cdp_wire.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/verification/curl.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/verification/form_strategies.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/verification/means_catalog.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/deployment/providers/verification/playwright.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/design_md.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/diff/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/diff/apply.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/diff/engine.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/diff/persistence.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/diff/templates/diff_prompt.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/drift.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/e2e_extractor.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/e2e_generator.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/e2e_runner.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/apply.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/finding.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/formatters/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/formatters/base.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/formatters/interactive.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/formatters/json_fmt.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/formatters/md.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/lexicon_loader.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/persistence.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/elicit/templates/elicit_prompt_L0.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/env_refs.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/extract_ai.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/extractor.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/fixer.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/fixup_drift.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/fixup_drift_strategies/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/fixup_drift_strategies/design_token_drift.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/fixup_drift_strategies/lexicon_violation.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/fixup_drift_strategies/url_drift.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/generator.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/graph.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/hitl_session.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/hooks/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/hooks/pre-commit +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/hooks/recipes/claude_settings_example.json +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/hooks/recipes/codex_hook.sh +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/hooks/recipes/git_post_commit.sh +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/hooks/recipes/git_pre_commit.sh +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/implementer/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/implementer/chunked_runner.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/implementer/typecheck_loop.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/implementer.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/inheritance.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/init/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/init/lexicon_suggest.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/init/llm_lexicon_suggester.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/init/stack_detector.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/knowledge_fetcher.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/lexicon_cli/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/lexicon_cli/formatters/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/lexicon_cli/formatters/html.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/lexicon_cli/formatters/json_fmt.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/lexicon_cli/formatters/md.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/lexicon_cli/inspector.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/lexicon_cli/manager.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/lexicon_cli/reporter.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/lexicon_cli/threshold.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/approval.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/best_practice_augmenter.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/criteria_expander.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/design_doc_extractor.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/impl_step_deriver.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/means_catalog_loader.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/parser.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/plan_deriver.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/prompt_builder.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/strategy_validator.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/templates/best_practice_augment_meta.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/templates/criteria_expand_meta.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/templates/design_doc_extract_meta.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/templates/impl_step_derive_meta.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/templates/implementation_step_catalog.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/templates/meta_instruction.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/templates/plan_derive_meta.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/llm/templates/verification_means_catalog.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/mcp_server.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/measure.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/parsing.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/planner.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/policy.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/preflight/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/preflight/defaults/cli.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/preflight/defaults/iot.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/preflight/defaults/mobile.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/preflight/defaults/web.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/propagate.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/propagator.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/registry.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/approval_repair.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/engine.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/git_patcher.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/history.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/llm_repair_engine.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/loop.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/primary_picker.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/proof_breaks.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/repair_result.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/repairability_classifier.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/schema.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/templates/analyze_meta.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/templates/propose_meta.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/templates/repair_strategy_meta.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/templates/repairability_meta.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair/verify_runner.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/repair_slice.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/require.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/require_plugins.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/require_propagate.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/required_artifacts/defaults/cli.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/required_artifacts/defaults/iot.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/required_artifacts/defaults/mobile.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/required_artifacts/defaults/web.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/requirement_completeness/defaults/cli.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/requirement_completeness/defaults/iot.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/requirement_completeness/defaults/mobile.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/requirement_completeness/defaults/web.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/restore.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/routes_extractor.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/scanner.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/schema_refs.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/screen_flow_validator.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/screen_transition_extractor.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/screen_transitions/defaults.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/synth.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/codd.yaml.tmpl +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/conventions.yaml.tmpl +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/data_dependencies.yaml.tmpl +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/doc_links.yaml.tmpl +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/extract_ai_prompt_baseline.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/extracted/api-contract.md.j2 +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/extracted/architecture-overview.md.j2 +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/extracted/module-detail.md.j2 +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/extracted/schema-design.md.j2 +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/extracted/system-context.md.j2 +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/gitignore.tmpl +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/lexicon_questions.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/lexicon_schema.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/templates/overrides.yaml.tmpl +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/traceability.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/validator.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/watch/__init__.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/watch/events.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/watch/propagation_log.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/watch/propagation_pipeline.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/watch/test_runner.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/watch/watcher.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd/wiring.py +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ai_governance_eu_act/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ai_governance_eu_act/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ai_governance_eu_act/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ai_governance_eu_act/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ai_governance_eu_act/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ai_governance_eu_act/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rate_limiting_caching/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rate_limiting_caching/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rate_limiting_caching/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rate_limiting_caching/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rate_limiting_caching/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rate_limiting_caching/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rest_openapi/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rest_openapi/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rest_openapi/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rest_openapi/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rest_openapi/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/api_rest_openapi/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/babok/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/babok/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/babok/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/babok/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/babok/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_event_cloudevents/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_event_cloudevents/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_event_cloudevents/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_event_cloudevents/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_event_cloudevents/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_event_cloudevents/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_graphql/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_graphql/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_graphql/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_graphql/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_graphql/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_graphql/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_grpc_proto/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_grpc_proto/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_grpc_proto/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_grpc_proto/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_grpc_proto/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/backend_grpc_proto/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_hipaa/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_hipaa/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_hipaa/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_hipaa/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_hipaa/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_hipaa/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_iso27001/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_iso27001/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_iso27001/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_iso27001/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_iso27001/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_iso27001/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_pci_dss_4/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_pci_dss_4/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_pci_dss_4/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_pci_dss_4/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_pci_dss_4/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/compliance_pci_dss_4/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_governance_appi_gdpr/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_governance_appi_gdpr/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_governance_appi_gdpr/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_governance_appi_gdpr/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_governance_appi_gdpr/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_governance_appi_gdpr/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_nosql_jsonschema/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_nosql_jsonschema/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_nosql_jsonschema/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_nosql_jsonschema/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_nosql_jsonschema/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_nosql_jsonschema/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_relational_iso_sql/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_relational_iso_sql/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_relational_iso_sql/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_relational_iso_sql/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_relational_iso_sql/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/data_relational_iso_sql/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ddd_domain_driven_design/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ddd_domain_driven_design/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ddd_domain_driven_design/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ddd_domain_driven_design/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ddd_domain_driven_design/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ddd_domain_driven_design/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/dora_sre_metrics/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/dora_sre_metrics/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/dora_sre_metrics/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/dora_sre_metrics/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/dora_sre_metrics/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/dora_sre_metrics/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/i18n_unicode_cldr/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/i18n_unicode_cldr/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/i18n_unicode_cldr/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/i18n_unicode_cldr/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/i18n_unicode_cldr/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/i18n_unicode_cldr/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ml_model_cards/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ml_model_cards/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ml_model_cards/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ml_model_cards/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ml_model_cards/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ml_model_cards/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_a11y_native/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_a11y_native/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_a11y_native/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_a11y_native/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_a11y_native/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_a11y_native/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_android_material3/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_android_material3/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_android_material3/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_android_material3/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_android_material3/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_android_material3/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_ios_hig/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_ios_hig/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_ios_hig/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_ios_hig/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_ios_hig/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_ios_hig/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_security_masvs/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_security_masvs/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_security_masvs/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_security_masvs/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_security_masvs/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/mobile_security_masvs/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_cicd_pipeline/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_cicd_pipeline/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_cicd_pipeline/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_cicd_pipeline/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_cicd_pipeline/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_cicd_pipeline/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_iac_terraform/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_iac_terraform/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_iac_terraform/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_iac_terraform/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_iac_terraform/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_iac_terraform/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_kubernetes/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_kubernetes/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_kubernetes/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_kubernetes/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_kubernetes/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_kubernetes/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_observability_otel/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_observability_otel/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_observability_otel/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_observability_otel/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_observability_otel/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/ops_observability_otel/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_iso25010/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_iso25010/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_iso25010/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_iso25010/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_iso25010/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_iso25010/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_test_iso29119/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_test_iso29119/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_test_iso29119/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_test_iso29119/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_test_iso29119/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/process_test_iso29119/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/twelve_factor_app/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/twelve_factor_app/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/twelve_factor_app/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/twelve_factor_app/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/twelve_factor_app/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/twelve_factor_app/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_authn_webauthn/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_authn_webauthn/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_authn_webauthn/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_authn_webauthn/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_authn_webauthn/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_authn_webauthn/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_browser_compat/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_browser_compat/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_browser_compat/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_browser_compat/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_browser_compat/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_browser_compat/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_forms_html5/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_forms_html5/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_forms_html5/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_forms_html5/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_forms_html5/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_forms_html5/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_performance_core_web_vitals/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_performance_core_web_vitals/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_performance_core_web_vitals/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_performance_core_web_vitals/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_performance_core_web_vitals/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_performance_core_web_vitals/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_pwa_manifest/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_pwa_manifest/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_pwa_manifest/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_pwa_manifest/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_pwa_manifest/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_pwa_manifest/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_responsive/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_responsive/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_responsive/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_responsive/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_responsive/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_responsive/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_security_owasp/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_security_owasp/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_security_owasp/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_security_owasp/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_security_owasp/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_security_owasp/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_seo_schemaorg/coverage_matrix.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_seo_schemaorg/elicit_extend.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_seo_schemaorg/lexicon.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_seo_schemaorg/manifest.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_seo_schemaorg/recommended_kinds.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/lexicons/web_seo_schemaorg/severity_rules.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/codd_plugins/stack_map.yaml +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/docs/cookbook/cdp_browser/README.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.0}/docs/requirements/README.md +0 -0
- {codd_dev-2.13.0 → codd_dev-2.15.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.15.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,11 +153,12 @@ 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.
|
|
157
|
-
- **v2.
|
|
158
|
-
- **v2.
|
|
159
|
-
- **v2.
|
|
160
|
-
- **v2.
|
|
156
|
+
- **v2.15.0 (current)** — `kind: common` for shared infrastructure (cmd_467). Classify cross-cutting files (DB client, middleware, config) as `common` via `common_node_patterns:` glob or frontmatter. C5 amber −79.2% on dogfood LMS (125 → 26). `**` glob translator fix. See [CHANGELOG](CHANGELOG.md).
|
|
157
|
+
- **v2.14.0** — 8 structural gaps closed (cmd_466 dogfood). Sidecar `<test>.codd.yaml` with `verified_by:` (C6) / `axis_matrix:` (C9); lexicon schema SSoT; completeness_audit batch; `scan.exclude` bug fix (−52%); `codd dag verify --auto-repair`; elicit mock-AI sentinel; AI timeout 3600 s SSoT. Red 22 → 0.
|
|
158
|
+
- **v2.13.0** — Opt-out protection: `OptOutPolicy` requires `justification` + `expires_at`. Silent SKIP abolished; severity preserved.
|
|
159
|
+
- **v2.12.0** — Test-completeness gates: C7 amber promotion + C8 `ci_health` static check.
|
|
160
|
+
- **v2.11.0** — Sprint-less `codd implement` (`--design <path> --output <dir>` directly).
|
|
161
|
+
- **v2.16.0 (next)** — `codd fix [PHENOMENON]` — express a desired change in natural language; CoDD identifies affected design docs, updates them, updates implementation and tests, then verifies the DAG. Interactive mode included.
|
|
161
162
|
|
|
162
163
|
---
|
|
163
164
|
|
|
@@ -113,11 +113,12 @@ 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.
|
|
117
|
-
- **v2.
|
|
118
|
-
- **v2.
|
|
119
|
-
- **v2.
|
|
120
|
-
- **v2.
|
|
116
|
+
- **v2.15.0 (current)** — `kind: common` for shared infrastructure (cmd_467). Classify cross-cutting files (DB client, middleware, config) as `common` via `common_node_patterns:` glob or frontmatter. C5 amber −79.2% on dogfood LMS (125 → 26). `**` glob translator fix. See [CHANGELOG](CHANGELOG.md).
|
|
117
|
+
- **v2.14.0** — 8 structural gaps closed (cmd_466 dogfood). Sidecar `<test>.codd.yaml` with `verified_by:` (C6) / `axis_matrix:` (C9); lexicon schema SSoT; completeness_audit batch; `scan.exclude` bug fix (−52%); `codd dag verify --auto-repair`; elicit mock-AI sentinel; AI timeout 3600 s SSoT. Red 22 → 0.
|
|
118
|
+
- **v2.13.0** — Opt-out protection: `OptOutPolicy` requires `justification` + `expires_at`. Silent SKIP abolished; severity preserved.
|
|
119
|
+
- **v2.12.0** — Test-completeness gates: C7 amber promotion + C8 `ci_health` static check.
|
|
120
|
+
- **v2.11.0** — Sprint-less `codd implement` (`--design <path> --output <dir>` directly).
|
|
121
|
+
- **v2.16.0 (next)** — `codd fix [PHENOMENON]` — express a desired change in natural language; CoDD identifies affected design docs, updates them, updates implementation and tests, then verifies the DAG. Interactive mode included.
|
|
121
122
|
|
|
122
123
|
---
|
|
123
124
|
|
|
@@ -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
|
|
|
@@ -4940,6 +4961,20 @@ def dag_verify(project_path: str, check_names: tuple[str, ...], output_format: s
|
|
|
4940
4961
|
for result in opt_out_results:
|
|
4941
4962
|
click.echo(f" - {_dag_result_name(result)}: {_dag_result_message(result)}")
|
|
4942
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}")
|
|
4977
|
+
|
|
4943
4978
|
raise SystemExit(1 if failed_red else 0)
|
|
4944
4979
|
|
|
4945
4980
|
|
|
@@ -5240,6 +5275,9 @@ def _dag_result_details(result: Any) -> list[str]:
|
|
|
5240
5275
|
details.append(f"{key}: {rendered}")
|
|
5241
5276
|
else:
|
|
5242
5277
|
details.append(f"{key}: {value}")
|
|
5278
|
+
common_count = _dag_result_value(result, "common_node_count")
|
|
5279
|
+
if isinstance(common_count, int) and common_count > 0:
|
|
5280
|
+
details.append(f"common_node_count: {common_count}")
|
|
5243
5281
|
return details
|
|
5244
5282
|
|
|
5245
5283
|
|
|
@@ -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)
|
|
@@ -125,11 +125,14 @@ def load_dag_settings(project_root: Path, settings: dict[str, Any] | None = None
|
|
|
125
125
|
merged["test_suffixes"] = test_suffixes
|
|
126
126
|
_apply_scan_patterns(merged, project_config)
|
|
127
127
|
_apply_scan_patterns(merged, requested_settings)
|
|
128
|
+
_apply_common_node_patterns(merged, project_config)
|
|
129
|
+
_apply_common_node_patterns(merged, requested_settings)
|
|
128
130
|
merged["coherence"] = _coherence_settings(project_config, requested_settings)
|
|
129
131
|
merged["extraction"] = _extraction_settings(project_config, requested_settings)
|
|
130
132
|
merged.setdefault("design_doc_patterns", [])
|
|
131
133
|
merged.setdefault("impl_file_patterns", [])
|
|
132
134
|
merged.setdefault("test_file_patterns", [])
|
|
135
|
+
merged.setdefault("common_node_patterns", [])
|
|
133
136
|
# cmd_444 v2.11.0: implementation_plan.md is no longer the entry point.
|
|
134
137
|
# `codd implement` now takes design_node + output_paths directly. Any
|
|
135
138
|
# `plan_task_file` value present in legacy codd.yaml is silently ignored.
|
|
@@ -222,18 +225,27 @@ def _add_design_docs(dag: DAG, project_root: Path, settings: dict[str, Any]) ->
|
|
|
222
225
|
design_docs: dict[str, dict[str, Any]] = {}
|
|
223
226
|
aliases: dict[str, str] = {}
|
|
224
227
|
frontmatter_alias = _frontmatter_alias_settings(settings)
|
|
225
|
-
for md_path in _glob_project_paths(
|
|
228
|
+
for md_path in _glob_project_paths(
|
|
229
|
+
project_root,
|
|
230
|
+
settings.get("design_doc_patterns", []),
|
|
231
|
+
exclude_patterns=settings.get("scan_exclude_patterns"),
|
|
232
|
+
):
|
|
226
233
|
if not md_path.is_file():
|
|
227
234
|
continue
|
|
228
235
|
node_id = _relative_id(md_path, project_root)
|
|
229
236
|
metadata = extract_design_doc_metadata(md_path, frontmatter_alias=frontmatter_alias)
|
|
230
237
|
attributes = metadata.get("attributes") or {}
|
|
231
238
|
_validate_design_doc_journey_attributes(node_id, attributes)
|
|
239
|
+
node_kind = (
|
|
240
|
+
"common"
|
|
241
|
+
if _design_doc_declares_common(metadata.get("frontmatter"), attributes)
|
|
242
|
+
else "design_doc"
|
|
243
|
+
)
|
|
232
244
|
_add_node_once(
|
|
233
245
|
dag,
|
|
234
246
|
Node(
|
|
235
247
|
id=node_id,
|
|
236
|
-
kind=
|
|
248
|
+
kind=node_kind,
|
|
237
249
|
path=node_id,
|
|
238
250
|
attributes={
|
|
239
251
|
"frontmatter": metadata["frontmatter"],
|
|
@@ -256,7 +268,13 @@ def _add_impl_files(dag: DAG, project_root: Path, settings: dict[str, Any]) -> d
|
|
|
256
268
|
impl_nodes: dict[str, Path] = {}
|
|
257
269
|
capability_patterns = _capability_patterns(settings)
|
|
258
270
|
implementation_suffixes = _suffix_tuple(settings.get("implementation_suffixes")) or LEGACY_IMPLEMENTATION_SUFFIXES
|
|
259
|
-
|
|
271
|
+
common_patterns = _common_node_patterns(settings)
|
|
272
|
+
project_root_resolved = Path(project_root).resolve()
|
|
273
|
+
for file_path in _glob_project_paths(
|
|
274
|
+
project_root,
|
|
275
|
+
settings.get("impl_file_patterns", []),
|
|
276
|
+
exclude_patterns=settings.get("scan_exclude_patterns"),
|
|
277
|
+
):
|
|
260
278
|
if (
|
|
261
279
|
not file_path.is_file()
|
|
262
280
|
or file_path.suffix not in implementation_suffixes
|
|
@@ -265,11 +283,16 @@ def _add_impl_files(dag: DAG, project_root: Path, settings: dict[str, Any]) -> d
|
|
|
265
283
|
continue
|
|
266
284
|
node_id = _relative_id(file_path, project_root)
|
|
267
285
|
impl_nodes[node_id] = file_path.resolve()
|
|
286
|
+
kind = "impl_file"
|
|
287
|
+
if common_patterns and _path_matches_any_pattern(
|
|
288
|
+
file_path, project_root_resolved, common_patterns
|
|
289
|
+
):
|
|
290
|
+
kind = "common"
|
|
268
291
|
_add_node_once(
|
|
269
292
|
dag,
|
|
270
293
|
Node(
|
|
271
294
|
id=node_id,
|
|
272
|
-
kind=
|
|
295
|
+
kind=kind,
|
|
273
296
|
path=node_id,
|
|
274
297
|
attributes={
|
|
275
298
|
"language": _language_for_path(file_path),
|
|
@@ -284,16 +307,27 @@ def _add_impl_files(dag: DAG, project_root: Path, settings: dict[str, Any]) -> d
|
|
|
284
307
|
def _add_test_files(dag: DAG, project_root: Path, settings: dict[str, Any]) -> dict[str, Path]:
|
|
285
308
|
test_nodes: dict[str, Path] = {}
|
|
286
309
|
test_suffixes = _suffix_tuple(settings.get("test_suffixes")) or LEGACY_TEST_SUFFIXES
|
|
287
|
-
|
|
310
|
+
common_patterns = _common_node_patterns(settings)
|
|
311
|
+
project_root_resolved = Path(project_root).resolve()
|
|
312
|
+
for file_path in _glob_project_paths(
|
|
313
|
+
project_root,
|
|
314
|
+
settings.get("test_file_patterns", []),
|
|
315
|
+
exclude_patterns=settings.get("scan_exclude_patterns"),
|
|
316
|
+
):
|
|
288
317
|
if not file_path.is_file() or file_path.suffix not in test_suffixes or not _is_test_file(file_path, project_root):
|
|
289
318
|
continue
|
|
290
319
|
node_id = _relative_id(file_path, project_root)
|
|
291
320
|
test_nodes[node_id] = file_path.resolve()
|
|
321
|
+
kind = "test_file"
|
|
322
|
+
if common_patterns and _path_matches_any_pattern(
|
|
323
|
+
file_path, project_root_resolved, common_patterns
|
|
324
|
+
):
|
|
325
|
+
kind = "common"
|
|
292
326
|
_add_node_once(
|
|
293
327
|
dag,
|
|
294
328
|
Node(
|
|
295
329
|
id=node_id,
|
|
296
|
-
kind=
|
|
330
|
+
kind=kind,
|
|
297
331
|
path=node_id,
|
|
298
332
|
attributes={
|
|
299
333
|
"language": _language_for_path(file_path),
|
|
@@ -1067,7 +1101,11 @@ def _alias_candidates(import_ref: str, project_root: Path, aliases: dict[str, li
|
|
|
1067
1101
|
return candidates
|
|
1068
1102
|
|
|
1069
1103
|
|
|
1070
|
-
def _glob_project_paths(
|
|
1104
|
+
def _glob_project_paths(
|
|
1105
|
+
project_root: Path,
|
|
1106
|
+
patterns: Any,
|
|
1107
|
+
exclude_patterns: Any = None,
|
|
1108
|
+
) -> list[Path]:
|
|
1071
1109
|
paths: dict[str, Path] = {}
|
|
1072
1110
|
for pattern in _as_list(patterns):
|
|
1073
1111
|
if not isinstance(pattern, str) or not pattern:
|
|
@@ -1075,7 +1113,85 @@ def _glob_project_paths(project_root: Path, patterns: Any) -> list[Path]:
|
|
|
1075
1113
|
for expanded in _expand_braces(pattern):
|
|
1076
1114
|
for path in project_root.glob(expanded):
|
|
1077
1115
|
paths[str(path.resolve())] = path.resolve()
|
|
1078
|
-
|
|
1116
|
+
excludes = [
|
|
1117
|
+
str(pattern)
|
|
1118
|
+
for pattern in _as_list(exclude_patterns)
|
|
1119
|
+
if isinstance(pattern, str) and pattern.strip()
|
|
1120
|
+
]
|
|
1121
|
+
if not excludes:
|
|
1122
|
+
return [paths[key] for key in sorted(paths)]
|
|
1123
|
+
project_root_resolved = project_root.resolve()
|
|
1124
|
+
filtered: list[Path] = []
|
|
1125
|
+
for key in sorted(paths):
|
|
1126
|
+
path = paths[key]
|
|
1127
|
+
if _path_matches_any_pattern(path, project_root_resolved, excludes):
|
|
1128
|
+
continue
|
|
1129
|
+
filtered.append(path)
|
|
1130
|
+
return filtered
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
|
+
def _path_matches_any_pattern(
|
|
1134
|
+
path: Path,
|
|
1135
|
+
project_root: Path,
|
|
1136
|
+
patterns: list[str],
|
|
1137
|
+
) -> bool:
|
|
1138
|
+
try:
|
|
1139
|
+
relative = path.resolve().relative_to(project_root)
|
|
1140
|
+
except ValueError:
|
|
1141
|
+
return False
|
|
1142
|
+
rel_text = relative.as_posix()
|
|
1143
|
+
|
|
1144
|
+
for pattern in patterns:
|
|
1145
|
+
if _glob_pattern_to_regex(pattern).match(rel_text):
|
|
1146
|
+
return True
|
|
1147
|
+
return False
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
_GLOB_REGEX_CACHE: dict[str, "re.Pattern[str]"] = {}
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
def _glob_pattern_to_regex(pattern: str) -> "re.Pattern[str]":
|
|
1154
|
+
"""Translate a glob pattern (with ``**`` recursion) into a regex.
|
|
1155
|
+
|
|
1156
|
+
Recognised tokens:
|
|
1157
|
+
|
|
1158
|
+
* ``**/`` — zero or more path segments (greedy across separators).
|
|
1159
|
+
* ``**`` — anything (including ``/``); used at end of a pattern.
|
|
1160
|
+
* ``*`` — any chars except ``/``.
|
|
1161
|
+
* ``?`` — single char except ``/``.
|
|
1162
|
+
* Anything else — literal.
|
|
1163
|
+
|
|
1164
|
+
Patterns such as ``**/dist/**`` match a path containing ``dist`` at any
|
|
1165
|
+
depth, ``src/lib/**/*.ts`` matches both ``src/lib/x.ts`` and
|
|
1166
|
+
``src/lib/sub/x.ts``.
|
|
1167
|
+
"""
|
|
1168
|
+
|
|
1169
|
+
cached = _GLOB_REGEX_CACHE.get(pattern)
|
|
1170
|
+
if cached is not None:
|
|
1171
|
+
return cached
|
|
1172
|
+
|
|
1173
|
+
parts: list[str] = []
|
|
1174
|
+
i = 0
|
|
1175
|
+
n = len(pattern)
|
|
1176
|
+
while i < n:
|
|
1177
|
+
if pattern[i : i + 3] == "**/":
|
|
1178
|
+
parts.append("(?:[^/]+/)*")
|
|
1179
|
+
i += 3
|
|
1180
|
+
elif pattern[i : i + 2] == "**":
|
|
1181
|
+
parts.append(".*")
|
|
1182
|
+
i += 2
|
|
1183
|
+
elif pattern[i] == "*":
|
|
1184
|
+
parts.append("[^/]*")
|
|
1185
|
+
i += 1
|
|
1186
|
+
elif pattern[i] == "?":
|
|
1187
|
+
parts.append("[^/]")
|
|
1188
|
+
i += 1
|
|
1189
|
+
else:
|
|
1190
|
+
parts.append(re.escape(pattern[i]))
|
|
1191
|
+
i += 1
|
|
1192
|
+
compiled = re.compile("^" + "".join(parts) + "$")
|
|
1193
|
+
_GLOB_REGEX_CACHE[pattern] = compiled
|
|
1194
|
+
return compiled
|
|
1079
1195
|
|
|
1080
1196
|
|
|
1081
1197
|
def _expand_braces(pattern: str) -> list[str]:
|
|
@@ -1287,6 +1403,80 @@ def _capability_patterns(settings: dict[str, Any]) -> dict[str, Any]:
|
|
|
1287
1403
|
return patterns if isinstance(patterns, dict) else {}
|
|
1288
1404
|
|
|
1289
1405
|
|
|
1406
|
+
def _apply_common_node_patterns(settings: dict[str, Any], config: dict[str, Any]) -> None:
|
|
1407
|
+
"""Capture ``common_node_patterns`` from project / requested config.
|
|
1408
|
+
|
|
1409
|
+
Recognises both ``common_node_patterns:`` at the top level (preferred,
|
|
1410
|
+
sibling of ``scan:``) and ``scan.common_node_patterns:`` (nested under
|
|
1411
|
+
scan for users who prefer to colocate scan-related knobs). Both feed
|
|
1412
|
+
the same ``settings['common_node_patterns']`` list.
|
|
1413
|
+
"""
|
|
1414
|
+
|
|
1415
|
+
if not isinstance(config, dict):
|
|
1416
|
+
return
|
|
1417
|
+
patterns: list[str] = []
|
|
1418
|
+
top = config.get("common_node_patterns")
|
|
1419
|
+
if isinstance(top, list):
|
|
1420
|
+
patterns.extend(
|
|
1421
|
+
str(item) for item in top if isinstance(item, str) and item.strip()
|
|
1422
|
+
)
|
|
1423
|
+
scan = config.get("scan")
|
|
1424
|
+
if isinstance(scan, dict):
|
|
1425
|
+
nested = scan.get("common_node_patterns")
|
|
1426
|
+
if isinstance(nested, list):
|
|
1427
|
+
patterns.extend(
|
|
1428
|
+
str(item) for item in nested if isinstance(item, str) and item.strip()
|
|
1429
|
+
)
|
|
1430
|
+
if patterns:
|
|
1431
|
+
_extend_unique(settings, "common_node_patterns", patterns)
|
|
1432
|
+
|
|
1433
|
+
|
|
1434
|
+
def _design_doc_declares_common(
|
|
1435
|
+
frontmatter: Any, attributes: Any
|
|
1436
|
+
) -> bool:
|
|
1437
|
+
"""Return True when a design doc opts into ``kind="common"`` via frontmatter.
|
|
1438
|
+
|
|
1439
|
+
Recognised keys (any one wins):
|
|
1440
|
+
* ``codd.node_type`` (preferred, lives under the ``codd:`` block)
|
|
1441
|
+
* top-level ``node_type`` (legacy / convenience)
|
|
1442
|
+
"""
|
|
1443
|
+
|
|
1444
|
+
for source in (frontmatter, attributes):
|
|
1445
|
+
if not isinstance(source, dict):
|
|
1446
|
+
continue
|
|
1447
|
+
node_type = source.get("node_type")
|
|
1448
|
+
if isinstance(node_type, str) and node_type.strip().lower() == "common":
|
|
1449
|
+
return True
|
|
1450
|
+
codd_block = source.get("codd")
|
|
1451
|
+
if isinstance(codd_block, dict):
|
|
1452
|
+
value = codd_block.get("node_type")
|
|
1453
|
+
if isinstance(value, str) and value.strip().lower() == "common":
|
|
1454
|
+
return True
|
|
1455
|
+
return False
|
|
1456
|
+
|
|
1457
|
+
|
|
1458
|
+
def _common_node_patterns(settings: dict[str, Any]) -> list[str]:
|
|
1459
|
+
"""Return glob patterns that should be classified as ``kind='common'``.
|
|
1460
|
+
|
|
1461
|
+
Common nodes represent shared infrastructure (DB clients, middleware,
|
|
1462
|
+
framework config, generated artifacts) that exist outside any single
|
|
1463
|
+
design document's scope. They participate in the DAG so that change
|
|
1464
|
+
impact can be traced, but they are exempt from C5 transitive_closure
|
|
1465
|
+
unreachable_nodes since requiring every common file to have a parent
|
|
1466
|
+
design_doc would force the entire codebase to be re-modelled as a tree.
|
|
1467
|
+
"""
|
|
1468
|
+
|
|
1469
|
+
raw = settings.get("common_node_patterns")
|
|
1470
|
+
if not isinstance(raw, list):
|
|
1471
|
+
return []
|
|
1472
|
+
expanded: list[str] = []
|
|
1473
|
+
for pattern in raw:
|
|
1474
|
+
if not isinstance(pattern, str) or not pattern.strip():
|
|
1475
|
+
continue
|
|
1476
|
+
expanded.extend(_expand_braces(pattern.strip()))
|
|
1477
|
+
return expanded
|
|
1478
|
+
|
|
1479
|
+
|
|
1290
1480
|
def _runtime_evidence_for_file(file_path: Path, node_id: str, capability_patterns: dict[str, Any]) -> list[dict]:
|
|
1291
1481
|
evidence = scan_capability_evidence(file_path, capability_patterns)
|
|
1292
1482
|
absolute_prefix = f"{file_path.as_posix()}:"
|
|
@@ -1306,6 +1496,11 @@ def _apply_scan_patterns(settings: dict[str, Any], config: dict[str, Any]) -> No
|
|
|
1306
1496
|
source_dirs = _as_list(scan.get("source_dirs"))
|
|
1307
1497
|
test_dirs = _as_list(scan.get("test_dirs"))
|
|
1308
1498
|
doc_dirs = _as_list(scan.get("doc_dirs"))
|
|
1499
|
+
exclude_patterns = [
|
|
1500
|
+
str(pattern)
|
|
1501
|
+
for pattern in _as_list(scan.get("exclude"))
|
|
1502
|
+
if isinstance(pattern, str) and pattern.strip()
|
|
1503
|
+
]
|
|
1309
1504
|
|
|
1310
1505
|
if source_dirs:
|
|
1311
1506
|
_extend_unique(
|
|
@@ -1324,6 +1519,8 @@ def _apply_scan_patterns(settings: dict[str, Any], config: dict[str, Any]) -> No
|
|
|
1324
1519
|
)
|
|
1325
1520
|
if doc_dirs:
|
|
1326
1521
|
_extend_unique(settings, "design_doc_patterns", _file_patterns_for_dirs(doc_dirs, (".md",)))
|
|
1522
|
+
if exclude_patterns:
|
|
1523
|
+
_extend_unique(settings, "scan_exclude_patterns", exclude_patterns)
|
|
1327
1524
|
|
|
1328
1525
|
|
|
1329
1526
|
def _normalize_dag_section(section: dict[str, Any]) -> dict[str, Any]:
|
|
@@ -15,12 +15,20 @@ class TransitiveClosureResult:
|
|
|
15
15
|
check_name: str = "transitive_closure"
|
|
16
16
|
severity: str = "amber"
|
|
17
17
|
unreachable_nodes: list[str] = field(default_factory=list)
|
|
18
|
+
common_node_count: int = 0
|
|
18
19
|
passed: bool = True
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
@register_dag_check("transitive_closure")
|
|
22
23
|
class TransitiveClosureCheck:
|
|
23
|
-
"""Report nodes unreachable from root design docs without blocking deploy.
|
|
24
|
+
"""Report nodes unreachable from root design docs without blocking deploy.
|
|
25
|
+
|
|
26
|
+
Nodes with ``kind == "common"`` (shared infrastructure declared via
|
|
27
|
+
``common_node_patterns`` or frontmatter ``node_type: common``) are exempt
|
|
28
|
+
from unreachable detection. They participate in the DAG so change-impact
|
|
29
|
+
analysis still sees them, but they do not need to be the descendant of a
|
|
30
|
+
single design document.
|
|
31
|
+
"""
|
|
24
32
|
|
|
25
33
|
def __init__(self, dag=None, project_root: Path | None = None, settings: dict[str, Any] | None = None):
|
|
26
34
|
self.dag = dag
|
|
@@ -45,8 +53,19 @@ class TransitiveClosureCheck:
|
|
|
45
53
|
]
|
|
46
54
|
|
|
47
55
|
visited = self._reachable_from(dag, roots)
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
common_count = sum(
|
|
57
|
+
1 for node in dag.nodes.values() if node.kind == "common"
|
|
58
|
+
)
|
|
59
|
+
unreachable = [
|
|
60
|
+
node_id
|
|
61
|
+
for node_id, node in dag.nodes.items()
|
|
62
|
+
if node_id not in visited and node.kind != "common"
|
|
63
|
+
]
|
|
64
|
+
return TransitiveClosureResult(
|
|
65
|
+
unreachable_nodes=unreachable,
|
|
66
|
+
common_node_count=common_count,
|
|
67
|
+
passed=True,
|
|
68
|
+
)
|
|
50
69
|
|
|
51
70
|
def _reachable_from(self, dag, roots: list[str]) -> set[str]:
|
|
52
71
|
visited: set[str] = set()
|