codd-dev 2.11.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.11.0 → codd_dev-2.13.0}/PKG-INFO +6 -3
  2. {codd_dev-2.11.0 → codd_dev-2.13.0}/README.md +5 -2
  3. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/cli.py +20 -2
  4. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/coverage_metrics.py +11 -1
  5. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/checks/__init__.py +41 -1
  6. codd_dev-2.13.0/codd/dag/checks/ci_health.py +418 -0
  7. codd_dev-2.13.0/codd/dag/checks/opt_out.py +265 -0
  8. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/checks/user_journey_coherence.py +113 -1
  9. codd_dev-2.13.0/codd/dag/runner.py +146 -0
  10. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployer.py +97 -1
  11. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/__init__.py +3 -1
  12. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/engine.py +230 -3
  13. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/finding.py +22 -3
  14. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/codd.yaml.tmpl +10 -0
  15. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/validator.py +30 -0
  16. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/stack_map.yaml +8 -0
  17. {codd_dev-2.11.0 → codd_dev-2.13.0}/pyproject.toml +1 -1
  18. codd_dev-2.11.0/codd/dag/runner.py +0 -78
  19. {codd_dev-2.11.0 → codd_dev-2.13.0}/.gitignore +0 -0
  20. {codd_dev-2.11.0 → codd_dev-2.13.0}/LICENSE +0 -0
  21. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/__init__.py +0 -0
  22. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/__main__.py +0 -0
  23. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/_git_helper.py +0 -0
  24. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/ask_user_question_adapter.py +0 -0
  25. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/assembler.py +0 -0
  26. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/bridge.py +0 -0
  27. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/brownfield/__init__.py +0 -0
  28. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/brownfield/pipeline.py +0 -0
  29. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/clustering.py +0 -0
  30. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/coherence_adapters.py +0 -0
  31. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/coherence_engine.py +0 -0
  32. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/config.py +0 -0
  33. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/contracts.py +0 -0
  34. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/coverage_auditor.py +0 -0
  35. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/__init__.py +0 -0
  36. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/builder.py +0 -0
  37. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/checks/depends_on_consistency.py +0 -0
  38. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/checks/deployment_completeness.py +0 -0
  39. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/checks/edge_validity.py +0 -0
  40. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/checks/environment_coverage.py +0 -0
  41. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/checks/implementation_coverage.py +0 -0
  42. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/checks/node_completeness.py +0 -0
  43. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/checks/task_completion.py +0 -0
  44. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/checks/transitive_closure.py +0 -0
  45. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/coverage_axes.py +0 -0
  46. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/cli.yaml +0 -0
  47. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/cpp_embedded.yaml +0 -0
  48. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/csharp.yaml +0 -0
  49. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/elixir.yaml +0 -0
  50. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/generic.yaml +0 -0
  51. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/iot.yaml +0 -0
  52. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/java.yaml +0 -0
  53. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/kotlin.yaml +0 -0
  54. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/mobile.yaml +0 -0
  55. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/ruby.yaml +0 -0
  56. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/rust.yaml +0 -0
  57. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/scala.yaml +0 -0
  58. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/swift.yaml +0 -0
  59. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/test_frameworks.yaml +0 -0
  60. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/defaults/web.yaml +0 -0
  61. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/dag/extractor.py +0 -0
  62. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/defaults.yaml +0 -0
  63. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deploy_targets/__init__.py +0 -0
  64. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deploy_targets/app_service.py +0 -0
  65. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deploy_targets/base.py +0 -0
  66. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deploy_targets/docker_compose.py +0 -0
  67. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/__init__.py +0 -0
  68. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/checks/__init__.py +0 -0
  69. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/defaults/deploy_targets.yaml +0 -0
  70. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/defaults/runtime_capability_inference.yaml +0 -0
  71. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/defaults/schema_providers.yaml +0 -0
  72. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/defaults/verification_templates.yaml +0 -0
  73. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/extractor.py +0 -0
  74. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/__init__.py +0 -0
  75. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/ai_command.py +0 -0
  76. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/llm_consideration.py +0 -0
  77. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/schema/__init__.py +0 -0
  78. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/schema/prisma.py +0 -0
  79. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/target/__init__.py +0 -0
  80. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/target/docker_compose.py +0 -0
  81. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/__init__.py +0 -0
  82. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/assertion_handlers.py +0 -0
  83. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_browser.py +0 -0
  84. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_engines.py +0 -0
  85. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_launchers.py +0 -0
  86. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/cdp_wire.py +0 -0
  87. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/curl.py +0 -0
  88. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/form_strategies.py +0 -0
  89. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/means_catalog.py +0 -0
  90. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/deployment/providers/verification/playwright.py +0 -0
  91. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/design_md.py +0 -0
  92. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/diff/__init__.py +0 -0
  93. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/diff/apply.py +0 -0
  94. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/diff/engine.py +0 -0
  95. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/diff/persistence.py +0 -0
  96. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/diff/templates/diff_prompt.md +0 -0
  97. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/drift.py +0 -0
  98. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/e2e_extractor.py +0 -0
  99. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/e2e_generator.py +0 -0
  100. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/e2e_runner.py +0 -0
  101. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/apply.py +0 -0
  102. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/formatters/__init__.py +0 -0
  103. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/formatters/base.py +0 -0
  104. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/formatters/interactive.py +0 -0
  105. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/formatters/json_fmt.py +0 -0
  106. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/formatters/md.py +0 -0
  107. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/lexicon_loader.py +0 -0
  108. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/persistence.py +0 -0
  109. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/elicit/templates/elicit_prompt_L0.md +0 -0
  110. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/env_refs.py +0 -0
  111. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/extract_ai.py +0 -0
  112. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/extractor.py +0 -0
  113. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/fixer.py +0 -0
  114. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/fixup_drift.py +0 -0
  115. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/__init__.py +0 -0
  116. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/design_token_drift.py +0 -0
  117. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/lexicon_violation.py +0 -0
  118. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/fixup_drift_strategies/url_drift.py +0 -0
  119. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/generator.py +0 -0
  120. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/graph.py +0 -0
  121. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/hitl_session.py +0 -0
  122. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/hooks/__init__.py +0 -0
  123. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/hooks/pre-commit +0 -0
  124. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/hooks/recipes/claude_settings_example.json +0 -0
  125. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/hooks/recipes/codex_hook.sh +0 -0
  126. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/hooks/recipes/git_post_commit.sh +0 -0
  127. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/hooks/recipes/git_pre_commit.sh +0 -0
  128. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/implementer/__init__.py +0 -0
  129. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/implementer/chunked_runner.py +0 -0
  130. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/implementer/typecheck_loop.py +0 -0
  131. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/implementer.py +0 -0
  132. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/inheritance.py +0 -0
  133. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/init/__init__.py +0 -0
  134. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/init/lexicon_suggest.py +0 -0
  135. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/init/llm_lexicon_suggester.py +0 -0
  136. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/init/stack_detector.py +0 -0
  137. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/knowledge_fetcher.py +0 -0
  138. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/lexicon.py +0 -0
  139. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/lexicon_cli/__init__.py +0 -0
  140. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/__init__.py +0 -0
  141. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/html.py +0 -0
  142. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/json_fmt.py +0 -0
  143. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/lexicon_cli/formatters/md.py +0 -0
  144. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/lexicon_cli/inspector.py +0 -0
  145. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/lexicon_cli/manager.py +0 -0
  146. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/lexicon_cli/reporter.py +0 -0
  147. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/lexicon_cli/threshold.py +0 -0
  148. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/__init__.py +0 -0
  149. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/approval.py +0 -0
  150. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/best_practice_augmenter.py +0 -0
  151. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/criteria_expander.py +0 -0
  152. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/design_doc_extractor.py +0 -0
  153. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/impl_step_deriver.py +0 -0
  154. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/means_catalog_loader.py +0 -0
  155. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/parser.py +0 -0
  156. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/plan_deriver.py +0 -0
  157. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/prompt_builder.py +0 -0
  158. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/strategy_validator.py +0 -0
  159. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/templates/best_practice_augment_meta.md +0 -0
  160. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/templates/criteria_expand_meta.md +0 -0
  161. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/templates/design_doc_extract_meta.md +0 -0
  162. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/templates/impl_step_derive_meta.md +0 -0
  163. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/templates/implementation_step_catalog.yaml +0 -0
  164. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/templates/meta_instruction.md +0 -0
  165. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/templates/plan_derive_meta.md +0 -0
  166. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/llm/templates/verification_means_catalog.yaml +0 -0
  167. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/mcp_server.py +0 -0
  168. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/measure.py +0 -0
  169. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/parsing.py +0 -0
  170. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/planner.py +0 -0
  171. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/policy.py +0 -0
  172. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/preflight/__init__.py +0 -0
  173. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/preflight/defaults/cli.yaml +0 -0
  174. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/preflight/defaults/iot.yaml +0 -0
  175. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/preflight/defaults/mobile.yaml +0 -0
  176. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/preflight/defaults/web.yaml +0 -0
  177. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/propagate.py +0 -0
  178. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/propagator.py +0 -0
  179. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/registry.py +0 -0
  180. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/__init__.py +0 -0
  181. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/approval_repair.py +0 -0
  182. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/engine.py +0 -0
  183. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/git_patcher.py +0 -0
  184. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/history.py +0 -0
  185. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/llm_repair_engine.py +0 -0
  186. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/loop.py +0 -0
  187. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/primary_picker.py +0 -0
  188. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/proof_breaks.py +0 -0
  189. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/repair_result.py +0 -0
  190. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/repairability_classifier.py +0 -0
  191. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/schema.py +0 -0
  192. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/templates/analyze_meta.md +0 -0
  193. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/templates/propose_meta.md +0 -0
  194. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/templates/repair_strategy_meta.md +0 -0
  195. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/templates/repairability_meta.md +0 -0
  196. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair/verify_runner.py +0 -0
  197. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/repair_slice.py +0 -0
  198. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/require.py +0 -0
  199. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/require_plugins.py +0 -0
  200. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/require_propagate.py +0 -0
  201. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/cli.yaml +0 -0
  202. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/iot.yaml +0 -0
  203. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/mobile.yaml +0 -0
  204. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/required_artifacts/defaults/web.yaml +0 -0
  205. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/required_artifacts_deriver.py +0 -0
  206. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/cli.yaml +0 -0
  207. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/iot.yaml +0 -0
  208. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/mobile.yaml +0 -0
  209. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/requirement_completeness/defaults/web.yaml +0 -0
  210. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/requirement_completeness_auditor.py +0 -0
  211. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/restore.py +0 -0
  212. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/routes_extractor.py +0 -0
  213. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/scanner.py +0 -0
  214. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/schema_refs.py +0 -0
  215. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/screen_flow_validator.py +0 -0
  216. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/screen_transition_extractor.py +0 -0
  217. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/screen_transitions/defaults.yaml +0 -0
  218. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/synth.py +0 -0
  219. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/conventions.yaml.tmpl +0 -0
  220. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/data_dependencies.yaml.tmpl +0 -0
  221. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/doc_links.yaml.tmpl +0 -0
  222. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/extract_ai_prompt_baseline.md +0 -0
  223. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/extracted/api-contract.md.j2 +0 -0
  224. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/extracted/architecture-overview.md.j2 +0 -0
  225. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/extracted/module-detail.md.j2 +0 -0
  226. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/extracted/schema-design.md.j2 +0 -0
  227. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/extracted/system-context.md.j2 +0 -0
  228. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/gitignore.tmpl +0 -0
  229. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/lexicon_questions.md +0 -0
  230. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/lexicon_schema.yaml +0 -0
  231. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/templates/overrides.yaml.tmpl +0 -0
  232. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/traceability.py +0 -0
  233. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/watch/__init__.py +0 -0
  234. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/watch/events.py +0 -0
  235. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/watch/propagation_log.py +0 -0
  236. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/watch/propagation_pipeline.py +0 -0
  237. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/watch/test_runner.py +0 -0
  238. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/watch/watcher.py +0 -0
  239. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd/wiring.py +0 -0
  240. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/coverage_matrix.md +0 -0
  241. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/elicit_extend.md +0 -0
  242. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/lexicon.yaml +0 -0
  243. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/manifest.yaml +0 -0
  244. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/recommended_kinds.yaml +0 -0
  245. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ai_governance_eu_act/severity_rules.yaml +0 -0
  246. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/coverage_matrix.md +0 -0
  247. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/elicit_extend.md +0 -0
  248. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/lexicon.yaml +0 -0
  249. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/manifest.yaml +0 -0
  250. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/recommended_kinds.yaml +0 -0
  251. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rate_limiting_caching/severity_rules.yaml +0 -0
  252. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/coverage_matrix.md +0 -0
  253. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/elicit_extend.md +0 -0
  254. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/lexicon.yaml +0 -0
  255. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/manifest.yaml +0 -0
  256. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/recommended_kinds.yaml +0 -0
  257. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/api_rest_openapi/severity_rules.yaml +0 -0
  258. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/elicit_extend.md +0 -0
  259. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/lexicon.yaml +0 -0
  260. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/manifest.yaml +0 -0
  261. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/recommended_kinds.yaml +0 -0
  262. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/babok/severity_rules.yaml +0 -0
  263. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/coverage_matrix.md +0 -0
  264. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/elicit_extend.md +0 -0
  265. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/lexicon.yaml +0 -0
  266. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/manifest.yaml +0 -0
  267. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/recommended_kinds.yaml +0 -0
  268. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_event_cloudevents/severity_rules.yaml +0 -0
  269. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/coverage_matrix.md +0 -0
  270. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/elicit_extend.md +0 -0
  271. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/lexicon.yaml +0 -0
  272. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/manifest.yaml +0 -0
  273. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/recommended_kinds.yaml +0 -0
  274. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_graphql/severity_rules.yaml +0 -0
  275. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/coverage_matrix.md +0 -0
  276. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/elicit_extend.md +0 -0
  277. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/lexicon.yaml +0 -0
  278. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/manifest.yaml +0 -0
  279. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/recommended_kinds.yaml +0 -0
  280. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/backend_grpc_proto/severity_rules.yaml +0 -0
  281. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/coverage_matrix.md +0 -0
  282. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/elicit_extend.md +0 -0
  283. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/lexicon.yaml +0 -0
  284. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/manifest.yaml +0 -0
  285. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/recommended_kinds.yaml +0 -0
  286. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_hipaa/severity_rules.yaml +0 -0
  287. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/coverage_matrix.md +0 -0
  288. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/elicit_extend.md +0 -0
  289. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/lexicon.yaml +0 -0
  290. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/manifest.yaml +0 -0
  291. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/recommended_kinds.yaml +0 -0
  292. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_iso27001/severity_rules.yaml +0 -0
  293. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/coverage_matrix.md +0 -0
  294. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/elicit_extend.md +0 -0
  295. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/lexicon.yaml +0 -0
  296. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/manifest.yaml +0 -0
  297. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/recommended_kinds.yaml +0 -0
  298. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/compliance_pci_dss_4/severity_rules.yaml +0 -0
  299. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/coverage_matrix.md +0 -0
  300. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/elicit_extend.md +0 -0
  301. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/lexicon.yaml +0 -0
  302. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/manifest.yaml +0 -0
  303. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/recommended_kinds.yaml +0 -0
  304. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/severity_rules.yaml +0 -0
  305. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/coverage_matrix.md +0 -0
  306. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/elicit_extend.md +0 -0
  307. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/lexicon.yaml +0 -0
  308. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/manifest.yaml +0 -0
  309. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/recommended_kinds.yaml +0 -0
  310. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_governance_appi_gdpr/severity_rules.yaml +0 -0
  311. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/coverage_matrix.md +0 -0
  312. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/elicit_extend.md +0 -0
  313. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/lexicon.yaml +0 -0
  314. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/manifest.yaml +0 -0
  315. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/recommended_kinds.yaml +0 -0
  316. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_nosql_jsonschema/severity_rules.yaml +0 -0
  317. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/coverage_matrix.md +0 -0
  318. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/elicit_extend.md +0 -0
  319. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/lexicon.yaml +0 -0
  320. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/manifest.yaml +0 -0
  321. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/recommended_kinds.yaml +0 -0
  322. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/data_relational_iso_sql/severity_rules.yaml +0 -0
  323. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/coverage_matrix.md +0 -0
  324. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/elicit_extend.md +0 -0
  325. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/lexicon.yaml +0 -0
  326. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/manifest.yaml +0 -0
  327. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/recommended_kinds.yaml +0 -0
  328. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ddd_domain_driven_design/severity_rules.yaml +0 -0
  329. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/coverage_matrix.md +0 -0
  330. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/elicit_extend.md +0 -0
  331. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/lexicon.yaml +0 -0
  332. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/manifest.yaml +0 -0
  333. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/recommended_kinds.yaml +0 -0
  334. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/dora_sre_metrics/severity_rules.yaml +0 -0
  335. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/coverage_matrix.md +0 -0
  336. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/elicit_extend.md +0 -0
  337. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/lexicon.yaml +0 -0
  338. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/manifest.yaml +0 -0
  339. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/recommended_kinds.yaml +0 -0
  340. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/i18n_unicode_cldr/severity_rules.yaml +0 -0
  341. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/coverage_matrix.md +0 -0
  342. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/elicit_extend.md +0 -0
  343. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/lexicon.yaml +0 -0
  344. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/manifest.yaml +0 -0
  345. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/recommended_kinds.yaml +0 -0
  346. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ml_model_cards/severity_rules.yaml +0 -0
  347. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/coverage_matrix.md +0 -0
  348. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/elicit_extend.md +0 -0
  349. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/lexicon.yaml +0 -0
  350. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/manifest.yaml +0 -0
  351. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/recommended_kinds.yaml +0 -0
  352. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_a11y_native/severity_rules.yaml +0 -0
  353. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/coverage_matrix.md +0 -0
  354. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/elicit_extend.md +0 -0
  355. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/lexicon.yaml +0 -0
  356. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/manifest.yaml +0 -0
  357. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/recommended_kinds.yaml +0 -0
  358. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_android_material3/severity_rules.yaml +0 -0
  359. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/coverage_matrix.md +0 -0
  360. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/elicit_extend.md +0 -0
  361. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/lexicon.yaml +0 -0
  362. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/manifest.yaml +0 -0
  363. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/recommended_kinds.yaml +0 -0
  364. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_ios_hig/severity_rules.yaml +0 -0
  365. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/coverage_matrix.md +0 -0
  366. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/elicit_extend.md +0 -0
  367. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/lexicon.yaml +0 -0
  368. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/manifest.yaml +0 -0
  369. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/recommended_kinds.yaml +0 -0
  370. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/mobile_security_masvs/severity_rules.yaml +0 -0
  371. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/coverage_matrix.md +0 -0
  372. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/elicit_extend.md +0 -0
  373. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/lexicon.yaml +0 -0
  374. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/manifest.yaml +0 -0
  375. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/recommended_kinds.yaml +0 -0
  376. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_cicd_pipeline/severity_rules.yaml +0 -0
  377. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/coverage_matrix.md +0 -0
  378. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/elicit_extend.md +0 -0
  379. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/lexicon.yaml +0 -0
  380. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/manifest.yaml +0 -0
  381. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/recommended_kinds.yaml +0 -0
  382. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_iac_terraform/severity_rules.yaml +0 -0
  383. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/coverage_matrix.md +0 -0
  384. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/elicit_extend.md +0 -0
  385. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/lexicon.yaml +0 -0
  386. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/manifest.yaml +0 -0
  387. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/recommended_kinds.yaml +0 -0
  388. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_kubernetes/severity_rules.yaml +0 -0
  389. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/coverage_matrix.md +0 -0
  390. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/elicit_extend.md +0 -0
  391. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/lexicon.yaml +0 -0
  392. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/manifest.yaml +0 -0
  393. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/recommended_kinds.yaml +0 -0
  394. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/ops_observability_otel/severity_rules.yaml +0 -0
  395. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/coverage_matrix.md +0 -0
  396. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/elicit_extend.md +0 -0
  397. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/lexicon.yaml +0 -0
  398. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/manifest.yaml +0 -0
  399. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/recommended_kinds.yaml +0 -0
  400. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_iso25010/severity_rules.yaml +0 -0
  401. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/coverage_matrix.md +0 -0
  402. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/elicit_extend.md +0 -0
  403. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/lexicon.yaml +0 -0
  404. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/manifest.yaml +0 -0
  405. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/recommended_kinds.yaml +0 -0
  406. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/process_test_iso29119/severity_rules.yaml +0 -0
  407. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/coverage_matrix.md +0 -0
  408. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/elicit_extend.md +0 -0
  409. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/lexicon.yaml +0 -0
  410. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/manifest.yaml +0 -0
  411. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/recommended_kinds.yaml +0 -0
  412. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/twelve_factor_app/severity_rules.yaml +0 -0
  413. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/coverage_matrix.md +0 -0
  414. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/elicit_extend.md +0 -0
  415. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/lexicon.yaml +0 -0
  416. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/manifest.yaml +0 -0
  417. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/recommended_kinds.yaml +0 -0
  418. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/severity_rules.yaml +0 -0
  419. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/coverage_matrix.md +0 -0
  420. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/elicit_extend.md +0 -0
  421. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/lexicon.yaml +0 -0
  422. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/manifest.yaml +0 -0
  423. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/recommended_kinds.yaml +0 -0
  424. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_authn_webauthn/severity_rules.yaml +0 -0
  425. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/coverage_matrix.md +0 -0
  426. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/elicit_extend.md +0 -0
  427. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/lexicon.yaml +0 -0
  428. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/manifest.yaml +0 -0
  429. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/recommended_kinds.yaml +0 -0
  430. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_browser_compat/severity_rules.yaml +0 -0
  431. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/coverage_matrix.md +0 -0
  432. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/elicit_extend.md +0 -0
  433. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/lexicon.yaml +0 -0
  434. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/manifest.yaml +0 -0
  435. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/recommended_kinds.yaml +0 -0
  436. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_forms_html5/severity_rules.yaml +0 -0
  437. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/coverage_matrix.md +0 -0
  438. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/elicit_extend.md +0 -0
  439. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/lexicon.yaml +0 -0
  440. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/manifest.yaml +0 -0
  441. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/recommended_kinds.yaml +0 -0
  442. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_performance_core_web_vitals/severity_rules.yaml +0 -0
  443. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/coverage_matrix.md +0 -0
  444. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/elicit_extend.md +0 -0
  445. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/lexicon.yaml +0 -0
  446. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/manifest.yaml +0 -0
  447. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/recommended_kinds.yaml +0 -0
  448. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_pwa_manifest/severity_rules.yaml +0 -0
  449. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/coverage_matrix.md +0 -0
  450. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/elicit_extend.md +0 -0
  451. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/lexicon.yaml +0 -0
  452. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/manifest.yaml +0 -0
  453. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/recommended_kinds.yaml +0 -0
  454. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_responsive/severity_rules.yaml +0 -0
  455. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/coverage_matrix.md +0 -0
  456. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/elicit_extend.md +0 -0
  457. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/lexicon.yaml +0 -0
  458. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/manifest.yaml +0 -0
  459. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/recommended_kinds.yaml +0 -0
  460. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_security_owasp/severity_rules.yaml +0 -0
  461. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/coverage_matrix.md +0 -0
  462. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/elicit_extend.md +0 -0
  463. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/lexicon.yaml +0 -0
  464. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/manifest.yaml +0 -0
  465. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/recommended_kinds.yaml +0 -0
  466. {codd_dev-2.11.0 → codd_dev-2.13.0}/codd_plugins/lexicons/web_seo_schemaorg/severity_rules.yaml +0 -0
  467. {codd_dev-2.11.0 → codd_dev-2.13.0}/docs/cookbook/cdp_browser/README.md +0 -0
  468. {codd_dev-2.11.0 → codd_dev-2.13.0}/docs/requirements/README.md +0 -0
  469. {codd_dev-2.11.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.11.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,8 +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.10.0 (current)** — Lexicon-driven completeness, 38 plug-ins, LLM-enhanced init, scope/phase filter, auto-repair across the full DAG.
157
- - **v2.11.0 (next)** — Sprint-less `codd implement` (`--design <path> --output <dir>` directly; `implementation_plan.md` parser removed). See [migration guide](docs/migrations/v2.11.0-sprintless.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).
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).
159
+ - **v2.10.0** — Lexicon-driven completeness, 38 plug-ins, LLM-enhanced init, scope/phase filter, auto-repair across the full DAG.
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.
158
161
 
159
162
  ---
160
163
 
@@ -113,8 +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.10.0 (current)** — Lexicon-driven completeness, 38 plug-ins, LLM-enhanced init, scope/phase filter, auto-repair across the full DAG.
117
- - **v2.11.0 (next)** — Sprint-less `codd implement` (`--design <path> --output <dir>` directly; `implementation_plan.md` parser removed). See [migration guide](docs/migrations/v2.11.0-sprintless.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).
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).
119
+ - **v2.10.0** — Lexicon-driven completeness, 38 plug-ins, LLM-enhanced init, scope/phase filter, auto-repair across the full DAG.
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.
118
121
 
119
122
  ---
120
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``."""
@@ -0,0 +1,418 @@
1
+ """C8 CI health check with deterministic static validation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import asdict, dataclass, field
6
+ from glob import glob
7
+ import json
8
+ from pathlib import Path
9
+ import re
10
+ from typing import Any, Mapping
11
+
12
+ import yaml
13
+
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
+ )
20
+
21
+
22
+ _DEFAULT_PROVIDER = "github" + "_actions"
23
+ _OPT_OUT_PROVIDER = "none"
24
+
25
+
26
+ @dataclass
27
+ class CiConfig:
28
+ provider: str = _DEFAULT_PROVIDER
29
+ workflow_glob: str = ".github/workflows/*.yml"
30
+ required_triggers: list[str] = field(default_factory=lambda: ["push", "pull_request"])
31
+ runtime_check: bool = False
32
+ staleness_days: int = 14
33
+ default_branch: str = "main"
34
+ trigger_key: str = "on"
35
+
36
+ @classmethod
37
+ def from_mapping(cls, value: Mapping[str, Any] | None) -> "CiConfig":
38
+ if not isinstance(value, Mapping):
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()
44
+
45
+ config = cls()
46
+ return cls(
47
+ provider=_string_value(value.get("provider"), config.provider),
48
+ workflow_glob=_string_value(value.get("workflow_glob"), config.workflow_glob),
49
+ required_triggers=_string_list(value.get("required_triggers"), config.required_triggers),
50
+ runtime_check=bool(value.get("runtime_check", config.runtime_check)),
51
+ staleness_days=_int_value(value.get("staleness_days"), config.staleness_days),
52
+ default_branch=_string_value(value.get("default_branch"), config.default_branch),
53
+ trigger_key=_string_value(value.get("trigger_key"), config.trigger_key),
54
+ )
55
+
56
+
57
+ @dataclass
58
+ class CiHealthFinding:
59
+ violation_type: str
60
+ severity: str
61
+ block_deploy: bool
62
+ message: str
63
+ details: list[str] = field(default_factory=list)
64
+
65
+
66
+ @dataclass
67
+ class CiHealthResult:
68
+ check_name: str = "ci_health"
69
+ status: str = "pass"
70
+ severity: str = "info"
71
+ block_deploy: bool = False
72
+ message: str = "C8 ci_health PASS"
73
+ findings: list[CiHealthFinding] = field(default_factory=list)
74
+ workflow_files: list[str] = field(default_factory=list)
75
+ passed: bool = True
76
+
77
+
78
+ @register_dag_check("ci_health")
79
+ class CiHealthCheck(DagCheck):
80
+ """C8 CI workflow presence and trigger validation.
81
+
82
+ Runtime provider polling is intentionally deferred. The shipped path is
83
+ static, deterministic, and driven by config values.
84
+ """
85
+
86
+ check_name = "ci_health"
87
+ severity = "red"
88
+ block_deploy = True
89
+
90
+ def run(
91
+ self,
92
+ dag: Any | None = None,
93
+ project_root: str | Path | None = None,
94
+ settings: dict[str, Any] | None = None,
95
+ codd_config: dict[str, Any] | None = None,
96
+ ) -> CiHealthResult:
97
+ del dag
98
+ root = Path(project_root or self.project_root or ".").resolve()
99
+ active_settings = codd_config or settings or self.settings
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
111
+
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):
131
+ return CiHealthResult(
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,
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
+ )
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)
161
+ workflow_files = self._locate_workflows(project_root, config.workflow_glob)
162
+ if not workflow_files:
163
+ finding = CiHealthFinding(
164
+ violation_type="ci_workflow_missing",
165
+ severity="red",
166
+ block_deploy=True,
167
+ message="No CI workflow files found matching glob.",
168
+ details=[config.workflow_glob],
169
+ )
170
+ return CiHealthResult(
171
+ status="fail",
172
+ severity="red",
173
+ block_deploy=True,
174
+ message=finding.message,
175
+ findings=[finding],
176
+ passed=False,
177
+ )
178
+
179
+ findings = [
180
+ *self._check_triggers(workflow_files, config.required_triggers, config.trigger_key),
181
+ *self._check_verification_coverage(workflow_files, project_root),
182
+ ]
183
+ block_deploy = any(finding.block_deploy for finding in findings)
184
+ severity = _max_severity(finding.severity for finding in findings)
185
+ status = "fail" if block_deploy else ("warn" if findings else "pass")
186
+ message = (
187
+ "C8 ci_health PASS"
188
+ if not findings
189
+ else f"C8 ci_health found {len(findings)} static finding(s)"
190
+ )
191
+ return CiHealthResult(
192
+ status=status,
193
+ severity=severity,
194
+ block_deploy=block_deploy,
195
+ message=message,
196
+ findings=findings,
197
+ workflow_files=[path.relative_to(project_root).as_posix() for path in workflow_files],
198
+ passed=not block_deploy,
199
+ )
200
+
201
+ def format_report(self, result: CiHealthResult) -> str:
202
+ return json.dumps({"ci_health_report": asdict(result)}, ensure_ascii=False, indent=2)
203
+
204
+ def _locate_workflows(self, project_root: Path, workflow_glob: str) -> list[Path]:
205
+ pattern = workflow_glob.strip()
206
+ if not pattern:
207
+ return []
208
+ if Path(pattern).is_absolute():
209
+ paths = [Path(path) for path in glob(pattern)]
210
+ else:
211
+ paths = list(project_root.glob(pattern))
212
+ return sorted(path for path in paths if path.is_file())
213
+
214
+ def _check_triggers(
215
+ self,
216
+ workflow_files: list[Path],
217
+ required_triggers: list[str],
218
+ trigger_key: str,
219
+ ) -> list[CiHealthFinding]:
220
+ required = {trigger.strip() for trigger in required_triggers if trigger.strip()}
221
+ if not required:
222
+ return []
223
+
224
+ actual: set[str] = set()
225
+ for path in workflow_files:
226
+ actual.update(self._workflow_triggers(path, trigger_key))
227
+
228
+ missing = sorted(required - actual)
229
+ if not missing:
230
+ return []
231
+ return [
232
+ CiHealthFinding(
233
+ violation_type="ci_trigger_incomplete",
234
+ severity="amber",
235
+ block_deploy=False,
236
+ message="CI workflow does not include all required triggers.",
237
+ details=[f"missing: {', '.join(missing)}"],
238
+ )
239
+ ]
240
+
241
+ def _workflow_triggers(self, path: Path, trigger_key: str) -> set[str]:
242
+ payload = _read_yaml_mapping(path)
243
+ value = payload.get(trigger_key)
244
+ if value is None and trigger_key == "on":
245
+ value = payload.get(True)
246
+ return _trigger_names(value)
247
+
248
+ def _check_verification_coverage(
249
+ self,
250
+ workflow_files: list[Path],
251
+ project_root: Path,
252
+ ) -> list[CiHealthFinding]:
253
+ verification_commands = self._deploy_verification_commands(project_root)
254
+ if not verification_commands:
255
+ return []
256
+
257
+ workflow_commands = {
258
+ _normalize_command(command)
259
+ for path in workflow_files
260
+ for command in self._workflow_commands(path)
261
+ if _normalize_command(command)
262
+ }
263
+ missing = [
264
+ command
265
+ for command in verification_commands
266
+ if not self._command_appears_in_workflow(command, workflow_commands)
267
+ ]
268
+ if not missing:
269
+ return []
270
+ return [
271
+ CiHealthFinding(
272
+ violation_type="ci_verification_not_in_workflow",
273
+ severity="amber",
274
+ block_deploy=False,
275
+ message="Deployment verification command is not invoked by CI workflow.",
276
+ details=missing,
277
+ )
278
+ ]
279
+
280
+ def _deploy_verification_commands(self, project_root: Path) -> list[str]:
281
+ commands: list[str] = []
282
+ for path in self._deploy_yaml_candidates(project_root):
283
+ if not path.is_file():
284
+ continue
285
+ payload = _read_yaml_mapping(path)
286
+ commands.extend(_hook_commands(payload))
287
+ return _dedupe(_normalize_command(command) for command in commands if _normalize_command(command))
288
+
289
+ @staticmethod
290
+ def _deploy_yaml_candidates(project_root: Path) -> list[Path]:
291
+ return [
292
+ project_root / "deploy.yaml",
293
+ project_root / ".codd" / "deploy.yaml",
294
+ project_root / "codd" / "deploy.yaml",
295
+ ]
296
+
297
+ def _workflow_commands(self, path: Path) -> list[str]:
298
+ return _command_values(_read_yaml_mapping(path))
299
+
300
+ @staticmethod
301
+ def _command_appears_in_workflow(command: str, workflow_commands: set[str]) -> bool:
302
+ return any(command == candidate or command in candidate for candidate in workflow_commands)
303
+
304
+
305
+ def _read_yaml_mapping(path: Path) -> dict[str, Any]:
306
+ payload = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
307
+ return payload if isinstance(payload, dict) else {}
308
+
309
+
310
+ def _mapping_value(mapping: Any, key: str) -> Mapping[str, Any] | None:
311
+ if isinstance(mapping, Mapping) and isinstance(mapping.get(key), Mapping):
312
+ return mapping[key]
313
+ return None
314
+
315
+
316
+ def _trigger_names(value: Any) -> set[str]:
317
+ if isinstance(value, str):
318
+ return {value}
319
+ if isinstance(value, list):
320
+ return {str(item) for item in value if item}
321
+ if isinstance(value, dict):
322
+ return {str(key) for key in value if key}
323
+ return set()
324
+
325
+
326
+ def _hook_commands(value: Any) -> list[str]:
327
+ if isinstance(value, str):
328
+ return [value]
329
+ if isinstance(value, list):
330
+ commands: list[str] = []
331
+ for item in value:
332
+ commands.extend(_hook_commands(item))
333
+ return commands
334
+ if isinstance(value, dict):
335
+ commands: list[str] = []
336
+ for key in ("post_deploy", "post_deploy_steps", "post_deploy_hooks", "verification", "verifications"):
337
+ commands.extend(_hook_commands(value.get(key)))
338
+ for key in ("command", "run", "script", "test"):
339
+ commands.extend(_hook_commands(value.get(key)))
340
+ targets = value.get("targets")
341
+ if isinstance(targets, dict):
342
+ for target_config in targets.values():
343
+ commands.extend(_hook_commands(target_config))
344
+ return commands
345
+ return []
346
+
347
+
348
+ def _command_values(value: Any) -> list[str]:
349
+ if isinstance(value, str):
350
+ return []
351
+ if isinstance(value, list):
352
+ commands: list[str] = []
353
+ for item in value:
354
+ commands.extend(_command_values(item))
355
+ return commands
356
+ if isinstance(value, dict):
357
+ commands: list[str] = []
358
+ for key, item in value.items():
359
+ if key in {"run", "script", "command", "commands"}:
360
+ commands.extend(_coerce_command_list(item))
361
+ else:
362
+ commands.extend(_command_values(item))
363
+ return commands
364
+ return []
365
+
366
+
367
+ def _coerce_command_list(value: Any) -> list[str]:
368
+ if isinstance(value, str):
369
+ return [value]
370
+ if isinstance(value, list):
371
+ commands: list[str] = []
372
+ for item in value:
373
+ commands.extend(_coerce_command_list(item))
374
+ return commands
375
+ return []
376
+
377
+
378
+ def _normalize_command(value: str) -> str:
379
+ return re.sub(r"\s+", " ", value).strip()
380
+
381
+
382
+ def _dedupe(values: Any) -> list[str]:
383
+ seen: set[str] = set()
384
+ result: list[str] = []
385
+ for value in values:
386
+ if not value or value in seen:
387
+ continue
388
+ seen.add(value)
389
+ result.append(value)
390
+ return result
391
+
392
+
393
+ def _string_value(value: Any, default: str) -> str:
394
+ return value if isinstance(value, str) and value.strip() else default
395
+
396
+
397
+ def _string_list(value: Any, default: list[str]) -> list[str]:
398
+ if not isinstance(value, list):
399
+ return list(default)
400
+ result = [str(item) for item in value if str(item).strip()]
401
+ return result or list(default)
402
+
403
+
404
+ def _int_value(value: Any, default: int) -> int:
405
+ try:
406
+ return int(value)
407
+ except (TypeError, ValueError):
408
+ return default
409
+
410
+
411
+ def _max_severity(values: Any) -> str:
412
+ order = {"info": 0, "amber": 1, "red": 2}
413
+ selected = "info"
414
+ for value in values:
415
+ text = str(value)
416
+ if order.get(text, 0) > order[selected]:
417
+ selected = text
418
+ return selected