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.
Files changed (469) hide show
  1. {codd_dev-2.12.0 → codd_dev-2.13.0}/PKG-INFO +4 -3
  2. {codd_dev-2.12.0 → codd_dev-2.13.0}/README.md +3 -2
  3. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/cli.py +20 -2
  4. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/coverage_metrics.py +11 -1
  5. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/__init__.py +41 -1
  6. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/ci_health.py +68 -8
  7. codd_dev-2.13.0/codd/dag/checks/opt_out.py +265 -0
  8. codd_dev-2.13.0/codd/dag/runner.py +146 -0
  9. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployer.py +25 -4
  10. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/validator.py +30 -0
  11. {codd_dev-2.12.0 → codd_dev-2.13.0}/pyproject.toml +1 -1
  12. codd_dev-2.12.0/codd/dag/runner.py +0 -79
  13. {codd_dev-2.12.0 → codd_dev-2.13.0}/.gitignore +0 -0
  14. {codd_dev-2.12.0 → codd_dev-2.13.0}/LICENSE +0 -0
  15. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/__init__.py +0 -0
  16. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/__main__.py +0 -0
  17. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/_git_helper.py +0 -0
  18. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/ask_user_question_adapter.py +0 -0
  19. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/assembler.py +0 -0
  20. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/bridge.py +0 -0
  21. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/brownfield/__init__.py +0 -0
  22. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/brownfield/pipeline.py +0 -0
  23. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/clustering.py +0 -0
  24. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/coherence_adapters.py +0 -0
  25. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/coherence_engine.py +0 -0
  26. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/config.py +0 -0
  27. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/contracts.py +0 -0
  28. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/coverage_auditor.py +0 -0
  29. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/__init__.py +0 -0
  30. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/builder.py +0 -0
  31. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/depends_on_consistency.py +0 -0
  32. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/deployment_completeness.py +0 -0
  33. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/edge_validity.py +0 -0
  34. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/environment_coverage.py +0 -0
  35. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/implementation_coverage.py +0 -0
  36. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/node_completeness.py +0 -0
  37. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/task_completion.py +0 -0
  38. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/transitive_closure.py +0 -0
  39. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/checks/user_journey_coherence.py +0 -0
  40. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/coverage_axes.py +0 -0
  41. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/cli.yaml +0 -0
  42. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/cpp_embedded.yaml +0 -0
  43. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/csharp.yaml +0 -0
  44. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/elixir.yaml +0 -0
  45. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/generic.yaml +0 -0
  46. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/iot.yaml +0 -0
  47. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/java.yaml +0 -0
  48. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/kotlin.yaml +0 -0
  49. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/mobile.yaml +0 -0
  50. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/ruby.yaml +0 -0
  51. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/rust.yaml +0 -0
  52. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/scala.yaml +0 -0
  53. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/swift.yaml +0 -0
  54. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/test_frameworks.yaml +0 -0
  55. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/defaults/web.yaml +0 -0
  56. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/dag/extractor.py +0 -0
  57. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/defaults.yaml +0 -0
  58. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deploy_targets/__init__.py +0 -0
  59. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deploy_targets/app_service.py +0 -0
  60. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deploy_targets/base.py +0 -0
  61. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deploy_targets/docker_compose.py +0 -0
  62. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/__init__.py +0 -0
  63. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/checks/__init__.py +0 -0
  64. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/defaults/deploy_targets.yaml +0 -0
  65. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/defaults/runtime_capability_inference.yaml +0 -0
  66. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/defaults/schema_providers.yaml +0 -0
  67. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/defaults/verification_templates.yaml +0 -0
  68. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/extractor.py +0 -0
  69. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/__init__.py +0 -0
  70. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/ai_command.py +0 -0
  71. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/llm_consideration.py +0 -0
  72. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/schema/__init__.py +0 -0
  73. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/schema/prisma.py +0 -0
  74. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/target/__init__.py +0 -0
  75. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/target/docker_compose.py +0 -0
  76. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/__init__.py +0 -0
  77. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/assertion_handlers.py +0 -0
  78. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_browser.py +0 -0
  79. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_engines.py +0 -0
  80. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_launchers.py +0 -0
  81. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_wire.py +0 -0
  82. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/curl.py +0 -0
  83. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/form_strategies.py +0 -0
  84. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/means_catalog.py +0 -0
  85. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/playwright.py +0 -0
  86. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/design_md.py +0 -0
  87. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/diff/__init__.py +0 -0
  88. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/diff/apply.py +0 -0
  89. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/diff/engine.py +0 -0
  90. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/diff/persistence.py +0 -0
  91. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/diff/templates/diff_prompt.md +0 -0
  92. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/drift.py +0 -0
  93. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/e2e_extractor.py +0 -0
  94. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/e2e_generator.py +0 -0
  95. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/e2e_runner.py +0 -0
  96. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/__init__.py +0 -0
  97. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/apply.py +0 -0
  98. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/engine.py +0 -0
  99. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/finding.py +0 -0
  100. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/formatters/__init__.py +0 -0
  101. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/formatters/base.py +0 -0
  102. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/formatters/interactive.py +0 -0
  103. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/formatters/json_fmt.py +0 -0
  104. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/formatters/md.py +0 -0
  105. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/lexicon_loader.py +0 -0
  106. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/persistence.py +0 -0
  107. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/elicit/templates/elicit_prompt_L0.md +0 -0
  108. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/env_refs.py +0 -0
  109. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/extract_ai.py +0 -0
  110. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/extractor.py +0 -0
  111. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixer.py +0 -0
  112. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixup_drift.py +0 -0
  113. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/__init__.py +0 -0
  114. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/design_token_drift.py +0 -0
  115. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/lexicon_violation.py +0 -0
  116. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/url_drift.py +0 -0
  117. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/generator.py +0 -0
  118. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/graph.py +0 -0
  119. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hitl_session.py +0 -0
  120. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/__init__.py +0 -0
  121. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/pre-commit +0 -0
  122. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/recipes/claude_settings_example.json +0 -0
  123. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/recipes/codex_hook.sh +0 -0
  124. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/recipes/git_post_commit.sh +0 -0
  125. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/hooks/recipes/git_pre_commit.sh +0 -0
  126. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/implementer/__init__.py +0 -0
  127. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/implementer/chunked_runner.py +0 -0
  128. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/implementer/typecheck_loop.py +0 -0
  129. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/implementer.py +0 -0
  130. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/inheritance.py +0 -0
  131. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/init/__init__.py +0 -0
  132. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/init/lexicon_suggest.py +0 -0
  133. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/init/llm_lexicon_suggester.py +0 -0
  134. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/init/stack_detector.py +0 -0
  135. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/knowledge_fetcher.py +0 -0
  136. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon.py +0 -0
  137. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/__init__.py +0 -0
  138. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/__init__.py +0 -0
  139. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/html.py +0 -0
  140. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/json_fmt.py +0 -0
  141. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/md.py +0 -0
  142. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/inspector.py +0 -0
  143. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/manager.py +0 -0
  144. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/reporter.py +0 -0
  145. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/lexicon_cli/threshold.py +0 -0
  146. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/__init__.py +0 -0
  147. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/approval.py +0 -0
  148. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/best_practice_augmenter.py +0 -0
  149. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/criteria_expander.py +0 -0
  150. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/design_doc_extractor.py +0 -0
  151. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/impl_step_deriver.py +0 -0
  152. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/means_catalog_loader.py +0 -0
  153. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/parser.py +0 -0
  154. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/plan_deriver.py +0 -0
  155. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/prompt_builder.py +0 -0
  156. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/strategy_validator.py +0 -0
  157. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/best_practice_augment_meta.md +0 -0
  158. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/criteria_expand_meta.md +0 -0
  159. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/design_doc_extract_meta.md +0 -0
  160. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/impl_step_derive_meta.md +0 -0
  161. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/implementation_step_catalog.yaml +0 -0
  162. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/meta_instruction.md +0 -0
  163. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/plan_derive_meta.md +0 -0
  164. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/llm/templates/verification_means_catalog.yaml +0 -0
  165. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/mcp_server.py +0 -0
  166. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/measure.py +0 -0
  167. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/parsing.py +0 -0
  168. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/planner.py +0 -0
  169. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/policy.py +0 -0
  170. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/preflight/__init__.py +0 -0
  171. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/preflight/defaults/cli.yaml +0 -0
  172. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/preflight/defaults/iot.yaml +0 -0
  173. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/preflight/defaults/mobile.yaml +0 -0
  174. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/preflight/defaults/web.yaml +0 -0
  175. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/propagate.py +0 -0
  176. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/propagator.py +0 -0
  177. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/registry.py +0 -0
  178. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/__init__.py +0 -0
  179. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/approval_repair.py +0 -0
  180. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/engine.py +0 -0
  181. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/git_patcher.py +0 -0
  182. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/history.py +0 -0
  183. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/llm_repair_engine.py +0 -0
  184. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/loop.py +0 -0
  185. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/primary_picker.py +0 -0
  186. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/proof_breaks.py +0 -0
  187. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/repair_result.py +0 -0
  188. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/repairability_classifier.py +0 -0
  189. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/schema.py +0 -0
  190. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/templates/analyze_meta.md +0 -0
  191. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/templates/propose_meta.md +0 -0
  192. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/templates/repair_strategy_meta.md +0 -0
  193. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/templates/repairability_meta.md +0 -0
  194. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair/verify_runner.py +0 -0
  195. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/repair_slice.py +0 -0
  196. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/require.py +0 -0
  197. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/require_plugins.py +0 -0
  198. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/require_propagate.py +0 -0
  199. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/cli.yaml +0 -0
  200. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/iot.yaml +0 -0
  201. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/mobile.yaml +0 -0
  202. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/web.yaml +0 -0
  203. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/required_artifacts_deriver.py +0 -0
  204. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/cli.yaml +0 -0
  205. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/iot.yaml +0 -0
  206. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/mobile.yaml +0 -0
  207. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/web.yaml +0 -0
  208. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/requirement_completeness_auditor.py +0 -0
  209. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/restore.py +0 -0
  210. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/routes_extractor.py +0 -0
  211. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/scanner.py +0 -0
  212. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/schema_refs.py +0 -0
  213. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/screen_flow_validator.py +0 -0
  214. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/screen_transition_extractor.py +0 -0
  215. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/screen_transitions/defaults.yaml +0 -0
  216. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/synth.py +0 -0
  217. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/codd.yaml.tmpl +0 -0
  218. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/conventions.yaml.tmpl +0 -0
  219. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/data_dependencies.yaml.tmpl +0 -0
  220. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/doc_links.yaml.tmpl +0 -0
  221. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extract_ai_prompt_baseline.md +0 -0
  222. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extracted/api-contract.md.j2 +0 -0
  223. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extracted/architecture-overview.md.j2 +0 -0
  224. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extracted/module-detail.md.j2 +0 -0
  225. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extracted/schema-design.md.j2 +0 -0
  226. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/extracted/system-context.md.j2 +0 -0
  227. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/gitignore.tmpl +0 -0
  228. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/lexicon_questions.md +0 -0
  229. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/lexicon_schema.yaml +0 -0
  230. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/templates/overrides.yaml.tmpl +0 -0
  231. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/traceability.py +0 -0
  232. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/__init__.py +0 -0
  233. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/events.py +0 -0
  234. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/propagation_log.py +0 -0
  235. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/propagation_pipeline.py +0 -0
  236. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/test_runner.py +0 -0
  237. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/watch/watcher.py +0 -0
  238. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd/wiring.py +0 -0
  239. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/coverage_matrix.md +0 -0
  240. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/elicit_extend.md +0 -0
  241. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/lexicon.yaml +0 -0
  242. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/manifest.yaml +0 -0
  243. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/recommended_kinds.yaml +0 -0
  244. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/severity_rules.yaml +0 -0
  245. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/coverage_matrix.md +0 -0
  246. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/elicit_extend.md +0 -0
  247. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/lexicon.yaml +0 -0
  248. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/manifest.yaml +0 -0
  249. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/recommended_kinds.yaml +0 -0
  250. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/severity_rules.yaml +0 -0
  251. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/coverage_matrix.md +0 -0
  252. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/elicit_extend.md +0 -0
  253. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/lexicon.yaml +0 -0
  254. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/manifest.yaml +0 -0
  255. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/recommended_kinds.yaml +0 -0
  256. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/severity_rules.yaml +0 -0
  257. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/elicit_extend.md +0 -0
  258. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/lexicon.yaml +0 -0
  259. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/manifest.yaml +0 -0
  260. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/recommended_kinds.yaml +0 -0
  261. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/severity_rules.yaml +0 -0
  262. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/coverage_matrix.md +0 -0
  263. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/elicit_extend.md +0 -0
  264. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/lexicon.yaml +0 -0
  265. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/manifest.yaml +0 -0
  266. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/recommended_kinds.yaml +0 -0
  267. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/severity_rules.yaml +0 -0
  268. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/coverage_matrix.md +0 -0
  269. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/elicit_extend.md +0 -0
  270. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/lexicon.yaml +0 -0
  271. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/manifest.yaml +0 -0
  272. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/recommended_kinds.yaml +0 -0
  273. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/severity_rules.yaml +0 -0
  274. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/coverage_matrix.md +0 -0
  275. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/elicit_extend.md +0 -0
  276. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/lexicon.yaml +0 -0
  277. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/manifest.yaml +0 -0
  278. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/recommended_kinds.yaml +0 -0
  279. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/severity_rules.yaml +0 -0
  280. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/coverage_matrix.md +0 -0
  281. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/elicit_extend.md +0 -0
  282. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/lexicon.yaml +0 -0
  283. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/manifest.yaml +0 -0
  284. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/recommended_kinds.yaml +0 -0
  285. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/severity_rules.yaml +0 -0
  286. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/coverage_matrix.md +0 -0
  287. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/elicit_extend.md +0 -0
  288. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/lexicon.yaml +0 -0
  289. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/manifest.yaml +0 -0
  290. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/recommended_kinds.yaml +0 -0
  291. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/severity_rules.yaml +0 -0
  292. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/coverage_matrix.md +0 -0
  293. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/elicit_extend.md +0 -0
  294. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/lexicon.yaml +0 -0
  295. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/manifest.yaml +0 -0
  296. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/recommended_kinds.yaml +0 -0
  297. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/severity_rules.yaml +0 -0
  298. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/coverage_matrix.md +0 -0
  299. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/elicit_extend.md +0 -0
  300. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/lexicon.yaml +0 -0
  301. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/manifest.yaml +0 -0
  302. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/recommended_kinds.yaml +0 -0
  303. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/severity_rules.yaml +0 -0
  304. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/coverage_matrix.md +0 -0
  305. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/elicit_extend.md +0 -0
  306. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/lexicon.yaml +0 -0
  307. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/manifest.yaml +0 -0
  308. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/recommended_kinds.yaml +0 -0
  309. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/severity_rules.yaml +0 -0
  310. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/coverage_matrix.md +0 -0
  311. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/elicit_extend.md +0 -0
  312. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/lexicon.yaml +0 -0
  313. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/manifest.yaml +0 -0
  314. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/recommended_kinds.yaml +0 -0
  315. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/severity_rules.yaml +0 -0
  316. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/coverage_matrix.md +0 -0
  317. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/elicit_extend.md +0 -0
  318. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/lexicon.yaml +0 -0
  319. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/manifest.yaml +0 -0
  320. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/recommended_kinds.yaml +0 -0
  321. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/severity_rules.yaml +0 -0
  322. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/coverage_matrix.md +0 -0
  323. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/elicit_extend.md +0 -0
  324. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/lexicon.yaml +0 -0
  325. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/manifest.yaml +0 -0
  326. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/recommended_kinds.yaml +0 -0
  327. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/severity_rules.yaml +0 -0
  328. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/coverage_matrix.md +0 -0
  329. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/elicit_extend.md +0 -0
  330. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/lexicon.yaml +0 -0
  331. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/manifest.yaml +0 -0
  332. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/recommended_kinds.yaml +0 -0
  333. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/severity_rules.yaml +0 -0
  334. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/coverage_matrix.md +0 -0
  335. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/elicit_extend.md +0 -0
  336. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/lexicon.yaml +0 -0
  337. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/manifest.yaml +0 -0
  338. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/recommended_kinds.yaml +0 -0
  339. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/severity_rules.yaml +0 -0
  340. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/coverage_matrix.md +0 -0
  341. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/elicit_extend.md +0 -0
  342. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/lexicon.yaml +0 -0
  343. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/manifest.yaml +0 -0
  344. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/recommended_kinds.yaml +0 -0
  345. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/severity_rules.yaml +0 -0
  346. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/coverage_matrix.md +0 -0
  347. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/elicit_extend.md +0 -0
  348. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/lexicon.yaml +0 -0
  349. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/manifest.yaml +0 -0
  350. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/recommended_kinds.yaml +0 -0
  351. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/severity_rules.yaml +0 -0
  352. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/coverage_matrix.md +0 -0
  353. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/elicit_extend.md +0 -0
  354. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/lexicon.yaml +0 -0
  355. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/manifest.yaml +0 -0
  356. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/recommended_kinds.yaml +0 -0
  357. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/severity_rules.yaml +0 -0
  358. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/coverage_matrix.md +0 -0
  359. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/elicit_extend.md +0 -0
  360. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/lexicon.yaml +0 -0
  361. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/manifest.yaml +0 -0
  362. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/recommended_kinds.yaml +0 -0
  363. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/severity_rules.yaml +0 -0
  364. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/coverage_matrix.md +0 -0
  365. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/elicit_extend.md +0 -0
  366. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/lexicon.yaml +0 -0
  367. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/manifest.yaml +0 -0
  368. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/recommended_kinds.yaml +0 -0
  369. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/severity_rules.yaml +0 -0
  370. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/coverage_matrix.md +0 -0
  371. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/elicit_extend.md +0 -0
  372. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/lexicon.yaml +0 -0
  373. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/manifest.yaml +0 -0
  374. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/recommended_kinds.yaml +0 -0
  375. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/severity_rules.yaml +0 -0
  376. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/coverage_matrix.md +0 -0
  377. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/elicit_extend.md +0 -0
  378. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/lexicon.yaml +0 -0
  379. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/manifest.yaml +0 -0
  380. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/recommended_kinds.yaml +0 -0
  381. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/severity_rules.yaml +0 -0
  382. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/coverage_matrix.md +0 -0
  383. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/elicit_extend.md +0 -0
  384. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/lexicon.yaml +0 -0
  385. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/manifest.yaml +0 -0
  386. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/recommended_kinds.yaml +0 -0
  387. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/severity_rules.yaml +0 -0
  388. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/coverage_matrix.md +0 -0
  389. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/elicit_extend.md +0 -0
  390. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/lexicon.yaml +0 -0
  391. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/manifest.yaml +0 -0
  392. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/recommended_kinds.yaml +0 -0
  393. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/severity_rules.yaml +0 -0
  394. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/coverage_matrix.md +0 -0
  395. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/elicit_extend.md +0 -0
  396. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/lexicon.yaml +0 -0
  397. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/manifest.yaml +0 -0
  398. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/recommended_kinds.yaml +0 -0
  399. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/severity_rules.yaml +0 -0
  400. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/coverage_matrix.md +0 -0
  401. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/elicit_extend.md +0 -0
  402. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/lexicon.yaml +0 -0
  403. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/manifest.yaml +0 -0
  404. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/recommended_kinds.yaml +0 -0
  405. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/severity_rules.yaml +0 -0
  406. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/coverage_matrix.md +0 -0
  407. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/elicit_extend.md +0 -0
  408. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/lexicon.yaml +0 -0
  409. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/manifest.yaml +0 -0
  410. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/recommended_kinds.yaml +0 -0
  411. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/severity_rules.yaml +0 -0
  412. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/coverage_matrix.md +0 -0
  413. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/elicit_extend.md +0 -0
  414. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/lexicon.yaml +0 -0
  415. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/manifest.yaml +0 -0
  416. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/recommended_kinds.yaml +0 -0
  417. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/severity_rules.yaml +0 -0
  418. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/coverage_matrix.md +0 -0
  419. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/elicit_extend.md +0 -0
  420. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/lexicon.yaml +0 -0
  421. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/manifest.yaml +0 -0
  422. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/recommended_kinds.yaml +0 -0
  423. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/severity_rules.yaml +0 -0
  424. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/coverage_matrix.md +0 -0
  425. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/elicit_extend.md +0 -0
  426. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/lexicon.yaml +0 -0
  427. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/manifest.yaml +0 -0
  428. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/recommended_kinds.yaml +0 -0
  429. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/severity_rules.yaml +0 -0
  430. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/coverage_matrix.md +0 -0
  431. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/elicit_extend.md +0 -0
  432. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/lexicon.yaml +0 -0
  433. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/manifest.yaml +0 -0
  434. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/recommended_kinds.yaml +0 -0
  435. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/severity_rules.yaml +0 -0
  436. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/coverage_matrix.md +0 -0
  437. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/elicit_extend.md +0 -0
  438. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/lexicon.yaml +0 -0
  439. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/manifest.yaml +0 -0
  440. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/recommended_kinds.yaml +0 -0
  441. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/severity_rules.yaml +0 -0
  442. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/coverage_matrix.md +0 -0
  443. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/elicit_extend.md +0 -0
  444. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/lexicon.yaml +0 -0
  445. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/manifest.yaml +0 -0
  446. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/recommended_kinds.yaml +0 -0
  447. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/severity_rules.yaml +0 -0
  448. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/coverage_matrix.md +0 -0
  449. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/elicit_extend.md +0 -0
  450. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/lexicon.yaml +0 -0
  451. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/manifest.yaml +0 -0
  452. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/recommended_kinds.yaml +0 -0
  453. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/severity_rules.yaml +0 -0
  454. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/coverage_matrix.md +0 -0
  455. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/elicit_extend.md +0 -0
  456. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/lexicon.yaml +0 -0
  457. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/manifest.yaml +0 -0
  458. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/recommended_kinds.yaml +0 -0
  459. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/severity_rules.yaml +0 -0
  460. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/coverage_matrix.md +0 -0
  461. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/elicit_extend.md +0 -0
  462. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/lexicon.yaml +0 -0
  463. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/manifest.yaml +0 -0
  464. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/recommended_kinds.yaml +0 -0
  465. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/severity_rules.yaml +0 -0
  466. {codd_dev-2.12.0 → codd_dev-2.13.0}/codd_plugins/stack_map.yaml +0 -0
  467. {codd_dev-2.12.0 → codd_dev-2.13.0}/docs/cookbook/cdp_browser/README.md +0 -0
  468. {codd_dev-2.12.0 → codd_dev-2.13.0}/docs/requirements/README.md +0 -0
  469. {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.12.0
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.12.0 (current)** — Test-completeness gates: C7 `actors_without_journeys` amber promotion + new C8 `ci_health` static check (workflow presence, trigger coverage, verification-in-workflow). Defaults to opt-in for legacy projects; new `codd init` projects get `ci:` defaults from the template. See [post-mortem](docs/post-mortems/test_completeness_gap.md).
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.13.0 (next)** — C8 `ci_health` runtime mode (opt-in `ci.runtime_check: true`) polling the CI provider for latest-run-on-default-branch success.
160
+ - **v2.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.12.0 (current)** — Test-completeness gates: C7 `actors_without_journeys` amber promotion + new C8 `ci_health` static check (workflow presence, trigger coverage, verification-in-workflow). Defaults to opt-in for legacy projects; new `codd init` projects get `ci:` defaults from the template. See [post-mortem](docs/post-mortems/test_completeness_gap.md).
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.13.0 (next)** — C8 `ci_health` runtime mode (opt-in `ci.runtime_check: true`) polling the CI provider for latest-run-on-default-branch success.
120
+ - **v2.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) and _dag_result_severity(result) == "red"
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
- if _dag_result_passed(result):
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 = [result for result in red_results if _dag_result_passed(result) is False]
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
- return cls(provider="none")
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
- return self.check(root, CiConfig.from_mapping(_mapping_value(active_settings, "ci")))
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
- def check(self, project_root: Path, config: CiConfig) -> CiHealthResult:
93
- project_root = Path(project_root).resolve()
94
- if config.provider.strip().lower() == "none":
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="skip",
97
- message="ci.provider=none, C8 SKIP",
98
- passed=True,
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