codd-dev 2.11.0__tar.gz → 2.12.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 (467) hide show
  1. {codd_dev-2.11.0 → codd_dev-2.12.0}/PKG-INFO +5 -3
  2. {codd_dev-2.11.0 → codd_dev-2.12.0}/README.md +4 -2
  3. codd_dev-2.12.0/codd/dag/checks/ci_health.py +358 -0
  4. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/checks/user_journey_coherence.py +113 -1
  5. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/runner.py +1 -0
  6. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployer.py +76 -1
  7. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/__init__.py +3 -1
  8. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/engine.py +230 -3
  9. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/finding.py +22 -3
  10. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/codd.yaml.tmpl +10 -0
  11. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/stack_map.yaml +8 -0
  12. {codd_dev-2.11.0 → codd_dev-2.12.0}/pyproject.toml +1 -1
  13. {codd_dev-2.11.0 → codd_dev-2.12.0}/.gitignore +0 -0
  14. {codd_dev-2.11.0 → codd_dev-2.12.0}/LICENSE +0 -0
  15. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/__init__.py +0 -0
  16. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/__main__.py +0 -0
  17. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/_git_helper.py +0 -0
  18. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/ask_user_question_adapter.py +0 -0
  19. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/assembler.py +0 -0
  20. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/bridge.py +0 -0
  21. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/brownfield/__init__.py +0 -0
  22. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/brownfield/pipeline.py +0 -0
  23. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/cli.py +0 -0
  24. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/clustering.py +0 -0
  25. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/coherence_adapters.py +0 -0
  26. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/coherence_engine.py +0 -0
  27. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/config.py +0 -0
  28. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/contracts.py +0 -0
  29. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/coverage_auditor.py +0 -0
  30. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/coverage_metrics.py +0 -0
  31. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/__init__.py +0 -0
  32. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/builder.py +0 -0
  33. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/checks/__init__.py +0 -0
  34. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/checks/depends_on_consistency.py +0 -0
  35. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/checks/deployment_completeness.py +0 -0
  36. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/checks/edge_validity.py +0 -0
  37. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/checks/environment_coverage.py +0 -0
  38. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/checks/implementation_coverage.py +0 -0
  39. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/checks/node_completeness.py +0 -0
  40. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/checks/task_completion.py +0 -0
  41. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/checks/transitive_closure.py +0 -0
  42. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/coverage_axes.py +0 -0
  43. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/cli.yaml +0 -0
  44. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/cpp_embedded.yaml +0 -0
  45. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/csharp.yaml +0 -0
  46. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/elixir.yaml +0 -0
  47. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/generic.yaml +0 -0
  48. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/iot.yaml +0 -0
  49. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/java.yaml +0 -0
  50. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/kotlin.yaml +0 -0
  51. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/mobile.yaml +0 -0
  52. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/ruby.yaml +0 -0
  53. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/rust.yaml +0 -0
  54. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/scala.yaml +0 -0
  55. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/swift.yaml +0 -0
  56. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/test_frameworks.yaml +0 -0
  57. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/defaults/web.yaml +0 -0
  58. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/dag/extractor.py +0 -0
  59. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/defaults.yaml +0 -0
  60. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deploy_targets/__init__.py +0 -0
  61. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deploy_targets/app_service.py +0 -0
  62. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deploy_targets/base.py +0 -0
  63. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deploy_targets/docker_compose.py +0 -0
  64. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/__init__.py +0 -0
  65. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/checks/__init__.py +0 -0
  66. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/defaults/deploy_targets.yaml +0 -0
  67. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/defaults/runtime_capability_inference.yaml +0 -0
  68. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/defaults/schema_providers.yaml +0 -0
  69. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/defaults/verification_templates.yaml +0 -0
  70. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/extractor.py +0 -0
  71. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/__init__.py +0 -0
  72. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/ai_command.py +0 -0
  73. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/llm_consideration.py +0 -0
  74. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/schema/__init__.py +0 -0
  75. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/schema/prisma.py +0 -0
  76. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/target/__init__.py +0 -0
  77. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/target/docker_compose.py +0 -0
  78. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/verification/__init__.py +0 -0
  79. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/verification/assertion_handlers.py +0 -0
  80. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/verification/cdp_browser.py +0 -0
  81. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/verification/cdp_engines.py +0 -0
  82. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/verification/cdp_launchers.py +0 -0
  83. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/verification/cdp_wire.py +0 -0
  84. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/verification/curl.py +0 -0
  85. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/verification/form_strategies.py +0 -0
  86. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/verification/means_catalog.py +0 -0
  87. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/deployment/providers/verification/playwright.py +0 -0
  88. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/design_md.py +0 -0
  89. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/diff/__init__.py +0 -0
  90. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/diff/apply.py +0 -0
  91. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/diff/engine.py +0 -0
  92. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/diff/persistence.py +0 -0
  93. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/diff/templates/diff_prompt.md +0 -0
  94. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/drift.py +0 -0
  95. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/e2e_extractor.py +0 -0
  96. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/e2e_generator.py +0 -0
  97. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/e2e_runner.py +0 -0
  98. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/apply.py +0 -0
  99. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/formatters/__init__.py +0 -0
  100. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/formatters/base.py +0 -0
  101. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/formatters/interactive.py +0 -0
  102. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/formatters/json_fmt.py +0 -0
  103. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/formatters/md.py +0 -0
  104. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/lexicon_loader.py +0 -0
  105. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/persistence.py +0 -0
  106. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/elicit/templates/elicit_prompt_L0.md +0 -0
  107. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/env_refs.py +0 -0
  108. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/extract_ai.py +0 -0
  109. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/extractor.py +0 -0
  110. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/fixer.py +0 -0
  111. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/fixup_drift.py +0 -0
  112. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/fixup_drift_strategies/__init__.py +0 -0
  113. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/fixup_drift_strategies/design_token_drift.py +0 -0
  114. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/fixup_drift_strategies/lexicon_violation.py +0 -0
  115. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/fixup_drift_strategies/url_drift.py +0 -0
  116. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/generator.py +0 -0
  117. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/graph.py +0 -0
  118. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/hitl_session.py +0 -0
  119. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/hooks/__init__.py +0 -0
  120. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/hooks/pre-commit +0 -0
  121. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/hooks/recipes/claude_settings_example.json +0 -0
  122. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/hooks/recipes/codex_hook.sh +0 -0
  123. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/hooks/recipes/git_post_commit.sh +0 -0
  124. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/hooks/recipes/git_pre_commit.sh +0 -0
  125. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/implementer/__init__.py +0 -0
  126. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/implementer/chunked_runner.py +0 -0
  127. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/implementer/typecheck_loop.py +0 -0
  128. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/implementer.py +0 -0
  129. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/inheritance.py +0 -0
  130. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/init/__init__.py +0 -0
  131. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/init/lexicon_suggest.py +0 -0
  132. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/init/llm_lexicon_suggester.py +0 -0
  133. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/init/stack_detector.py +0 -0
  134. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/knowledge_fetcher.py +0 -0
  135. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/lexicon.py +0 -0
  136. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/lexicon_cli/__init__.py +0 -0
  137. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/lexicon_cli/formatters/__init__.py +0 -0
  138. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/lexicon_cli/formatters/html.py +0 -0
  139. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/lexicon_cli/formatters/json_fmt.py +0 -0
  140. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/lexicon_cli/formatters/md.py +0 -0
  141. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/lexicon_cli/inspector.py +0 -0
  142. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/lexicon_cli/manager.py +0 -0
  143. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/lexicon_cli/reporter.py +0 -0
  144. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/lexicon_cli/threshold.py +0 -0
  145. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/__init__.py +0 -0
  146. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/approval.py +0 -0
  147. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/best_practice_augmenter.py +0 -0
  148. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/criteria_expander.py +0 -0
  149. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/design_doc_extractor.py +0 -0
  150. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/impl_step_deriver.py +0 -0
  151. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/means_catalog_loader.py +0 -0
  152. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/parser.py +0 -0
  153. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/plan_deriver.py +0 -0
  154. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/prompt_builder.py +0 -0
  155. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/strategy_validator.py +0 -0
  156. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/templates/best_practice_augment_meta.md +0 -0
  157. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/templates/criteria_expand_meta.md +0 -0
  158. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/templates/design_doc_extract_meta.md +0 -0
  159. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/templates/impl_step_derive_meta.md +0 -0
  160. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/templates/implementation_step_catalog.yaml +0 -0
  161. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/templates/meta_instruction.md +0 -0
  162. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/templates/plan_derive_meta.md +0 -0
  163. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/llm/templates/verification_means_catalog.yaml +0 -0
  164. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/mcp_server.py +0 -0
  165. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/measure.py +0 -0
  166. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/parsing.py +0 -0
  167. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/planner.py +0 -0
  168. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/policy.py +0 -0
  169. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/preflight/__init__.py +0 -0
  170. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/preflight/defaults/cli.yaml +0 -0
  171. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/preflight/defaults/iot.yaml +0 -0
  172. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/preflight/defaults/mobile.yaml +0 -0
  173. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/preflight/defaults/web.yaml +0 -0
  174. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/propagate.py +0 -0
  175. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/propagator.py +0 -0
  176. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/registry.py +0 -0
  177. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/__init__.py +0 -0
  178. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/approval_repair.py +0 -0
  179. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/engine.py +0 -0
  180. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/git_patcher.py +0 -0
  181. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/history.py +0 -0
  182. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/llm_repair_engine.py +0 -0
  183. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/loop.py +0 -0
  184. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/primary_picker.py +0 -0
  185. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/proof_breaks.py +0 -0
  186. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/repair_result.py +0 -0
  187. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/repairability_classifier.py +0 -0
  188. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/schema.py +0 -0
  189. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/templates/analyze_meta.md +0 -0
  190. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/templates/propose_meta.md +0 -0
  191. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/templates/repair_strategy_meta.md +0 -0
  192. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/templates/repairability_meta.md +0 -0
  193. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair/verify_runner.py +0 -0
  194. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/repair_slice.py +0 -0
  195. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/require.py +0 -0
  196. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/require_plugins.py +0 -0
  197. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/require_propagate.py +0 -0
  198. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/required_artifacts/defaults/cli.yaml +0 -0
  199. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/required_artifacts/defaults/iot.yaml +0 -0
  200. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/required_artifacts/defaults/mobile.yaml +0 -0
  201. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/required_artifacts/defaults/web.yaml +0 -0
  202. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/required_artifacts_deriver.py +0 -0
  203. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/requirement_completeness/defaults/cli.yaml +0 -0
  204. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/requirement_completeness/defaults/iot.yaml +0 -0
  205. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/requirement_completeness/defaults/mobile.yaml +0 -0
  206. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/requirement_completeness/defaults/web.yaml +0 -0
  207. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/requirement_completeness_auditor.py +0 -0
  208. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/restore.py +0 -0
  209. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/routes_extractor.py +0 -0
  210. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/scanner.py +0 -0
  211. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/schema_refs.py +0 -0
  212. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/screen_flow_validator.py +0 -0
  213. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/screen_transition_extractor.py +0 -0
  214. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/screen_transitions/defaults.yaml +0 -0
  215. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/synth.py +0 -0
  216. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/conventions.yaml.tmpl +0 -0
  217. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/data_dependencies.yaml.tmpl +0 -0
  218. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/doc_links.yaml.tmpl +0 -0
  219. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/extract_ai_prompt_baseline.md +0 -0
  220. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/extracted/api-contract.md.j2 +0 -0
  221. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/extracted/architecture-overview.md.j2 +0 -0
  222. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/extracted/module-detail.md.j2 +0 -0
  223. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/extracted/schema-design.md.j2 +0 -0
  224. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/extracted/system-context.md.j2 +0 -0
  225. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/gitignore.tmpl +0 -0
  226. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/lexicon_questions.md +0 -0
  227. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/lexicon_schema.yaml +0 -0
  228. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/templates/overrides.yaml.tmpl +0 -0
  229. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/traceability.py +0 -0
  230. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/validator.py +0 -0
  231. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/watch/__init__.py +0 -0
  232. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/watch/events.py +0 -0
  233. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/watch/propagation_log.py +0 -0
  234. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/watch/propagation_pipeline.py +0 -0
  235. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/watch/test_runner.py +0 -0
  236. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/watch/watcher.py +0 -0
  237. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd/wiring.py +0 -0
  238. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ai_governance_eu_act/coverage_matrix.md +0 -0
  239. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ai_governance_eu_act/elicit_extend.md +0 -0
  240. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ai_governance_eu_act/lexicon.yaml +0 -0
  241. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ai_governance_eu_act/manifest.yaml +0 -0
  242. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ai_governance_eu_act/recommended_kinds.yaml +0 -0
  243. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ai_governance_eu_act/severity_rules.yaml +0 -0
  244. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rate_limiting_caching/coverage_matrix.md +0 -0
  245. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rate_limiting_caching/elicit_extend.md +0 -0
  246. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rate_limiting_caching/lexicon.yaml +0 -0
  247. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rate_limiting_caching/manifest.yaml +0 -0
  248. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rate_limiting_caching/recommended_kinds.yaml +0 -0
  249. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rate_limiting_caching/severity_rules.yaml +0 -0
  250. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rest_openapi/coverage_matrix.md +0 -0
  251. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rest_openapi/elicit_extend.md +0 -0
  252. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rest_openapi/lexicon.yaml +0 -0
  253. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rest_openapi/manifest.yaml +0 -0
  254. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rest_openapi/recommended_kinds.yaml +0 -0
  255. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/api_rest_openapi/severity_rules.yaml +0 -0
  256. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/babok/elicit_extend.md +0 -0
  257. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/babok/lexicon.yaml +0 -0
  258. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/babok/manifest.yaml +0 -0
  259. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/babok/recommended_kinds.yaml +0 -0
  260. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/babok/severity_rules.yaml +0 -0
  261. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_event_cloudevents/coverage_matrix.md +0 -0
  262. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_event_cloudevents/elicit_extend.md +0 -0
  263. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_event_cloudevents/lexicon.yaml +0 -0
  264. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_event_cloudevents/manifest.yaml +0 -0
  265. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_event_cloudevents/recommended_kinds.yaml +0 -0
  266. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_event_cloudevents/severity_rules.yaml +0 -0
  267. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_graphql/coverage_matrix.md +0 -0
  268. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_graphql/elicit_extend.md +0 -0
  269. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_graphql/lexicon.yaml +0 -0
  270. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_graphql/manifest.yaml +0 -0
  271. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_graphql/recommended_kinds.yaml +0 -0
  272. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_graphql/severity_rules.yaml +0 -0
  273. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_grpc_proto/coverage_matrix.md +0 -0
  274. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_grpc_proto/elicit_extend.md +0 -0
  275. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_grpc_proto/lexicon.yaml +0 -0
  276. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_grpc_proto/manifest.yaml +0 -0
  277. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_grpc_proto/recommended_kinds.yaml +0 -0
  278. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/backend_grpc_proto/severity_rules.yaml +0 -0
  279. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_hipaa/coverage_matrix.md +0 -0
  280. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_hipaa/elicit_extend.md +0 -0
  281. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_hipaa/lexicon.yaml +0 -0
  282. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_hipaa/manifest.yaml +0 -0
  283. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_hipaa/recommended_kinds.yaml +0 -0
  284. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_hipaa/severity_rules.yaml +0 -0
  285. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_iso27001/coverage_matrix.md +0 -0
  286. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_iso27001/elicit_extend.md +0 -0
  287. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_iso27001/lexicon.yaml +0 -0
  288. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_iso27001/manifest.yaml +0 -0
  289. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_iso27001/recommended_kinds.yaml +0 -0
  290. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_iso27001/severity_rules.yaml +0 -0
  291. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_pci_dss_4/coverage_matrix.md +0 -0
  292. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_pci_dss_4/elicit_extend.md +0 -0
  293. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_pci_dss_4/lexicon.yaml +0 -0
  294. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_pci_dss_4/manifest.yaml +0 -0
  295. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_pci_dss_4/recommended_kinds.yaml +0 -0
  296. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/compliance_pci_dss_4/severity_rules.yaml +0 -0
  297. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/coverage_matrix.md +0 -0
  298. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/elicit_extend.md +0 -0
  299. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/lexicon.yaml +0 -0
  300. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/manifest.yaml +0 -0
  301. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/recommended_kinds.yaml +0 -0
  302. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/severity_rules.yaml +0 -0
  303. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_governance_appi_gdpr/coverage_matrix.md +0 -0
  304. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_governance_appi_gdpr/elicit_extend.md +0 -0
  305. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_governance_appi_gdpr/lexicon.yaml +0 -0
  306. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_governance_appi_gdpr/manifest.yaml +0 -0
  307. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_governance_appi_gdpr/recommended_kinds.yaml +0 -0
  308. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_governance_appi_gdpr/severity_rules.yaml +0 -0
  309. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_nosql_jsonschema/coverage_matrix.md +0 -0
  310. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_nosql_jsonschema/elicit_extend.md +0 -0
  311. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_nosql_jsonschema/lexicon.yaml +0 -0
  312. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_nosql_jsonschema/manifest.yaml +0 -0
  313. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_nosql_jsonschema/recommended_kinds.yaml +0 -0
  314. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_nosql_jsonschema/severity_rules.yaml +0 -0
  315. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_relational_iso_sql/coverage_matrix.md +0 -0
  316. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_relational_iso_sql/elicit_extend.md +0 -0
  317. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_relational_iso_sql/lexicon.yaml +0 -0
  318. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_relational_iso_sql/manifest.yaml +0 -0
  319. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_relational_iso_sql/recommended_kinds.yaml +0 -0
  320. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/data_relational_iso_sql/severity_rules.yaml +0 -0
  321. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ddd_domain_driven_design/coverage_matrix.md +0 -0
  322. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ddd_domain_driven_design/elicit_extend.md +0 -0
  323. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ddd_domain_driven_design/lexicon.yaml +0 -0
  324. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ddd_domain_driven_design/manifest.yaml +0 -0
  325. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ddd_domain_driven_design/recommended_kinds.yaml +0 -0
  326. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ddd_domain_driven_design/severity_rules.yaml +0 -0
  327. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/dora_sre_metrics/coverage_matrix.md +0 -0
  328. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/dora_sre_metrics/elicit_extend.md +0 -0
  329. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/dora_sre_metrics/lexicon.yaml +0 -0
  330. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/dora_sre_metrics/manifest.yaml +0 -0
  331. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/dora_sre_metrics/recommended_kinds.yaml +0 -0
  332. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/dora_sre_metrics/severity_rules.yaml +0 -0
  333. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/i18n_unicode_cldr/coverage_matrix.md +0 -0
  334. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/i18n_unicode_cldr/elicit_extend.md +0 -0
  335. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/i18n_unicode_cldr/lexicon.yaml +0 -0
  336. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/i18n_unicode_cldr/manifest.yaml +0 -0
  337. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/i18n_unicode_cldr/recommended_kinds.yaml +0 -0
  338. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/i18n_unicode_cldr/severity_rules.yaml +0 -0
  339. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ml_model_cards/coverage_matrix.md +0 -0
  340. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ml_model_cards/elicit_extend.md +0 -0
  341. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ml_model_cards/lexicon.yaml +0 -0
  342. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ml_model_cards/manifest.yaml +0 -0
  343. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ml_model_cards/recommended_kinds.yaml +0 -0
  344. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ml_model_cards/severity_rules.yaml +0 -0
  345. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_a11y_native/coverage_matrix.md +0 -0
  346. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_a11y_native/elicit_extend.md +0 -0
  347. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_a11y_native/lexicon.yaml +0 -0
  348. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_a11y_native/manifest.yaml +0 -0
  349. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_a11y_native/recommended_kinds.yaml +0 -0
  350. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_a11y_native/severity_rules.yaml +0 -0
  351. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_android_material3/coverage_matrix.md +0 -0
  352. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_android_material3/elicit_extend.md +0 -0
  353. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_android_material3/lexicon.yaml +0 -0
  354. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_android_material3/manifest.yaml +0 -0
  355. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_android_material3/recommended_kinds.yaml +0 -0
  356. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_android_material3/severity_rules.yaml +0 -0
  357. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_ios_hig/coverage_matrix.md +0 -0
  358. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_ios_hig/elicit_extend.md +0 -0
  359. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_ios_hig/lexicon.yaml +0 -0
  360. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_ios_hig/manifest.yaml +0 -0
  361. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_ios_hig/recommended_kinds.yaml +0 -0
  362. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_ios_hig/severity_rules.yaml +0 -0
  363. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_security_masvs/coverage_matrix.md +0 -0
  364. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_security_masvs/elicit_extend.md +0 -0
  365. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_security_masvs/lexicon.yaml +0 -0
  366. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_security_masvs/manifest.yaml +0 -0
  367. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_security_masvs/recommended_kinds.yaml +0 -0
  368. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/mobile_security_masvs/severity_rules.yaml +0 -0
  369. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_cicd_pipeline/coverage_matrix.md +0 -0
  370. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_cicd_pipeline/elicit_extend.md +0 -0
  371. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_cicd_pipeline/lexicon.yaml +0 -0
  372. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_cicd_pipeline/manifest.yaml +0 -0
  373. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_cicd_pipeline/recommended_kinds.yaml +0 -0
  374. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_cicd_pipeline/severity_rules.yaml +0 -0
  375. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_iac_terraform/coverage_matrix.md +0 -0
  376. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_iac_terraform/elicit_extend.md +0 -0
  377. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_iac_terraform/lexicon.yaml +0 -0
  378. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_iac_terraform/manifest.yaml +0 -0
  379. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_iac_terraform/recommended_kinds.yaml +0 -0
  380. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_iac_terraform/severity_rules.yaml +0 -0
  381. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_kubernetes/coverage_matrix.md +0 -0
  382. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_kubernetes/elicit_extend.md +0 -0
  383. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_kubernetes/lexicon.yaml +0 -0
  384. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_kubernetes/manifest.yaml +0 -0
  385. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_kubernetes/recommended_kinds.yaml +0 -0
  386. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_kubernetes/severity_rules.yaml +0 -0
  387. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_observability_otel/coverage_matrix.md +0 -0
  388. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_observability_otel/elicit_extend.md +0 -0
  389. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_observability_otel/lexicon.yaml +0 -0
  390. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_observability_otel/manifest.yaml +0 -0
  391. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_observability_otel/recommended_kinds.yaml +0 -0
  392. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/ops_observability_otel/severity_rules.yaml +0 -0
  393. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_iso25010/coverage_matrix.md +0 -0
  394. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_iso25010/elicit_extend.md +0 -0
  395. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_iso25010/lexicon.yaml +0 -0
  396. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_iso25010/manifest.yaml +0 -0
  397. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_iso25010/recommended_kinds.yaml +0 -0
  398. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_iso25010/severity_rules.yaml +0 -0
  399. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_test_iso29119/coverage_matrix.md +0 -0
  400. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_test_iso29119/elicit_extend.md +0 -0
  401. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_test_iso29119/lexicon.yaml +0 -0
  402. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_test_iso29119/manifest.yaml +0 -0
  403. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_test_iso29119/recommended_kinds.yaml +0 -0
  404. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/process_test_iso29119/severity_rules.yaml +0 -0
  405. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/twelve_factor_app/coverage_matrix.md +0 -0
  406. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/twelve_factor_app/elicit_extend.md +0 -0
  407. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/twelve_factor_app/lexicon.yaml +0 -0
  408. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/twelve_factor_app/manifest.yaml +0 -0
  409. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/twelve_factor_app/recommended_kinds.yaml +0 -0
  410. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/twelve_factor_app/severity_rules.yaml +0 -0
  411. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/coverage_matrix.md +0 -0
  412. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/elicit_extend.md +0 -0
  413. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/lexicon.yaml +0 -0
  414. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/manifest.yaml +0 -0
  415. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/recommended_kinds.yaml +0 -0
  416. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/severity_rules.yaml +0 -0
  417. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_authn_webauthn/coverage_matrix.md +0 -0
  418. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_authn_webauthn/elicit_extend.md +0 -0
  419. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_authn_webauthn/lexicon.yaml +0 -0
  420. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_authn_webauthn/manifest.yaml +0 -0
  421. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_authn_webauthn/recommended_kinds.yaml +0 -0
  422. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_authn_webauthn/severity_rules.yaml +0 -0
  423. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_browser_compat/coverage_matrix.md +0 -0
  424. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_browser_compat/elicit_extend.md +0 -0
  425. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_browser_compat/lexicon.yaml +0 -0
  426. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_browser_compat/manifest.yaml +0 -0
  427. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_browser_compat/recommended_kinds.yaml +0 -0
  428. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_browser_compat/severity_rules.yaml +0 -0
  429. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_forms_html5/coverage_matrix.md +0 -0
  430. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_forms_html5/elicit_extend.md +0 -0
  431. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_forms_html5/lexicon.yaml +0 -0
  432. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_forms_html5/manifest.yaml +0 -0
  433. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_forms_html5/recommended_kinds.yaml +0 -0
  434. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_forms_html5/severity_rules.yaml +0 -0
  435. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_performance_core_web_vitals/coverage_matrix.md +0 -0
  436. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_performance_core_web_vitals/elicit_extend.md +0 -0
  437. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_performance_core_web_vitals/lexicon.yaml +0 -0
  438. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_performance_core_web_vitals/manifest.yaml +0 -0
  439. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_performance_core_web_vitals/recommended_kinds.yaml +0 -0
  440. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_performance_core_web_vitals/severity_rules.yaml +0 -0
  441. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_pwa_manifest/coverage_matrix.md +0 -0
  442. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_pwa_manifest/elicit_extend.md +0 -0
  443. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_pwa_manifest/lexicon.yaml +0 -0
  444. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_pwa_manifest/manifest.yaml +0 -0
  445. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_pwa_manifest/recommended_kinds.yaml +0 -0
  446. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_pwa_manifest/severity_rules.yaml +0 -0
  447. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_responsive/coverage_matrix.md +0 -0
  448. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_responsive/elicit_extend.md +0 -0
  449. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_responsive/lexicon.yaml +0 -0
  450. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_responsive/manifest.yaml +0 -0
  451. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_responsive/recommended_kinds.yaml +0 -0
  452. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_responsive/severity_rules.yaml +0 -0
  453. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_security_owasp/coverage_matrix.md +0 -0
  454. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_security_owasp/elicit_extend.md +0 -0
  455. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_security_owasp/lexicon.yaml +0 -0
  456. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_security_owasp/manifest.yaml +0 -0
  457. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_security_owasp/recommended_kinds.yaml +0 -0
  458. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_security_owasp/severity_rules.yaml +0 -0
  459. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_seo_schemaorg/coverage_matrix.md +0 -0
  460. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_seo_schemaorg/elicit_extend.md +0 -0
  461. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_seo_schemaorg/lexicon.yaml +0 -0
  462. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_seo_schemaorg/manifest.yaml +0 -0
  463. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_seo_schemaorg/recommended_kinds.yaml +0 -0
  464. {codd_dev-2.11.0 → codd_dev-2.12.0}/codd_plugins/lexicons/web_seo_schemaorg/severity_rules.yaml +0 -0
  465. {codd_dev-2.11.0 → codd_dev-2.12.0}/docs/cookbook/cdp_browser/README.md +0 -0
  466. {codd_dev-2.11.0 → codd_dev-2.12.0}/docs/requirements/README.md +0 -0
  467. {codd_dev-2.11.0 → codd_dev-2.12.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.12.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,10 @@ 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.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).
157
+ - **v2.11.0** — Sprint-less `codd implement` (`--design <path> --output <dir>` directly; `implementation_plan.md` parser removed). See [migration guide](docs/migrations/v2.11.0-sprintless.md).
158
+ - **v2.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.
158
160
 
159
161
  ---
160
162
 
@@ -113,8 +113,10 @@ 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.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).
117
+ - **v2.11.0** — Sprint-less `codd implement` (`--design <path> --output <dir>` directly; `implementation_plan.md` parser removed). See [migration guide](docs/migrations/v2.11.0-sprintless.md).
118
+ - **v2.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.
118
120
 
119
121
  ---
120
122
 
@@ -0,0 +1,358 @@
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
+
16
+
17
+ _DEFAULT_PROVIDER = "github" + "_actions"
18
+
19
+
20
+ @dataclass
21
+ class CiConfig:
22
+ provider: str = _DEFAULT_PROVIDER
23
+ workflow_glob: str = ".github/workflows/*.yml"
24
+ required_triggers: list[str] = field(default_factory=lambda: ["push", "pull_request"])
25
+ runtime_check: bool = False
26
+ staleness_days: int = 14
27
+ default_branch: str = "main"
28
+ trigger_key: str = "on"
29
+
30
+ @classmethod
31
+ def from_mapping(cls, value: Mapping[str, Any] | None) -> "CiConfig":
32
+ if not isinstance(value, Mapping):
33
+ return cls(provider="none")
34
+
35
+ config = cls()
36
+ return cls(
37
+ provider=_string_value(value.get("provider"), config.provider),
38
+ workflow_glob=_string_value(value.get("workflow_glob"), config.workflow_glob),
39
+ required_triggers=_string_list(value.get("required_triggers"), config.required_triggers),
40
+ runtime_check=bool(value.get("runtime_check", config.runtime_check)),
41
+ staleness_days=_int_value(value.get("staleness_days"), config.staleness_days),
42
+ default_branch=_string_value(value.get("default_branch"), config.default_branch),
43
+ trigger_key=_string_value(value.get("trigger_key"), config.trigger_key),
44
+ )
45
+
46
+
47
+ @dataclass
48
+ class CiHealthFinding:
49
+ violation_type: str
50
+ severity: str
51
+ block_deploy: bool
52
+ message: str
53
+ details: list[str] = field(default_factory=list)
54
+
55
+
56
+ @dataclass
57
+ class CiHealthResult:
58
+ check_name: str = "ci_health"
59
+ status: str = "pass"
60
+ severity: str = "info"
61
+ block_deploy: bool = False
62
+ message: str = "C8 ci_health PASS"
63
+ findings: list[CiHealthFinding] = field(default_factory=list)
64
+ workflow_files: list[str] = field(default_factory=list)
65
+ passed: bool = True
66
+
67
+
68
+ @register_dag_check("ci_health")
69
+ class CiHealthCheck(DagCheck):
70
+ """C8 CI workflow presence and trigger validation.
71
+
72
+ Runtime provider polling is intentionally deferred. The shipped path is
73
+ static, deterministic, and driven by config values.
74
+ """
75
+
76
+ check_name = "ci_health"
77
+ severity = "red"
78
+ block_deploy = True
79
+
80
+ def run(
81
+ self,
82
+ dag: Any | None = None,
83
+ project_root: str | Path | None = None,
84
+ settings: dict[str, Any] | None = None,
85
+ codd_config: dict[str, Any] | None = None,
86
+ ) -> CiHealthResult:
87
+ del dag
88
+ root = Path(project_root or self.project_root or ".").resolve()
89
+ active_settings = codd_config or settings or self.settings
90
+ return self.check(root, CiConfig.from_mapping(_mapping_value(active_settings, "ci")))
91
+
92
+ def check(self, project_root: Path, config: CiConfig) -> CiHealthResult:
93
+ project_root = Path(project_root).resolve()
94
+ if config.provider.strip().lower() == "none":
95
+ return CiHealthResult(
96
+ status="skip",
97
+ message="ci.provider=none, C8 SKIP",
98
+ passed=True,
99
+ )
100
+
101
+ workflow_files = self._locate_workflows(project_root, config.workflow_glob)
102
+ if not workflow_files:
103
+ finding = CiHealthFinding(
104
+ violation_type="ci_workflow_missing",
105
+ severity="red",
106
+ block_deploy=True,
107
+ message="No CI workflow files found matching glob.",
108
+ details=[config.workflow_glob],
109
+ )
110
+ return CiHealthResult(
111
+ status="fail",
112
+ severity="red",
113
+ block_deploy=True,
114
+ message=finding.message,
115
+ findings=[finding],
116
+ passed=False,
117
+ )
118
+
119
+ findings = [
120
+ *self._check_triggers(workflow_files, config.required_triggers, config.trigger_key),
121
+ *self._check_verification_coverage(workflow_files, project_root),
122
+ ]
123
+ block_deploy = any(finding.block_deploy for finding in findings)
124
+ severity = _max_severity(finding.severity for finding in findings)
125
+ status = "fail" if block_deploy else ("warn" if findings else "pass")
126
+ message = (
127
+ "C8 ci_health PASS"
128
+ if not findings
129
+ else f"C8 ci_health found {len(findings)} static finding(s)"
130
+ )
131
+ return CiHealthResult(
132
+ status=status,
133
+ severity=severity,
134
+ block_deploy=block_deploy,
135
+ message=message,
136
+ findings=findings,
137
+ workflow_files=[path.relative_to(project_root).as_posix() for path in workflow_files],
138
+ passed=not block_deploy,
139
+ )
140
+
141
+ def format_report(self, result: CiHealthResult) -> str:
142
+ return json.dumps({"ci_health_report": asdict(result)}, ensure_ascii=False, indent=2)
143
+
144
+ def _locate_workflows(self, project_root: Path, workflow_glob: str) -> list[Path]:
145
+ pattern = workflow_glob.strip()
146
+ if not pattern:
147
+ return []
148
+ if Path(pattern).is_absolute():
149
+ paths = [Path(path) for path in glob(pattern)]
150
+ else:
151
+ paths = list(project_root.glob(pattern))
152
+ return sorted(path for path in paths if path.is_file())
153
+
154
+ def _check_triggers(
155
+ self,
156
+ workflow_files: list[Path],
157
+ required_triggers: list[str],
158
+ trigger_key: str,
159
+ ) -> list[CiHealthFinding]:
160
+ required = {trigger.strip() for trigger in required_triggers if trigger.strip()}
161
+ if not required:
162
+ return []
163
+
164
+ actual: set[str] = set()
165
+ for path in workflow_files:
166
+ actual.update(self._workflow_triggers(path, trigger_key))
167
+
168
+ missing = sorted(required - actual)
169
+ if not missing:
170
+ return []
171
+ return [
172
+ CiHealthFinding(
173
+ violation_type="ci_trigger_incomplete",
174
+ severity="amber",
175
+ block_deploy=False,
176
+ message="CI workflow does not include all required triggers.",
177
+ details=[f"missing: {', '.join(missing)}"],
178
+ )
179
+ ]
180
+
181
+ def _workflow_triggers(self, path: Path, trigger_key: str) -> set[str]:
182
+ payload = _read_yaml_mapping(path)
183
+ value = payload.get(trigger_key)
184
+ if value is None and trigger_key == "on":
185
+ value = payload.get(True)
186
+ return _trigger_names(value)
187
+
188
+ def _check_verification_coverage(
189
+ self,
190
+ workflow_files: list[Path],
191
+ project_root: Path,
192
+ ) -> list[CiHealthFinding]:
193
+ verification_commands = self._deploy_verification_commands(project_root)
194
+ if not verification_commands:
195
+ return []
196
+
197
+ workflow_commands = {
198
+ _normalize_command(command)
199
+ for path in workflow_files
200
+ for command in self._workflow_commands(path)
201
+ if _normalize_command(command)
202
+ }
203
+ missing = [
204
+ command
205
+ for command in verification_commands
206
+ if not self._command_appears_in_workflow(command, workflow_commands)
207
+ ]
208
+ if not missing:
209
+ return []
210
+ return [
211
+ CiHealthFinding(
212
+ violation_type="ci_verification_not_in_workflow",
213
+ severity="amber",
214
+ block_deploy=False,
215
+ message="Deployment verification command is not invoked by CI workflow.",
216
+ details=missing,
217
+ )
218
+ ]
219
+
220
+ def _deploy_verification_commands(self, project_root: Path) -> list[str]:
221
+ commands: list[str] = []
222
+ for path in self._deploy_yaml_candidates(project_root):
223
+ if not path.is_file():
224
+ continue
225
+ payload = _read_yaml_mapping(path)
226
+ commands.extend(_hook_commands(payload))
227
+ return _dedupe(_normalize_command(command) for command in commands if _normalize_command(command))
228
+
229
+ @staticmethod
230
+ def _deploy_yaml_candidates(project_root: Path) -> list[Path]:
231
+ return [
232
+ project_root / "deploy.yaml",
233
+ project_root / ".codd" / "deploy.yaml",
234
+ project_root / "codd" / "deploy.yaml",
235
+ ]
236
+
237
+ def _workflow_commands(self, path: Path) -> list[str]:
238
+ return _command_values(_read_yaml_mapping(path))
239
+
240
+ @staticmethod
241
+ def _command_appears_in_workflow(command: str, workflow_commands: set[str]) -> bool:
242
+ return any(command == candidate or command in candidate for candidate in workflow_commands)
243
+
244
+
245
+ def _read_yaml_mapping(path: Path) -> dict[str, Any]:
246
+ payload = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
247
+ return payload if isinstance(payload, dict) else {}
248
+
249
+
250
+ def _mapping_value(mapping: Any, key: str) -> Mapping[str, Any] | None:
251
+ if isinstance(mapping, Mapping) and isinstance(mapping.get(key), Mapping):
252
+ return mapping[key]
253
+ return None
254
+
255
+
256
+ def _trigger_names(value: Any) -> set[str]:
257
+ if isinstance(value, str):
258
+ return {value}
259
+ if isinstance(value, list):
260
+ return {str(item) for item in value if item}
261
+ if isinstance(value, dict):
262
+ return {str(key) for key in value if key}
263
+ return set()
264
+
265
+
266
+ def _hook_commands(value: Any) -> list[str]:
267
+ if isinstance(value, str):
268
+ return [value]
269
+ if isinstance(value, list):
270
+ commands: list[str] = []
271
+ for item in value:
272
+ commands.extend(_hook_commands(item))
273
+ return commands
274
+ if isinstance(value, dict):
275
+ commands: list[str] = []
276
+ for key in ("post_deploy", "post_deploy_steps", "post_deploy_hooks", "verification", "verifications"):
277
+ commands.extend(_hook_commands(value.get(key)))
278
+ for key in ("command", "run", "script", "test"):
279
+ commands.extend(_hook_commands(value.get(key)))
280
+ targets = value.get("targets")
281
+ if isinstance(targets, dict):
282
+ for target_config in targets.values():
283
+ commands.extend(_hook_commands(target_config))
284
+ return commands
285
+ return []
286
+
287
+
288
+ def _command_values(value: Any) -> list[str]:
289
+ if isinstance(value, str):
290
+ return []
291
+ if isinstance(value, list):
292
+ commands: list[str] = []
293
+ for item in value:
294
+ commands.extend(_command_values(item))
295
+ return commands
296
+ if isinstance(value, dict):
297
+ commands: list[str] = []
298
+ for key, item in value.items():
299
+ if key in {"run", "script", "command", "commands"}:
300
+ commands.extend(_coerce_command_list(item))
301
+ else:
302
+ commands.extend(_command_values(item))
303
+ return commands
304
+ return []
305
+
306
+
307
+ def _coerce_command_list(value: Any) -> list[str]:
308
+ if isinstance(value, str):
309
+ return [value]
310
+ if isinstance(value, list):
311
+ commands: list[str] = []
312
+ for item in value:
313
+ commands.extend(_coerce_command_list(item))
314
+ return commands
315
+ return []
316
+
317
+
318
+ def _normalize_command(value: str) -> str:
319
+ return re.sub(r"\s+", " ", value).strip()
320
+
321
+
322
+ def _dedupe(values: Any) -> list[str]:
323
+ seen: set[str] = set()
324
+ result: list[str] = []
325
+ for value in values:
326
+ if not value or value in seen:
327
+ continue
328
+ seen.add(value)
329
+ result.append(value)
330
+ return result
331
+
332
+
333
+ def _string_value(value: Any, default: str) -> str:
334
+ return value if isinstance(value, str) and value.strip() else default
335
+
336
+
337
+ def _string_list(value: Any, default: list[str]) -> list[str]:
338
+ if not isinstance(value, list):
339
+ return list(default)
340
+ result = [str(item) for item in value if str(item).strip()]
341
+ return result or list(default)
342
+
343
+
344
+ def _int_value(value: Any, default: int) -> int:
345
+ try:
346
+ return int(value)
347
+ except (TypeError, ValueError):
348
+ return default
349
+
350
+
351
+ def _max_severity(values: Any) -> str:
352
+ order = {"info": 0, "amber": 1, "red": 2}
353
+ selected = "info"
354
+ for value in values:
355
+ text = str(value)
356
+ if order.get(text, 0) > order[selected]:
357
+ selected = text
358
+ return selected
@@ -30,6 +30,7 @@ class UserJourneyCoherenceResult:
30
30
  check_name: str = "user_journey_coherence"
31
31
  severity: str = "red"
32
32
  status: str = "pass"
33
+ violation_type: str | None = None
33
34
  message: str = ""
34
35
  block_deploy: bool = True
35
36
  violations: list[dict[str, Any]] = field(default_factory=list)
@@ -68,10 +69,41 @@ class UserJourneyCoherenceCheck(DagCheck):
68
69
  if node.kind == "design_doc" and self._journey_entries(node)
69
70
  ]
70
71
  if not journey_docs:
72
+ actors = self._extract_actors(target_dag)
73
+ if actors:
74
+ message = (
75
+ f"Actors identified ({', '.join(actors)}) but no user_journeys declared. "
76
+ "Consider declaring journeys for each actor."
77
+ )
78
+ violation = {
79
+ "type": "actors_without_journeys",
80
+ "severity": "amber",
81
+ "actors": actors,
82
+ "message": message,
83
+ "block_deploy": False,
84
+ "human_review_required": self._human_review_required(actors),
85
+ }
86
+ return UserJourneyCoherenceResult(
87
+ severity="amber",
88
+ status="warn",
89
+ violation_type="actors_without_journeys",
90
+ message=message,
91
+ block_deploy=False,
92
+ violations=[violation],
93
+ journey_reports=[
94
+ {
95
+ "user_journey": "(none declared)",
96
+ "design_doc": "(none)",
97
+ "violations": [violation],
98
+ "remediation_hints": ["Declare user_journeys for the identified actors."],
99
+ }
100
+ ],
101
+ passed=True,
102
+ )
71
103
  return UserJourneyCoherenceResult(
72
104
  severity="info",
73
105
  status="pass",
74
- message="No user_journeys declared, C7 SKIP",
106
+ message="No actors and no user_journeys declared, C7 SKIP",
75
107
  block_deploy=self.block_deploy,
76
108
  )
77
109
 
@@ -195,6 +227,22 @@ class UserJourneyCoherenceCheck(DagCheck):
195
227
  report["remediation_hints"] = self._remediation_hints(report["violations"], design_doc)
196
228
  return report
197
229
 
230
+ def _extract_actors(self, dag: DAG) -> list[str]:
231
+ actors: list[str] = []
232
+ for node in sorted(dag.nodes.values(), key=lambda item: item.id):
233
+ actors.extend(self._actor_names_from_mapping(node.attributes))
234
+ details = node.attributes.get("details")
235
+ if isinstance(details, dict):
236
+ actors.extend(
237
+ self._actor_names_from_mapping(
238
+ details,
239
+ actor_dimension=self._is_actor_dimension(details),
240
+ )
241
+ )
242
+ if self._is_actor_dimension(node.attributes):
243
+ actors.extend(self._actor_names_from_mapping(node.attributes, actor_dimension=True))
244
+ return self._dedupe_strings(actors)
245
+
198
246
  def _runtime_constraint_violations(
199
247
  self,
200
248
  dag: DAG,
@@ -657,6 +705,70 @@ class UserJourneyCoherenceCheck(DagCheck):
657
705
  )
658
706
  )
659
707
 
708
+ def _actor_names_from_mapping(self, mapping: dict[str, Any], *, actor_dimension: bool = False) -> list[str]:
709
+ keys = {
710
+ "actor",
711
+ "actors",
712
+ "role",
713
+ "roles",
714
+ "stakeholder",
715
+ "stakeholders",
716
+ "stakeholder_roles",
717
+ }
718
+ if actor_dimension:
719
+ keys.update({"value", "values", "item", "items", "candidate", "candidates", "name", "names"})
720
+
721
+ actors: list[str] = []
722
+ for key, value in mapping.items():
723
+ if str(key).strip().lower() in keys:
724
+ actors.extend(self._actor_names_from_value(value))
725
+ return self._dedupe_strings(actors)
726
+
727
+ def _actor_names_from_value(self, value: Any) -> list[str]:
728
+ if value is None:
729
+ return []
730
+ if isinstance(value, str):
731
+ return [actor for item in re.split(r"[,;\n]+", value) if (actor := self._clean_actor_name(item))]
732
+ if isinstance(value, dict):
733
+ for key in ("name", "id", "label", "role", "actor", "stakeholder"):
734
+ if key in value:
735
+ return self._actor_names_from_value(value[key])
736
+ return []
737
+ if isinstance(value, Iterable) and not isinstance(value, (bytes, bytearray)):
738
+ actors: list[str] = []
739
+ for item in value:
740
+ actors.extend(self._actor_names_from_value(item))
741
+ return self._dedupe_strings(actors)
742
+ actor = self._clean_actor_name(str(value))
743
+ return [actor] if actor else []
744
+
745
+ @staticmethod
746
+ def _clean_actor_name(value: str) -> str | None:
747
+ text = value.strip().strip("'\"`")
748
+ if not text or len(text) > 80:
749
+ return None
750
+ if text.lower() in {
751
+ "actor",
752
+ "actors",
753
+ "role",
754
+ "roles",
755
+ "stakeholder",
756
+ "stakeholders",
757
+ "covered",
758
+ "implicit",
759
+ "gap",
760
+ }:
761
+ return None
762
+ return text
763
+
764
+ @staticmethod
765
+ def _is_actor_dimension(attributes: dict[str, Any]) -> bool:
766
+ for key in ("dimension", "axis", "axis_type"):
767
+ value = attributes.get(key)
768
+ if isinstance(value, str) and any(token in value.lower() for token in ("actor", "stakeholder", "role")):
769
+ return True
770
+ return False
771
+
660
772
  def _runtime_state_summary(self, actual_caps: set[str]) -> str:
661
773
  return f"capabilities_provided=[{', '.join(sorted(actual_caps))}]"
662
774
 
@@ -18,6 +18,7 @@ CHECK_MODULES = (
18
18
  "codd.dag.checks.transitive_closure",
19
19
  "codd.dag.checks.deployment_completeness",
20
20
  "codd.dag.checks.user_journey_coherence",
21
+ "codd.dag.checks.ci_health",
21
22
  "codd.dag.checks.implementation_coverage",
22
23
  "codd.dag.checks.environment_coverage",
23
24
  )
@@ -217,7 +217,7 @@ def run_deploy(
217
217
 
218
218
 
219
219
  def _run_deploy_gates(project_root: Path) -> DeployGateResult:
220
- """Run validate, drift, coverage, DAG, C6, and C7 gates before apply deploy."""
220
+ """Run validate, drift, coverage, DAG, C6, C7, and C8 gates before apply deploy."""
221
221
  project_root = Path(project_root).resolve()
222
222
  settings = _load_gate_settings(project_root)
223
223
  codd_dir = _find_gate_codd_dir(project_root)
@@ -231,6 +231,7 @@ def _run_deploy_gates(project_root: Path) -> DeployGateResult:
231
231
  _collect_dag_completeness_gate(project_root, settings, result)
232
232
  _collect_deployment_completeness_gate_result(project_root, settings, result)
233
233
  _collect_user_journey_coherence_gate_result(project_root, settings, result)
234
+ _collect_ci_health_gate_result(project_root, settings, result)
234
235
  return result
235
236
 
236
237
 
@@ -525,6 +526,63 @@ def _collect_user_journey_coherence_gate_result(
525
526
  _ntfy_user_journey_coherence_fail(red_violations, settings)
526
527
 
527
528
 
529
+ def _collect_ci_health_gate(
530
+ project_root: Path,
531
+ codd_config: dict[str, Any],
532
+ ) -> Any:
533
+ """Run the C8 ci_health check and return its result."""
534
+
535
+ from codd.dag.checks.ci_health import CiConfig, CiHealthCheck
536
+
537
+ return CiHealthCheck().check(
538
+ Path(project_root).resolve(),
539
+ CiConfig.from_mapping(codd_config.get("ci")),
540
+ )
541
+
542
+
543
+ def _collect_ci_health_gate_result(
544
+ project_root: Path,
545
+ settings: dict[str, Any],
546
+ result: DeployGateResult,
547
+ ) -> None:
548
+ if "ci" not in settings:
549
+ return
550
+
551
+ try:
552
+ check_result = _collect_ci_health_gate(project_root, settings)
553
+ except Exception as exc: # pragma: no cover - defensive gate behavior
554
+ result.add_failure("ci_health", str(exc))
555
+ return
556
+
557
+ if str(_result_value(check_result, "status") or "").lower() == "skip":
558
+ return
559
+
560
+ findings = list(_result_value(check_result, "findings") or [])
561
+ if not findings:
562
+ return
563
+
564
+ from codd.dag.checks.ci_health import CiHealthCheck
565
+
566
+ report = CiHealthCheck().format_report(check_result)
567
+ result.add_report("ci_health_report", _parse_ci_health_report(report))
568
+
569
+ red_findings = [finding for finding in findings if _ci_finding_blocks_deploy(finding)]
570
+ amber_findings = [
571
+ finding
572
+ for finding in findings
573
+ if not _ci_finding_blocks_deploy(finding) and _ci_finding_severity(finding) == "amber"
574
+ ]
575
+ if amber_findings:
576
+ result.add_warning(f"ci_health: {len(amber_findings)} amber finding(s)")
577
+
578
+ if red_findings:
579
+ result.add_failure(
580
+ "ci_health",
581
+ f"C8 ci_health: {len(red_findings)} red finding(s)",
582
+ [report],
583
+ )
584
+
585
+
528
586
  def _screen_flow_strict_edges(settings: dict[str, Any]) -> bool:
529
587
  screen_flow_config = settings.get("screen_flow", {})
530
588
  if not isinstance(screen_flow_config, dict):
@@ -821,6 +879,15 @@ def _parse_user_journey_coherence_report(report: str) -> list[dict[str, Any]]:
821
879
  return value if isinstance(value, list) else []
822
880
 
823
881
 
882
+ def _parse_ci_health_report(report: str) -> dict[str, Any]:
883
+ try:
884
+ payload = json.loads(report)
885
+ except json.JSONDecodeError:
886
+ return {}
887
+ value = payload.get("ci_health_report")
888
+ return value if isinstance(value, dict) else {}
889
+
890
+
824
891
  def _red_user_journey_violations(violations: list[Any]) -> list[Any]:
825
892
  return [violation for violation in violations if _user_journey_violation_severity(violation) == "red"]
826
893
 
@@ -833,6 +900,14 @@ def _user_journey_violation_severity(violation: Any) -> str:
833
900
  return str(_violation_attr(violation, "severity") or "red")
834
901
 
835
902
 
903
+ def _ci_finding_blocks_deploy(finding: Any) -> bool:
904
+ return bool(_violation_attr(finding, "block_deploy"))
905
+
906
+
907
+ def _ci_finding_severity(finding: Any) -> str:
908
+ return str(_violation_attr(finding, "severity") or "red")
909
+
910
+
836
911
  def _violation_attr(violation: Any, key: str) -> Any:
837
912
  if isinstance(violation, dict):
838
913
  return violation.get(key)
@@ -2,7 +2,7 @@
2
2
 
3
3
  from codd.elicit.apply import ApplyResult, ElicitApplyEngine
4
4
  from codd.elicit.engine import ElicitEngine
5
- from codd.elicit.finding import Finding, Severity
5
+ from codd.elicit.finding import Finding, FindingDimension, FindingType, Severity
6
6
  from codd.elicit.persistence import ElicitPersistence
7
7
 
8
8
  __all__ = [
@@ -11,5 +11,7 @@ __all__ = [
11
11
  "ElicitEngine",
12
12
  "ElicitPersistence",
13
13
  "Finding",
14
+ "FindingDimension",
15
+ "FindingType",
14
16
  "Severity",
15
17
  ]