codd-dev 2.1.0__tar.gz → 2.3.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 (423) hide show
  1. {codd_dev-2.1.0 → codd_dev-2.3.0}/PKG-INFO +1 -1
  2. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/builder.py +23 -0
  3. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/extractor.py +42 -0
  4. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/apply.py +161 -15
  5. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/engine.py +174 -0
  6. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/lexicon_loader.py +28 -1
  7. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/lexicon.py +14 -0
  8. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/extracted/schema-design.md.j2 +1 -1
  9. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/lexicon_schema.yaml +2 -0
  10. codd_dev-2.3.0/codd_plugins/lexicons/babok/lexicon.yaml +105 -0
  11. codd_dev-2.3.0/codd_plugins/lexicons/babok/severity_rules.yaml +53 -0
  12. {codd_dev-2.1.0 → codd_dev-2.3.0}/pyproject.toml +1 -1
  13. {codd_dev-2.1.0 → codd_dev-2.3.0}/.gitignore +0 -0
  14. {codd_dev-2.1.0 → codd_dev-2.3.0}/LICENSE +0 -0
  15. {codd_dev-2.1.0 → codd_dev-2.3.0}/README.md +0 -0
  16. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/__init__.py +0 -0
  17. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/__main__.py +0 -0
  18. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/_git_helper.py +0 -0
  19. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/ask_user_question_adapter.py +0 -0
  20. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/assembler.py +0 -0
  21. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/bridge.py +0 -0
  22. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/brownfield/__init__.py +0 -0
  23. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/brownfield/pipeline.py +0 -0
  24. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/cli.py +0 -0
  25. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/clustering.py +0 -0
  26. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/coherence_adapters.py +0 -0
  27. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/coherence_engine.py +0 -0
  28. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/config.py +0 -0
  29. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/contracts.py +0 -0
  30. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/coverage_auditor.py +0 -0
  31. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/coverage_metrics.py +0 -0
  32. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/__init__.py +0 -0
  33. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/checks/__init__.py +0 -0
  34. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/checks/depends_on_consistency.py +0 -0
  35. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/checks/deployment_completeness.py +0 -0
  36. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/checks/edge_validity.py +0 -0
  37. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/checks/environment_coverage.py +0 -0
  38. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/checks/implementation_coverage.py +0 -0
  39. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/checks/node_completeness.py +0 -0
  40. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/checks/task_completion.py +0 -0
  41. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/checks/transitive_closure.py +0 -0
  42. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/checks/user_journey_coherence.py +0 -0
  43. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/coverage_axes.py +0 -0
  44. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/cli.yaml +0 -0
  45. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/cpp_embedded.yaml +0 -0
  46. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/csharp.yaml +0 -0
  47. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/elixir.yaml +0 -0
  48. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/generic.yaml +0 -0
  49. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/iot.yaml +0 -0
  50. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/java.yaml +0 -0
  51. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/kotlin.yaml +0 -0
  52. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/mobile.yaml +0 -0
  53. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/ruby.yaml +0 -0
  54. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/rust.yaml +0 -0
  55. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/scala.yaml +0 -0
  56. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/swift.yaml +0 -0
  57. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/test_frameworks.yaml +0 -0
  58. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/defaults/web.yaml +0 -0
  59. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/extractor.py +0 -0
  60. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/dag/runner.py +0 -0
  61. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/defaults.yaml +0 -0
  62. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deploy_targets/__init__.py +0 -0
  63. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deploy_targets/app_service.py +0 -0
  64. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deploy_targets/base.py +0 -0
  65. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deploy_targets/docker_compose.py +0 -0
  66. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployer.py +0 -0
  67. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/__init__.py +0 -0
  68. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/checks/__init__.py +0 -0
  69. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/defaults/deploy_targets.yaml +0 -0
  70. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/defaults/runtime_capability_inference.yaml +0 -0
  71. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/defaults/schema_providers.yaml +0 -0
  72. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/defaults/verification_templates.yaml +0 -0
  73. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/__init__.py +0 -0
  74. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/ai_command.py +0 -0
  75. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/llm_consideration.py +0 -0
  76. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/schema/__init__.py +0 -0
  77. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/schema/prisma.py +0 -0
  78. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/target/__init__.py +0 -0
  79. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/target/docker_compose.py +0 -0
  80. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/verification/__init__.py +0 -0
  81. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/verification/assertion_handlers.py +0 -0
  82. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/verification/cdp_browser.py +0 -0
  83. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/verification/cdp_engines.py +0 -0
  84. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/verification/cdp_launchers.py +0 -0
  85. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/verification/cdp_wire.py +0 -0
  86. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/verification/curl.py +0 -0
  87. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/verification/form_strategies.py +0 -0
  88. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/verification/means_catalog.py +0 -0
  89. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/deployment/providers/verification/playwright.py +0 -0
  90. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/design_md.py +0 -0
  91. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/diff/__init__.py +0 -0
  92. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/diff/apply.py +0 -0
  93. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/diff/engine.py +0 -0
  94. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/diff/persistence.py +0 -0
  95. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/diff/templates/diff_prompt.md +0 -0
  96. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/drift.py +0 -0
  97. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/e2e_extractor.py +0 -0
  98. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/e2e_generator.py +0 -0
  99. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/e2e_runner.py +0 -0
  100. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/__init__.py +0 -0
  101. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/finding.py +0 -0
  102. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/formatters/__init__.py +0 -0
  103. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/formatters/base.py +0 -0
  104. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/formatters/interactive.py +0 -0
  105. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/formatters/json_fmt.py +0 -0
  106. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/formatters/md.py +0 -0
  107. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/persistence.py +0 -0
  108. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/elicit/templates/elicit_prompt_L0.md +0 -0
  109. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/env_refs.py +0 -0
  110. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/extract_ai.py +0 -0
  111. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/extractor.py +0 -0
  112. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/fixer.py +0 -0
  113. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/fixup_drift.py +0 -0
  114. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/fixup_drift_strategies/__init__.py +0 -0
  115. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/fixup_drift_strategies/design_token_drift.py +0 -0
  116. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/fixup_drift_strategies/lexicon_violation.py +0 -0
  117. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/fixup_drift_strategies/url_drift.py +0 -0
  118. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/generator.py +0 -0
  119. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/graph.py +0 -0
  120. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/hitl_session.py +0 -0
  121. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/hooks/__init__.py +0 -0
  122. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/hooks/pre-commit +0 -0
  123. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/hooks/recipes/claude_settings_example.json +0 -0
  124. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/hooks/recipes/codex_hook.sh +0 -0
  125. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/hooks/recipes/git_post_commit.sh +0 -0
  126. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/hooks/recipes/git_pre_commit.sh +0 -0
  127. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/implementer/__init__.py +0 -0
  128. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/implementer/chunked_runner.py +0 -0
  129. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/implementer/typecheck_loop.py +0 -0
  130. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/implementer.py +0 -0
  131. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/inheritance.py +0 -0
  132. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/init/__init__.py +0 -0
  133. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/init/lexicon_suggest.py +0 -0
  134. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/init/stack_detector.py +0 -0
  135. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/knowledge_fetcher.py +0 -0
  136. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/lexicon_cli/__init__.py +0 -0
  137. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/lexicon_cli/formatters/__init__.py +0 -0
  138. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/lexicon_cli/formatters/html.py +0 -0
  139. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/lexicon_cli/formatters/json_fmt.py +0 -0
  140. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/lexicon_cli/formatters/md.py +0 -0
  141. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/lexicon_cli/inspector.py +0 -0
  142. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/lexicon_cli/manager.py +0 -0
  143. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/lexicon_cli/reporter.py +0 -0
  144. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/lexicon_cli/threshold.py +0 -0
  145. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/__init__.py +0 -0
  146. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/approval.py +0 -0
  147. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/best_practice_augmenter.py +0 -0
  148. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/criteria_expander.py +0 -0
  149. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/design_doc_extractor.py +0 -0
  150. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/impl_step_deriver.py +0 -0
  151. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/means_catalog_loader.py +0 -0
  152. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/parser.py +0 -0
  153. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/plan_deriver.py +0 -0
  154. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/prompt_builder.py +0 -0
  155. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/strategy_validator.py +0 -0
  156. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/templates/best_practice_augment_meta.md +0 -0
  157. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/templates/criteria_expand_meta.md +0 -0
  158. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/templates/design_doc_extract_meta.md +0 -0
  159. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/templates/impl_step_derive_meta.md +0 -0
  160. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/templates/implementation_step_catalog.yaml +0 -0
  161. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/templates/meta_instruction.md +0 -0
  162. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/templates/plan_derive_meta.md +0 -0
  163. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/llm/templates/verification_means_catalog.yaml +0 -0
  164. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/mcp_server.py +0 -0
  165. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/measure.py +0 -0
  166. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/parsing.py +0 -0
  167. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/planner.py +0 -0
  168. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/policy.py +0 -0
  169. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/preflight/__init__.py +0 -0
  170. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/preflight/defaults/cli.yaml +0 -0
  171. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/preflight/defaults/iot.yaml +0 -0
  172. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/preflight/defaults/mobile.yaml +0 -0
  173. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/preflight/defaults/web.yaml +0 -0
  174. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/propagate.py +0 -0
  175. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/propagator.py +0 -0
  176. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/registry.py +0 -0
  177. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/__init__.py +0 -0
  178. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/approval_repair.py +0 -0
  179. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/engine.py +0 -0
  180. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/git_patcher.py +0 -0
  181. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/history.py +0 -0
  182. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/llm_repair_engine.py +0 -0
  183. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/loop.py +0 -0
  184. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/primary_picker.py +0 -0
  185. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/proof_breaks.py +0 -0
  186. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/repair_result.py +0 -0
  187. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/repairability_classifier.py +0 -0
  188. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/schema.py +0 -0
  189. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/templates/analyze_meta.md +0 -0
  190. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/templates/propose_meta.md +0 -0
  191. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/templates/repair_strategy_meta.md +0 -0
  192. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/templates/repairability_meta.md +0 -0
  193. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair/verify_runner.py +0 -0
  194. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/repair_slice.py +0 -0
  195. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/require.py +0 -0
  196. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/require_plugins.py +0 -0
  197. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/require_propagate.py +0 -0
  198. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/required_artifacts/defaults/cli.yaml +0 -0
  199. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/required_artifacts/defaults/iot.yaml +0 -0
  200. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/required_artifacts/defaults/mobile.yaml +0 -0
  201. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/required_artifacts/defaults/web.yaml +0 -0
  202. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/required_artifacts_deriver.py +0 -0
  203. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/requirement_completeness/defaults/cli.yaml +0 -0
  204. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/requirement_completeness/defaults/iot.yaml +0 -0
  205. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/requirement_completeness/defaults/mobile.yaml +0 -0
  206. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/requirement_completeness/defaults/web.yaml +0 -0
  207. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/requirement_completeness_auditor.py +0 -0
  208. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/restore.py +0 -0
  209. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/routes_extractor.py +0 -0
  210. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/scanner.py +0 -0
  211. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/schema_refs.py +0 -0
  212. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/screen_flow_validator.py +0 -0
  213. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/screen_transition_extractor.py +0 -0
  214. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/screen_transitions/defaults.yaml +0 -0
  215. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/synth.py +0 -0
  216. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/codd.yaml.tmpl +0 -0
  217. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/conventions.yaml.tmpl +0 -0
  218. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/data_dependencies.yaml.tmpl +0 -0
  219. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/doc_links.yaml.tmpl +0 -0
  220. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/extract_ai_prompt_baseline.md +0 -0
  221. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/extracted/api-contract.md.j2 +0 -0
  222. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/extracted/architecture-overview.md.j2 +0 -0
  223. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/extracted/module-detail.md.j2 +0 -0
  224. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/extracted/system-context.md.j2 +0 -0
  225. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/gitignore.tmpl +0 -0
  226. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/lexicon_questions.md +0 -0
  227. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/templates/overrides.yaml.tmpl +0 -0
  228. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/traceability.py +0 -0
  229. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/validator.py +0 -0
  230. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/watch/__init__.py +0 -0
  231. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/watch/events.py +0 -0
  232. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/watch/propagation_log.py +0 -0
  233. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/watch/propagation_pipeline.py +0 -0
  234. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/watch/test_runner.py +0 -0
  235. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/watch/watcher.py +0 -0
  236. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd/wiring.py +0 -0
  237. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ai_governance_eu_act/coverage_matrix.md +0 -0
  238. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ai_governance_eu_act/elicit_extend.md +0 -0
  239. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ai_governance_eu_act/lexicon.yaml +0 -0
  240. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ai_governance_eu_act/manifest.yaml +0 -0
  241. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ai_governance_eu_act/recommended_kinds.yaml +0 -0
  242. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ai_governance_eu_act/severity_rules.yaml +0 -0
  243. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/api_rest_openapi/coverage_matrix.md +0 -0
  244. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/api_rest_openapi/elicit_extend.md +0 -0
  245. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/api_rest_openapi/lexicon.yaml +0 -0
  246. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/api_rest_openapi/manifest.yaml +0 -0
  247. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/api_rest_openapi/recommended_kinds.yaml +0 -0
  248. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/api_rest_openapi/severity_rules.yaml +0 -0
  249. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/babok/elicit_extend.md +0 -0
  250. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/babok/manifest.yaml +0 -0
  251. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/babok/recommended_kinds.yaml +0 -0
  252. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_event_cloudevents/coverage_matrix.md +0 -0
  253. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_event_cloudevents/elicit_extend.md +0 -0
  254. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_event_cloudevents/lexicon.yaml +0 -0
  255. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_event_cloudevents/manifest.yaml +0 -0
  256. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_event_cloudevents/recommended_kinds.yaml +0 -0
  257. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_event_cloudevents/severity_rules.yaml +0 -0
  258. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_graphql/coverage_matrix.md +0 -0
  259. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_graphql/elicit_extend.md +0 -0
  260. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_graphql/lexicon.yaml +0 -0
  261. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_graphql/manifest.yaml +0 -0
  262. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_graphql/recommended_kinds.yaml +0 -0
  263. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_graphql/severity_rules.yaml +0 -0
  264. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_grpc_proto/coverage_matrix.md +0 -0
  265. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_grpc_proto/elicit_extend.md +0 -0
  266. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_grpc_proto/lexicon.yaml +0 -0
  267. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_grpc_proto/manifest.yaml +0 -0
  268. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_grpc_proto/recommended_kinds.yaml +0 -0
  269. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/backend_grpc_proto/severity_rules.yaml +0 -0
  270. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_hipaa/coverage_matrix.md +0 -0
  271. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_hipaa/elicit_extend.md +0 -0
  272. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_hipaa/lexicon.yaml +0 -0
  273. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_hipaa/manifest.yaml +0 -0
  274. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_hipaa/recommended_kinds.yaml +0 -0
  275. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_hipaa/severity_rules.yaml +0 -0
  276. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_iso27001/coverage_matrix.md +0 -0
  277. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_iso27001/elicit_extend.md +0 -0
  278. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_iso27001/lexicon.yaml +0 -0
  279. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_iso27001/manifest.yaml +0 -0
  280. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_iso27001/recommended_kinds.yaml +0 -0
  281. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_iso27001/severity_rules.yaml +0 -0
  282. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_pci_dss_4/coverage_matrix.md +0 -0
  283. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_pci_dss_4/elicit_extend.md +0 -0
  284. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_pci_dss_4/lexicon.yaml +0 -0
  285. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_pci_dss_4/manifest.yaml +0 -0
  286. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_pci_dss_4/recommended_kinds.yaml +0 -0
  287. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/compliance_pci_dss_4/severity_rules.yaml +0 -0
  288. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/coverage_matrix.md +0 -0
  289. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/elicit_extend.md +0 -0
  290. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/lexicon.yaml +0 -0
  291. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/manifest.yaml +0 -0
  292. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/recommended_kinds.yaml +0 -0
  293. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/severity_rules.yaml +0 -0
  294. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_governance_appi_gdpr/coverage_matrix.md +0 -0
  295. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_governance_appi_gdpr/elicit_extend.md +0 -0
  296. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_governance_appi_gdpr/lexicon.yaml +0 -0
  297. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_governance_appi_gdpr/manifest.yaml +0 -0
  298. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_governance_appi_gdpr/recommended_kinds.yaml +0 -0
  299. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_governance_appi_gdpr/severity_rules.yaml +0 -0
  300. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_nosql_jsonschema/coverage_matrix.md +0 -0
  301. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_nosql_jsonschema/elicit_extend.md +0 -0
  302. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_nosql_jsonschema/lexicon.yaml +0 -0
  303. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_nosql_jsonschema/manifest.yaml +0 -0
  304. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_nosql_jsonschema/recommended_kinds.yaml +0 -0
  305. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_nosql_jsonschema/severity_rules.yaml +0 -0
  306. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_relational_iso_sql/coverage_matrix.md +0 -0
  307. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_relational_iso_sql/elicit_extend.md +0 -0
  308. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_relational_iso_sql/lexicon.yaml +0 -0
  309. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_relational_iso_sql/manifest.yaml +0 -0
  310. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_relational_iso_sql/recommended_kinds.yaml +0 -0
  311. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/data_relational_iso_sql/severity_rules.yaml +0 -0
  312. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_a11y_native/coverage_matrix.md +0 -0
  313. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_a11y_native/elicit_extend.md +0 -0
  314. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_a11y_native/lexicon.yaml +0 -0
  315. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_a11y_native/manifest.yaml +0 -0
  316. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_a11y_native/recommended_kinds.yaml +0 -0
  317. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_a11y_native/severity_rules.yaml +0 -0
  318. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_android_material3/coverage_matrix.md +0 -0
  319. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_android_material3/elicit_extend.md +0 -0
  320. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_android_material3/lexicon.yaml +0 -0
  321. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_android_material3/manifest.yaml +0 -0
  322. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_android_material3/recommended_kinds.yaml +0 -0
  323. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_android_material3/severity_rules.yaml +0 -0
  324. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_ios_hig/coverage_matrix.md +0 -0
  325. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_ios_hig/elicit_extend.md +0 -0
  326. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_ios_hig/lexicon.yaml +0 -0
  327. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_ios_hig/manifest.yaml +0 -0
  328. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_ios_hig/recommended_kinds.yaml +0 -0
  329. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/mobile_ios_hig/severity_rules.yaml +0 -0
  330. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_cicd_pipeline/coverage_matrix.md +0 -0
  331. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_cicd_pipeline/elicit_extend.md +0 -0
  332. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_cicd_pipeline/lexicon.yaml +0 -0
  333. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_cicd_pipeline/manifest.yaml +0 -0
  334. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_cicd_pipeline/recommended_kinds.yaml +0 -0
  335. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_cicd_pipeline/severity_rules.yaml +0 -0
  336. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_iac_terraform/coverage_matrix.md +0 -0
  337. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_iac_terraform/elicit_extend.md +0 -0
  338. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_iac_terraform/lexicon.yaml +0 -0
  339. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_iac_terraform/manifest.yaml +0 -0
  340. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_iac_terraform/recommended_kinds.yaml +0 -0
  341. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_iac_terraform/severity_rules.yaml +0 -0
  342. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_kubernetes/coverage_matrix.md +0 -0
  343. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_kubernetes/elicit_extend.md +0 -0
  344. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_kubernetes/lexicon.yaml +0 -0
  345. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_kubernetes/manifest.yaml +0 -0
  346. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_kubernetes/recommended_kinds.yaml +0 -0
  347. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_kubernetes/severity_rules.yaml +0 -0
  348. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_observability_otel/coverage_matrix.md +0 -0
  349. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_observability_otel/elicit_extend.md +0 -0
  350. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_observability_otel/lexicon.yaml +0 -0
  351. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_observability_otel/manifest.yaml +0 -0
  352. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_observability_otel/recommended_kinds.yaml +0 -0
  353. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/ops_observability_otel/severity_rules.yaml +0 -0
  354. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_iso25010/coverage_matrix.md +0 -0
  355. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_iso25010/elicit_extend.md +0 -0
  356. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_iso25010/lexicon.yaml +0 -0
  357. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_iso25010/manifest.yaml +0 -0
  358. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_iso25010/recommended_kinds.yaml +0 -0
  359. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_iso25010/severity_rules.yaml +0 -0
  360. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_test_iso29119/coverage_matrix.md +0 -0
  361. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_test_iso29119/elicit_extend.md +0 -0
  362. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_test_iso29119/lexicon.yaml +0 -0
  363. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_test_iso29119/manifest.yaml +0 -0
  364. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_test_iso29119/recommended_kinds.yaml +0 -0
  365. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/process_test_iso29119/severity_rules.yaml +0 -0
  366. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/coverage_matrix.md +0 -0
  367. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/elicit_extend.md +0 -0
  368. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/lexicon.yaml +0 -0
  369. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/manifest.yaml +0 -0
  370. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/recommended_kinds.yaml +0 -0
  371. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/severity_rules.yaml +0 -0
  372. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_authn_webauthn/coverage_matrix.md +0 -0
  373. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_authn_webauthn/elicit_extend.md +0 -0
  374. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_authn_webauthn/lexicon.yaml +0 -0
  375. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_authn_webauthn/manifest.yaml +0 -0
  376. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_authn_webauthn/recommended_kinds.yaml +0 -0
  377. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_authn_webauthn/severity_rules.yaml +0 -0
  378. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_browser_compat/coverage_matrix.md +0 -0
  379. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_browser_compat/elicit_extend.md +0 -0
  380. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_browser_compat/lexicon.yaml +0 -0
  381. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_browser_compat/manifest.yaml +0 -0
  382. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_browser_compat/recommended_kinds.yaml +0 -0
  383. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_browser_compat/severity_rules.yaml +0 -0
  384. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_forms_html5/coverage_matrix.md +0 -0
  385. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_forms_html5/elicit_extend.md +0 -0
  386. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_forms_html5/lexicon.yaml +0 -0
  387. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_forms_html5/manifest.yaml +0 -0
  388. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_forms_html5/recommended_kinds.yaml +0 -0
  389. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_forms_html5/severity_rules.yaml +0 -0
  390. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_performance_core_web_vitals/coverage_matrix.md +0 -0
  391. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_performance_core_web_vitals/elicit_extend.md +0 -0
  392. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_performance_core_web_vitals/lexicon.yaml +0 -0
  393. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_performance_core_web_vitals/manifest.yaml +0 -0
  394. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_performance_core_web_vitals/recommended_kinds.yaml +0 -0
  395. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_performance_core_web_vitals/severity_rules.yaml +0 -0
  396. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_pwa_manifest/coverage_matrix.md +0 -0
  397. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_pwa_manifest/elicit_extend.md +0 -0
  398. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_pwa_manifest/lexicon.yaml +0 -0
  399. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_pwa_manifest/manifest.yaml +0 -0
  400. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_pwa_manifest/recommended_kinds.yaml +0 -0
  401. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_pwa_manifest/severity_rules.yaml +0 -0
  402. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_responsive/coverage_matrix.md +0 -0
  403. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_responsive/elicit_extend.md +0 -0
  404. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_responsive/lexicon.yaml +0 -0
  405. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_responsive/manifest.yaml +0 -0
  406. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_responsive/recommended_kinds.yaml +0 -0
  407. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_responsive/severity_rules.yaml +0 -0
  408. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_security_owasp/coverage_matrix.md +0 -0
  409. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_security_owasp/elicit_extend.md +0 -0
  410. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_security_owasp/lexicon.yaml +0 -0
  411. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_security_owasp/manifest.yaml +0 -0
  412. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_security_owasp/recommended_kinds.yaml +0 -0
  413. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_security_owasp/severity_rules.yaml +0 -0
  414. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_seo_schemaorg/coverage_matrix.md +0 -0
  415. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_seo_schemaorg/elicit_extend.md +0 -0
  416. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_seo_schemaorg/lexicon.yaml +0 -0
  417. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_seo_schemaorg/manifest.yaml +0 -0
  418. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_seo_schemaorg/recommended_kinds.yaml +0 -0
  419. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/lexicons/web_seo_schemaorg/severity_rules.yaml +0 -0
  420. {codd_dev-2.1.0 → codd_dev-2.3.0}/codd_plugins/stack_map.yaml +0 -0
  421. {codd_dev-2.1.0 → codd_dev-2.3.0}/docs/cookbook/cdp_browser/README.md +0 -0
  422. {codd_dev-2.1.0 → codd_dev-2.3.0}/docs/requirements/README.md +0 -0
  423. {codd_dev-2.1.0 → codd_dev-2.3.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.1.0
3
+ Version: 2.3.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
@@ -610,6 +610,29 @@ def _add_deployment_graph(
610
610
  )
611
611
  verification_tests = extract_verification_tests(project_root, project_config, design_docs)
612
612
 
613
+ from codd.deployment.extractor import discover_deployment_impl_candidates
614
+
615
+ capability_patterns = _capability_patterns(project_config)
616
+ for impl_path in discover_deployment_impl_candidates(project_root, deployment_docs):
617
+ rel_id = impl_path.relative_to(project_root).as_posix()
618
+ if rel_id in dag.nodes:
619
+ continue
620
+ _add_node_once(
621
+ dag,
622
+ Node(
623
+ id=rel_id,
624
+ kind="impl_file",
625
+ path=rel_id,
626
+ attributes={
627
+ "language": _language_for_path(impl_path),
628
+ "imports": [],
629
+ "runtime_evidence": _runtime_evidence_for_file(impl_path, rel_id, capability_patterns),
630
+ "auto_registered_for_deployment": True,
631
+ },
632
+ ),
633
+ )
634
+ impl_nodes[rel_id] = impl_path.resolve()
635
+
613
636
  for deployment_doc in deployment_docs:
614
637
  _add_node_once(
615
638
  dag,
@@ -31,6 +31,17 @@ SMOKE_TEST_PATTERNS = ("tests/smoke/*.test.ts", "tests/smoke/*.spec.ts", "tests/
31
31
  E2E_TEST_PATTERNS = ("tests/e2e/*.spec.ts", "tests/e2e/*.test.ts")
32
32
  RUNTIME_CAPABILITY_INFERENCE_DEFAULTS = Path(__file__).parent / "defaults" / "runtime_capability_inference.yaml"
33
33
 
34
+ DEPLOYMENT_SECTION_IMPL_PATTERNS: dict[str, tuple[str, ...]] = {
35
+ "migrate": ("prisma/migrations/**/*", "schema.prisma", "**/migrations/**/*.sql"),
36
+ "seed": ("prisma/seed.ts", "prisma/seed.js", "scripts/seed.ts", "scripts/seed.js"),
37
+ "build": ("Dockerfile", "Containerfile", "package.json"),
38
+ "start": (
39
+ "main.ts", "main.js", "server.ts", "server.js",
40
+ "app.ts", "app.js", "index.ts", "index.js",
41
+ "src/main.ts", "src/main.js", "src/server.ts", "src/server.js",
42
+ ),
43
+ }
44
+
34
45
 
35
46
  def extract_deployment_nodes(project_root: Path, codd_config: dict[str, Any] | None = None) -> dict[str, list]:
36
47
  """Extract deployment document, runtime state, and verification test nodes."""
@@ -181,6 +192,37 @@ def extract_verification_tests(
181
192
  return [tests[key] for key in sorted(tests)]
182
193
 
183
194
 
195
+ def discover_deployment_impl_candidates(
196
+ project_root: Path,
197
+ deployment_docs: list[DeploymentDocNode],
198
+ ) -> list[Path]:
199
+ """Return existing standard impl artifacts referenced by deployment doc sections.
200
+
201
+ Walks each deployment document's sections and matches keywords against
202
+ DEPLOYMENT_SECTION_IMPL_PATTERNS, then keeps the patterns that resolve to a
203
+ real file under ``project_root``. The mapping itself stays inside the
204
+ deployment plug-in so DAG core code can remain free of stack-specific
205
+ filenames; this helper just runs an existence check.
206
+ """
207
+
208
+ root = Path(project_root)
209
+ seen: dict[str, Path] = {}
210
+ for doc in deployment_docs:
211
+ for section in doc.sections or []:
212
+ normalized = str(section).lower()
213
+ for keyword, patterns in DEPLOYMENT_SECTION_IMPL_PATTERNS.items():
214
+ if keyword not in normalized:
215
+ continue
216
+ for pattern in patterns:
217
+ for path in root.glob(pattern):
218
+ if not path.is_file():
219
+ continue
220
+ rel = path.relative_to(root).as_posix()
221
+ if rel not in seen:
222
+ seen[rel] = path
223
+ return list(seen.values())
224
+
225
+
184
226
  def infer_deployment_edges(
185
227
  project_root: Path,
186
228
  deployment_docs: list[DeploymentDocNode],
@@ -35,6 +35,7 @@ class ElicitApplyEngine:
35
35
  pending_path = self.elicit_dir / "pending_findings.yaml"
36
36
  history_path = self.elicit_dir / "elicit_history.yaml"
37
37
  findings_md_path = self.project_root / "findings.md"
38
+ requirements_path = _requirements_path(self.project_root)
38
39
 
39
40
  ignored_doc = _read_yaml_mapping(ignored_path, default_key="ignored")
40
41
  pending_doc = _read_yaml_mapping(pending_path, default_key="pending")
@@ -44,8 +45,12 @@ class ElicitApplyEngine:
44
45
  pending_entries = _list_value(pending_doc, "pending")
45
46
  history_entries = _list_value(history_doc, "sessions")
46
47
 
47
- existing_ids = _existing_finding_ids(ignored_entries) | _existing_finding_ids(pending_entries)
48
- accepted: list[Finding] = []
48
+ ignored_ids = _existing_finding_ids(ignored_entries)
49
+ pending_ids = _existing_finding_ids(pending_entries)
50
+ requirements_ids = _existing_ids_in_file(requirements_path)
51
+ accepted_for_requirements: list[Finding] = []
52
+ accepted_for_review: list[Finding] = []
53
+ pending_review: list[Finding] = []
49
54
  rejected: list[Finding] = []
50
55
  deferred: list[Finding] = []
51
56
  duplicates: list[Finding] = []
@@ -53,31 +58,60 @@ class ElicitApplyEngine:
53
58
  for finding in approved:
54
59
  decision = _finding_decision(finding)
55
60
  if decision == "reject":
61
+ _remove_finding_entry(pending_entries, finding.id)
62
+ pending_ids.discard(finding.id)
63
+ if finding.id in ignored_ids:
64
+ duplicates.append(finding)
65
+ continue
56
66
  rejected.append(finding)
67
+ ignored_ids.add(finding.id)
57
68
  continue
58
69
  if decision == "defer":
59
70
  deferred.append(finding)
60
71
  continue
61
- if finding.id in existing_ids:
72
+ if decision == "pending":
73
+ if finding.id in ignored_ids or finding.id in requirements_ids:
74
+ duplicates.append(finding)
75
+ continue
76
+ if finding.id in pending_ids:
77
+ duplicates.append(finding)
78
+ continue
79
+ pending_review.append(finding)
80
+ pending_ids.add(finding.id)
81
+ continue
82
+ if _writes_requirements(finding):
83
+ if finding.id in ignored_ids or finding.id in requirements_ids:
84
+ duplicates.append(finding)
85
+ continue
86
+ _remove_finding_entry(pending_entries, finding.id)
87
+ pending_ids.discard(finding.id)
88
+ accepted_for_requirements.append(finding)
89
+ requirements_ids.add(finding.id)
90
+ continue
91
+ if finding.id in ignored_ids or finding.id in pending_ids or finding.id in requirements_ids:
62
92
  duplicates.append(finding)
63
93
  continue
64
- accepted.append(finding)
65
- existing_ids.add(finding.id)
94
+ accepted_for_review.append(finding)
95
+ pending_ids.add(finding.id)
66
96
 
67
97
  for finding in rejected:
68
98
  ignored_entries.append(_ignored_entry(finding, timestamp))
69
- for finding in accepted:
99
+ for finding in [*accepted_for_review, *pending_review]:
70
100
  pending_entries.append(_pending_entry(finding, timestamp))
71
101
 
72
102
  history_entries.append(
73
103
  {
74
104
  "timestamp": timestamp,
75
105
  "findings_total": len(approved),
76
- "approved": len(accepted),
106
+ "approved": len(accepted_for_requirements) + len(accepted_for_review),
77
107
  "rejected": len(rejected),
78
108
  "deferred": len(deferred),
109
+ "pending": len(pending_review),
79
110
  "duplicates": len(duplicates),
80
- "findings_md": "findings.md" if accepted else None,
111
+ "findings_md": "findings.md" if accepted_for_review else None,
112
+ "requirements_md": _relative_path(requirements_path, self.project_root)
113
+ if accepted_for_requirements
114
+ else None,
81
115
  }
82
116
  )
83
117
 
@@ -89,12 +123,16 @@ class ElicitApplyEngine:
89
123
  _write_yaml(history_path, {"sessions": history_entries})
90
124
  files_updated.append(_relative_path(history_path, self.project_root))
91
125
 
92
- if accepted:
93
- findings_md_path.write_text(MdFormatter().format(accepted), encoding="utf-8")
126
+ if accepted_for_requirements:
127
+ _append_requirements(requirements_path, accepted_for_requirements)
128
+ files_updated.append(_relative_path(requirements_path, self.project_root))
129
+
130
+ if accepted_for_review:
131
+ findings_md_path.write_text(MdFormatter().format(accepted_for_review), encoding="utf-8")
94
132
  files_updated.append(_relative_path(findings_md_path, self.project_root))
95
133
 
96
134
  return ApplyResult(
97
- applied_count=len(accepted),
135
+ applied_count=len(accepted_for_requirements) + len(accepted_for_review) + len(pending_review),
98
136
  skipped_count=len(rejected) + len(deferred) + len(duplicates),
99
137
  files_updated=files_updated,
100
138
  )
@@ -128,17 +166,22 @@ def _findings_from_json(raw: str) -> list[Finding]:
128
166
 
129
167
 
130
168
  _FINDING_COMMENT_RE = re.compile(r"<!--\s*codd:finding\s*(.*?)\s*-->", re.DOTALL)
169
+ _APPROVAL_LINE_RE = re.compile(
170
+ r"(?m)^-\s+approval:\s*\[([^\]]*)\]\s*`?([A-Za-z0-9][A-Za-z0-9_.:-]*)`?"
171
+ )
131
172
 
132
173
 
133
174
  def _findings_from_markdown(raw: str) -> list[Finding]:
134
175
  findings = [Finding.from_dict(json.loads(match.group(1))) for match in _FINDING_COMMENT_RE.finditer(raw)]
135
176
  if findings:
136
- return findings
177
+ approval_states = _approval_states_from_markdown(raw)
178
+ return [_with_approval_state(finding, approval_states.get(finding.id)) for finding in findings]
137
179
  return _findings_from_markdown_fields(raw)
138
180
 
139
181
 
140
182
  def _findings_from_markdown_fields(raw: str) -> list[Finding]:
141
183
  findings: list[Finding] = []
184
+ approval_states = _approval_states_from_markdown(raw)
142
185
  for section in re.split(r"(?m)^##\s+", raw)[1:]:
143
186
  fields: dict[str, Any] = {}
144
187
  for key in ("id", "kind", "severity", "name", "question", "rationale"):
@@ -148,10 +191,36 @@ def _findings_from_markdown_fields(raw: str) -> list[Finding]:
148
191
  if value != "N/A":
149
192
  fields[key] = value
150
193
  if fields:
151
- findings.append(Finding.from_dict(fields))
194
+ finding = Finding.from_dict(fields)
195
+ findings.append(_with_approval_state(finding, approval_states.get(finding.id)))
152
196
  return findings
153
197
 
154
198
 
199
+ def _approval_states_from_markdown(raw: str) -> dict[str, str]:
200
+ states: dict[str, str] = {}
201
+ for match in _APPROVAL_LINE_RE.finditer(raw):
202
+ state = match.group(1).strip().lower()
203
+ finding_id = match.group(2).strip().strip("`")
204
+ if state:
205
+ states[finding_id] = state
206
+ return states
207
+
208
+
209
+ def _with_approval_state(finding: Finding, state: str | None) -> Finding:
210
+ if state is None:
211
+ return finding
212
+ details = dict(finding.details)
213
+ if state in {"x", "y", "yes", "approve", "approved"}:
214
+ details["approval"] = "approved"
215
+ elif state in {"r", "n", "no", "reject", "rejected"}:
216
+ details["approval"] = "rejected"
217
+ else:
218
+ details["approval"] = f"unknown:{state}"
219
+ payload = finding.to_dict()
220
+ payload["details"] = details
221
+ return Finding.from_dict(payload)
222
+
223
+
155
224
  def _utc_timestamp() -> str:
156
225
  return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
157
226
 
@@ -197,16 +266,93 @@ def _existing_finding_ids(entries: list[Any]) -> set[str]:
197
266
  return ids
198
267
 
199
268
 
269
+ def _remove_finding_entry(entries: list[Any], finding_id: str) -> None:
270
+ entries[:] = [
271
+ entry
272
+ for entry in entries
273
+ if _entry_finding_id(entry) != finding_id
274
+ ]
275
+
276
+
277
+ def _entry_finding_id(entry: Any) -> str | None:
278
+ if not isinstance(entry, dict):
279
+ return None
280
+ if "id" in entry:
281
+ return str(entry["id"])
282
+ finding = entry.get("finding")
283
+ if isinstance(finding, dict) and "id" in finding:
284
+ return str(finding["id"])
285
+ return None
286
+
287
+
200
288
  def _finding_decision(finding: Finding) -> str:
201
289
  raw = finding.details.get("decision", finding.details.get("approval", "approve"))
202
290
  value = str(raw).strip().lower()
203
- if value in {"reject", "rejected", "no", "n"}:
291
+ if value.startswith("unknown:"):
292
+ return "pending"
293
+ if value in {"reject", "rejected", "no", "n", "r"}:
204
294
  return "reject"
205
- if value in {"defer", "deferred", "later", "pending", "d"}:
295
+ if value in {"pending", "unchecked", "unreviewed"}:
296
+ return "pending"
297
+ if value in {"defer", "deferred", "later", "d"}:
206
298
  return "defer"
207
299
  return "approve"
208
300
 
209
301
 
302
+ def _writes_requirements(finding: Finding) -> bool:
303
+ raw = finding.details.get("decision", finding.details.get("approval"))
304
+ if raw is None:
305
+ return False
306
+ return str(raw).strip().lower() in {"approve", "approved", "yes", "y", "x"}
307
+
308
+
309
+ def _requirements_path(project_root: Path) -> Path:
310
+ candidates = [
311
+ project_root / "requirements.md",
312
+ project_root / "docs" / "requirements" / "requirements.md",
313
+ project_root / "docs" / "requirements.md",
314
+ project_root / ".codd" / "requirements.md",
315
+ ]
316
+ for candidate in candidates:
317
+ if candidate.exists():
318
+ return candidate
319
+ return candidates[0]
320
+
321
+
322
+ def _existing_ids_in_file(path: Path) -> set[str]:
323
+ if not path.exists():
324
+ return set()
325
+ text = path.read_text(encoding="utf-8", errors="replace")
326
+ return set(re.findall(r"\[([A-Za-z0-9][A-Za-z0-9_.:-]*)\]", text))
327
+
328
+
329
+ def _append_requirements(path: Path, findings: list[Finding]) -> None:
330
+ path.parent.mkdir(parents=True, exist_ok=True)
331
+ existing = path.read_text(encoding="utf-8") if path.exists() else ""
332
+ entries = "\n\n".join(_requirements_entry(finding) for finding in findings)
333
+ parts = [existing.rstrip()]
334
+ heading = "## TODO (codd elicit approved findings)"
335
+ if heading not in existing:
336
+ parts.extend(["", heading])
337
+ parts.extend(["", entries])
338
+ path.write_text("\n".join(part for part in parts if part != "").rstrip() + "\n", encoding="utf-8")
339
+
340
+
341
+ def _requirements_entry(finding: Finding) -> str:
342
+ lines = [f"- [ ] TODO [{finding.id}] {_summary(finding)}"]
343
+ if finding.question:
344
+ lines.append(f" - Question: {finding.question}")
345
+ if finding.rationale:
346
+ lines.append(f" - Rationale: {finding.rationale}")
347
+ if finding.related_requirement_ids:
348
+ lines.append(f" - Related requirements: {', '.join(finding.related_requirement_ids)}")
349
+ return "\n".join(lines)
350
+
351
+
352
+ def _summary(finding: Finding) -> str:
353
+ return finding.name or finding.question or finding.rationale or finding.id
354
+
355
+
210
356
  def _ignored_entry(finding: Finding, timestamp: str) -> dict[str, Any]:
211
357
  return {
212
358
  "id": finding.id,
@@ -35,9 +35,16 @@ class ElicitEngine:
35
35
 
36
36
  def run(self, project_root: Path, lexicon_config: Any | None = None) -> ElicitResult:
37
37
  root = Path(project_root)
38
+ project_scope, project_phase = _project_scope_phase(root)
38
39
  prompt = self.build_prompt(root, lexicon_config=lexicon_config)
39
40
  raw_output = self.invoke(prompt, root)
40
41
  result = self.deserialize_result(raw_output)
42
+ result.findings = _apply_scope_phase(
43
+ result.findings,
44
+ lexicon_config=lexicon_config,
45
+ scope=project_scope,
46
+ phase=project_phase,
47
+ )
41
48
  result.findings = ElicitPersistence(root).filter_known(result.findings)
42
49
  if not result.findings and result.lexicon_coverage_report:
43
50
  non_gap = all(
@@ -173,6 +180,151 @@ def _existing_axes_text(project_root: Path) -> str:
173
180
  return yaml.safe_dump(values, sort_keys=False, allow_unicode=True).strip()
174
181
 
175
182
 
183
+ def _project_scope_phase(project_root: Path) -> tuple[str, str]:
184
+ for name in ("project_lexicon.yaml", "project_lexicon.yml"):
185
+ path = project_root / name
186
+ if not path.is_file():
187
+ continue
188
+ payload = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
189
+ if not isinstance(payload, Mapping):
190
+ return "full", "production"
191
+ return (
192
+ str(payload.get("scope") or "full"),
193
+ str(payload.get("phase") or "production"),
194
+ )
195
+ return "full", "production"
196
+
197
+
198
+ def _apply_scope_phase(
199
+ findings: list[Finding],
200
+ *,
201
+ lexicon_config: Any | None,
202
+ scope: str,
203
+ phase: str,
204
+ ) -> list[Finding]:
205
+ axis_concerns = _axis_concern_map(lexicon_config)
206
+ severity_rules = _mapping_attr(lexicon_config, "severity_rules")
207
+ filtered: list[Finding] = []
208
+ for finding in findings:
209
+ axis = _finding_axis(finding)
210
+ concern = axis_concerns.get(axis) if axis is not None else None
211
+ if not _scope_allows_concern(scope, concern):
212
+ continue
213
+ _apply_phase_severity(
214
+ finding,
215
+ axis=axis,
216
+ concern=concern,
217
+ phase=phase,
218
+ scope=scope,
219
+ severity_rules=severity_rules,
220
+ )
221
+ filtered.append(finding)
222
+ return filtered
223
+
224
+
225
+ def _axis_concern_map(lexicon_config: Any | None) -> dict[str, str]:
226
+ concerns: dict[str, str] = {}
227
+ for axis in _list_attr(lexicon_config, "coverage_axes"):
228
+ if not isinstance(axis, Mapping):
229
+ continue
230
+ axis_type = axis.get("axis_type")
231
+ concern = axis.get("concern")
232
+ if isinstance(axis_type, str) and isinstance(concern, str):
233
+ concerns[axis_type] = concern.strip().lower()
234
+ return concerns
235
+
236
+
237
+ def _finding_axis(finding: Finding) -> str | None:
238
+ for key in ("dimension", "axis", "axis_type"):
239
+ value = finding.details.get(key)
240
+ if isinstance(value, str) and value.strip():
241
+ return value.strip()
242
+ return None
243
+
244
+
245
+ def _scope_allows_concern(scope: str, concern: str | None) -> bool:
246
+ if concern is None:
247
+ return True
248
+ scope_value = scope.strip().lower()
249
+ concern_value = concern.strip().lower()
250
+ if scope_value == "system_implementation":
251
+ return concern_value in {"system", "both"}
252
+ if scope_value == "business_only":
253
+ return concern_value in {"business", "both"}
254
+ return True
255
+
256
+
257
+ def _apply_phase_severity(
258
+ finding: Finding,
259
+ *,
260
+ axis: str | None,
261
+ concern: str | None,
262
+ phase: str,
263
+ scope: str,
264
+ severity_rules: Mapping[str, Any],
265
+ ) -> None:
266
+ phase_value = phase.strip().lower()
267
+ concern_value = (concern or "").strip().lower()
268
+ context = {
269
+ "axis": axis or "",
270
+ "dimension": axis or "",
271
+ "concern": concern_value,
272
+ "phase": phase_value,
273
+ "scope": scope.strip().lower(),
274
+ "severity": finding.severity,
275
+ }
276
+ if _apply_matching_severity_rule(finding, context, severity_rules):
277
+ return
278
+ if phase_value == "mvp" and concern_value == "business" and finding.severity != "info":
279
+ finding.severity = "info"
280
+
281
+
282
+ def _apply_matching_severity_rule(
283
+ finding: Finding,
284
+ context: Mapping[str, str],
285
+ severity_rules: Mapping[str, Any],
286
+ ) -> bool:
287
+ rules = severity_rules.get("rules", [])
288
+ if not isinstance(rules, list):
289
+ return False
290
+ for rule in rules:
291
+ if not isinstance(rule, Mapping):
292
+ continue
293
+ when = rule.get("when")
294
+ severity = rule.get("severity")
295
+ if not isinstance(when, str) or not isinstance(severity, str):
296
+ continue
297
+ if _condition_matches(when, context):
298
+ _set_severity(finding, severity)
299
+ return True
300
+ return False
301
+
302
+
303
+ def _condition_matches(condition: str, context: Mapping[str, str]) -> bool:
304
+ parts = [
305
+ part.strip()
306
+ for part in re.split(r"\bAND\b", condition, flags=re.IGNORECASE)
307
+ if part.strip()
308
+ ]
309
+ if not parts:
310
+ return False
311
+ for part in parts:
312
+ if "=" not in part:
313
+ return False
314
+ key_text, expected_text = part.split("=", 1)
315
+ key = key_text.strip().lower()
316
+ expected = expected_text.strip().lower()
317
+ if context.get(key, "").lower() != expected:
318
+ return False
319
+ return True
320
+
321
+
322
+ def _set_severity(finding: Finding, severity: str) -> None:
323
+ cleaned = severity.strip().lower()
324
+ if cleaned in {"critical", "high", "medium", "info"}:
325
+ finding.severity = cleaned # type: ignore[assignment]
326
+
327
+
176
328
  def _load_optional_codd_config(project_root: Path) -> dict[str, Any]:
177
329
  for dirname in ("codd", ".codd"):
178
330
  path = project_root / dirname / "codd.yaml"
@@ -237,6 +389,28 @@ def _string_attr(value: Any, name: str) -> str | None:
237
389
  return None
238
390
 
239
391
 
392
+ def _mapping_attr(value: Any, name: str) -> Mapping[str, Any]:
393
+ candidate = getattr(value, name, None)
394
+ if isinstance(candidate, Mapping):
395
+ return candidate
396
+ if isinstance(value, Mapping):
397
+ candidate = value.get(name)
398
+ if isinstance(candidate, Mapping):
399
+ return candidate
400
+ return {}
401
+
402
+
403
+ def _list_attr(value: Any, name: str) -> list[Any]:
404
+ candidate = getattr(value, name, None)
405
+ if isinstance(candidate, list):
406
+ return candidate
407
+ if isinstance(value, Mapping):
408
+ candidate = value.get(name)
409
+ if isinstance(candidate, list):
410
+ return candidate
411
+ return []
412
+
413
+
240
414
  def _unique_paths(paths: list[Path]) -> list[Path]:
241
415
  seen: set[Path] = set()
242
416
  unique: list[Path] = []
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from dataclasses import dataclass
5
+ from dataclasses import dataclass, field
6
6
  from pathlib import Path
7
7
  from typing import Any
8
8
 
@@ -18,6 +18,8 @@ class LexiconConfig:
18
18
  lexicon_name: str
19
19
  prompt_extension_content: str
20
20
  recommended_kinds: list[str]
21
+ coverage_axes: list[dict[str, Any]] = field(default_factory=list)
22
+ severity_rules: dict[str, Any] = field(default_factory=dict)
21
23
 
22
24
 
23
25
  def load_lexicon(lexicon_path: Path) -> LexiconConfig:
@@ -54,10 +56,18 @@ def load_lexicon(lexicon_path: Path) -> LexiconConfig:
54
56
  prompt_content = f"{base_prompt.rstrip()}\n\n{extension_body.lstrip()}"
55
57
 
56
58
  recommended_kinds = _load_recommended_kinds(recommended_kinds_path)
59
+ coverage_axes = _load_coverage_axes(manifest_dir, manifest)
60
+ severity_rules = _load_optional_mapping_file(
61
+ manifest_dir,
62
+ _optional_str(manifest.get("severity_rules")) or "severity_rules.yaml",
63
+ "severity_rules",
64
+ )
57
65
  return LexiconConfig(
58
66
  lexicon_name=lexicon_name,
59
67
  prompt_extension_content=prompt_content,
60
68
  recommended_kinds=recommended_kinds,
69
+ coverage_axes=coverage_axes,
70
+ severity_rules=severity_rules,
61
71
  )
62
72
 
63
73
 
@@ -154,3 +164,20 @@ def _load_recommended_kinds(path: Path) -> list[str]:
154
164
  raise LexiconLoadError(f"recommended_kinds contains duplicate entry: {kind}")
155
165
  kinds.append(kind)
156
166
  return kinds
167
+
168
+
169
+ def _load_coverage_axes(base_dir: Path, manifest: dict[str, Any]) -> list[dict[str, Any]]:
170
+ lexicon_path_text = _optional_str(manifest.get("lexicon")) or "lexicon.yaml"
171
+ payload = _load_optional_mapping_file(base_dir, lexicon_path_text, "lexicon")
172
+ raw_axes = payload.get("coverage_axes", manifest.get("coverage_axes", []))
173
+ if not isinstance(raw_axes, list):
174
+ return []
175
+ return [dict(item) for item in raw_axes if isinstance(item, dict)]
176
+
177
+
178
+ def _load_optional_mapping_file(base_dir: Path, declared_path: str, label: str) -> dict[str, Any]:
179
+ try:
180
+ path = _resolve_existing_path(base_dir, declared_path, label)
181
+ except LexiconLoadError:
182
+ return {}
183
+ return _load_yaml_mapping(path, label)
@@ -13,6 +13,8 @@ import yaml
13
13
  SCHEMA_PATH = Path(__file__).parent / "templates" / "lexicon_schema.yaml"
14
14
  LEXICON_FILENAME = "project_lexicon.yaml"
15
15
  REQUIRED_ARTIFACT_SOURCES = {"ai_derived", "user_override", "default_template"}
16
+ DEFAULT_SCOPE = "full"
17
+ DEFAULT_PHASE = "production"
16
18
 
17
19
 
18
20
  @dataclass
@@ -92,6 +94,14 @@ class ProjectLexicon:
92
94
  def required_artifacts(self) -> list[dict[str, Any]]:
93
95
  return deepcopy(self._data.get("required_artifacts", []))
94
96
 
97
+ @property
98
+ def scope(self) -> str:
99
+ return str(self._data.get("scope") or DEFAULT_SCOPE)
100
+
101
+ @property
102
+ def phase(self) -> str:
103
+ return str(self._data.get("phase") or DEFAULT_PHASE)
104
+
95
105
  def set_coverage_decisions(self, decisions: list[AskItem]) -> None:
96
106
  self._data["coverage_decisions"] = [
97
107
  ask_item_to_dict(item)
@@ -293,6 +303,10 @@ def validate_lexicon(data: dict[str, Any]) -> None:
293
303
  if derived_from is not None and not isinstance(derived_from, list):
294
304
  raise LexiconError(f"required_artifacts derived_from must be a list: {artifact}")
295
305
 
306
+ for field_name in ("scope", "phase"):
307
+ if field_name in data and not isinstance(data[field_name], str):
308
+ raise LexiconError(f"{field_name} must be a string")
309
+
296
310
 
297
311
  def _load_schema() -> dict[str, Any]:
298
312
  data = yaml.safe_load(SCHEMA_PATH.read_text(encoding="utf-8"))
@@ -67,6 +67,6 @@ Constraints:
67
67
  ## Prisma Enums
68
68
 
69
69
  {% for enum in prisma_enums -%}
70
- - `{{ enum.name }}`: {{ enum.values | join(", ") }}
70
+ - `{{ enum.name }}`: {{ enum["values"] | join(", ") }}
71
71
  {% endfor %}
72
72
  {% endif %}
@@ -10,6 +10,8 @@ optional_sections:
10
10
  - extractor_registry
11
11
  - coverage_decisions
12
12
  - required_artifacts
13
+ - scope
14
+ - phase
13
15
 
14
16
  required_artifact_source_values:
15
17
  - ai_derived