codd-dev 2.4.0__tar.gz → 2.6.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.4.0 → codd_dev-2.6.0}/PKG-INFO +1 -1
  2. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/cli.py +14 -2
  3. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/engine.py +121 -10
  4. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/init/lexicon_suggest.py +9 -22
  5. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/lexicon.py +95 -1
  6. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/lexicon_cli/manager.py +5 -12
  7. {codd_dev-2.4.0 → codd_dev-2.6.0}/pyproject.toml +1 -1
  8. {codd_dev-2.4.0 → codd_dev-2.6.0}/.gitignore +0 -0
  9. {codd_dev-2.4.0 → codd_dev-2.6.0}/LICENSE +0 -0
  10. {codd_dev-2.4.0 → codd_dev-2.6.0}/README.md +0 -0
  11. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/__init__.py +0 -0
  12. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/__main__.py +0 -0
  13. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/_git_helper.py +0 -0
  14. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/ask_user_question_adapter.py +0 -0
  15. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/assembler.py +0 -0
  16. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/bridge.py +0 -0
  17. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/brownfield/__init__.py +0 -0
  18. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/brownfield/pipeline.py +0 -0
  19. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/clustering.py +0 -0
  20. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/coherence_adapters.py +0 -0
  21. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/coherence_engine.py +0 -0
  22. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/config.py +0 -0
  23. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/contracts.py +0 -0
  24. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/coverage_auditor.py +0 -0
  25. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/coverage_metrics.py +0 -0
  26. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/__init__.py +0 -0
  27. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/builder.py +0 -0
  28. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/checks/__init__.py +0 -0
  29. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/checks/depends_on_consistency.py +0 -0
  30. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/checks/deployment_completeness.py +0 -0
  31. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/checks/edge_validity.py +0 -0
  32. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/checks/environment_coverage.py +0 -0
  33. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/checks/implementation_coverage.py +0 -0
  34. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/checks/node_completeness.py +0 -0
  35. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/checks/task_completion.py +0 -0
  36. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/checks/transitive_closure.py +0 -0
  37. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/checks/user_journey_coherence.py +0 -0
  38. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/coverage_axes.py +0 -0
  39. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/cli.yaml +0 -0
  40. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/cpp_embedded.yaml +0 -0
  41. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/csharp.yaml +0 -0
  42. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/elixir.yaml +0 -0
  43. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/generic.yaml +0 -0
  44. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/iot.yaml +0 -0
  45. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/java.yaml +0 -0
  46. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/kotlin.yaml +0 -0
  47. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/mobile.yaml +0 -0
  48. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/ruby.yaml +0 -0
  49. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/rust.yaml +0 -0
  50. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/scala.yaml +0 -0
  51. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/swift.yaml +0 -0
  52. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/test_frameworks.yaml +0 -0
  53. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/defaults/web.yaml +0 -0
  54. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/extractor.py +0 -0
  55. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/dag/runner.py +0 -0
  56. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/defaults.yaml +0 -0
  57. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deploy_targets/__init__.py +0 -0
  58. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deploy_targets/app_service.py +0 -0
  59. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deploy_targets/base.py +0 -0
  60. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deploy_targets/docker_compose.py +0 -0
  61. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployer.py +0 -0
  62. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/__init__.py +0 -0
  63. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/checks/__init__.py +0 -0
  64. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/defaults/deploy_targets.yaml +0 -0
  65. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/defaults/runtime_capability_inference.yaml +0 -0
  66. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/defaults/schema_providers.yaml +0 -0
  67. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/defaults/verification_templates.yaml +0 -0
  68. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/extractor.py +0 -0
  69. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/__init__.py +0 -0
  70. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/ai_command.py +0 -0
  71. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/llm_consideration.py +0 -0
  72. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/schema/__init__.py +0 -0
  73. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/schema/prisma.py +0 -0
  74. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/target/__init__.py +0 -0
  75. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/target/docker_compose.py +0 -0
  76. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/verification/__init__.py +0 -0
  77. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/verification/assertion_handlers.py +0 -0
  78. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/verification/cdp_browser.py +0 -0
  79. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/verification/cdp_engines.py +0 -0
  80. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/verification/cdp_launchers.py +0 -0
  81. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/verification/cdp_wire.py +0 -0
  82. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/verification/curl.py +0 -0
  83. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/verification/form_strategies.py +0 -0
  84. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/verification/means_catalog.py +0 -0
  85. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/deployment/providers/verification/playwright.py +0 -0
  86. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/design_md.py +0 -0
  87. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/diff/__init__.py +0 -0
  88. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/diff/apply.py +0 -0
  89. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/diff/engine.py +0 -0
  90. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/diff/persistence.py +0 -0
  91. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/diff/templates/diff_prompt.md +0 -0
  92. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/drift.py +0 -0
  93. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/e2e_extractor.py +0 -0
  94. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/e2e_generator.py +0 -0
  95. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/e2e_runner.py +0 -0
  96. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/__init__.py +0 -0
  97. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/apply.py +0 -0
  98. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/finding.py +0 -0
  99. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/formatters/__init__.py +0 -0
  100. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/formatters/base.py +0 -0
  101. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/formatters/interactive.py +0 -0
  102. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/formatters/json_fmt.py +0 -0
  103. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/formatters/md.py +0 -0
  104. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/lexicon_loader.py +0 -0
  105. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/persistence.py +0 -0
  106. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/elicit/templates/elicit_prompt_L0.md +0 -0
  107. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/env_refs.py +0 -0
  108. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/extract_ai.py +0 -0
  109. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/extractor.py +0 -0
  110. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/fixer.py +0 -0
  111. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/fixup_drift.py +0 -0
  112. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/fixup_drift_strategies/__init__.py +0 -0
  113. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/fixup_drift_strategies/design_token_drift.py +0 -0
  114. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/fixup_drift_strategies/lexicon_violation.py +0 -0
  115. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/fixup_drift_strategies/url_drift.py +0 -0
  116. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/generator.py +0 -0
  117. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/graph.py +0 -0
  118. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/hitl_session.py +0 -0
  119. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/hooks/__init__.py +0 -0
  120. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/hooks/pre-commit +0 -0
  121. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/hooks/recipes/claude_settings_example.json +0 -0
  122. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/hooks/recipes/codex_hook.sh +0 -0
  123. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/hooks/recipes/git_post_commit.sh +0 -0
  124. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/hooks/recipes/git_pre_commit.sh +0 -0
  125. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/implementer/__init__.py +0 -0
  126. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/implementer/chunked_runner.py +0 -0
  127. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/implementer/typecheck_loop.py +0 -0
  128. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/implementer.py +0 -0
  129. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/inheritance.py +0 -0
  130. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/init/__init__.py +0 -0
  131. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/init/stack_detector.py +0 -0
  132. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/knowledge_fetcher.py +0 -0
  133. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/lexicon_cli/__init__.py +0 -0
  134. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/lexicon_cli/formatters/__init__.py +0 -0
  135. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/lexicon_cli/formatters/html.py +0 -0
  136. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/lexicon_cli/formatters/json_fmt.py +0 -0
  137. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/lexicon_cli/formatters/md.py +0 -0
  138. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/lexicon_cli/inspector.py +0 -0
  139. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/lexicon_cli/reporter.py +0 -0
  140. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/lexicon_cli/threshold.py +0 -0
  141. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/__init__.py +0 -0
  142. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/approval.py +0 -0
  143. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/best_practice_augmenter.py +0 -0
  144. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/criteria_expander.py +0 -0
  145. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/design_doc_extractor.py +0 -0
  146. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/impl_step_deriver.py +0 -0
  147. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/means_catalog_loader.py +0 -0
  148. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/parser.py +0 -0
  149. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/plan_deriver.py +0 -0
  150. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/prompt_builder.py +0 -0
  151. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/strategy_validator.py +0 -0
  152. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/templates/best_practice_augment_meta.md +0 -0
  153. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/templates/criteria_expand_meta.md +0 -0
  154. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/templates/design_doc_extract_meta.md +0 -0
  155. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/templates/impl_step_derive_meta.md +0 -0
  156. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/templates/implementation_step_catalog.yaml +0 -0
  157. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/templates/meta_instruction.md +0 -0
  158. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/templates/plan_derive_meta.md +0 -0
  159. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/llm/templates/verification_means_catalog.yaml +0 -0
  160. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/mcp_server.py +0 -0
  161. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/measure.py +0 -0
  162. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/parsing.py +0 -0
  163. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/planner.py +0 -0
  164. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/policy.py +0 -0
  165. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/preflight/__init__.py +0 -0
  166. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/preflight/defaults/cli.yaml +0 -0
  167. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/preflight/defaults/iot.yaml +0 -0
  168. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/preflight/defaults/mobile.yaml +0 -0
  169. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/preflight/defaults/web.yaml +0 -0
  170. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/propagate.py +0 -0
  171. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/propagator.py +0 -0
  172. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/registry.py +0 -0
  173. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/__init__.py +0 -0
  174. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/approval_repair.py +0 -0
  175. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/engine.py +0 -0
  176. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/git_patcher.py +0 -0
  177. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/history.py +0 -0
  178. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/llm_repair_engine.py +0 -0
  179. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/loop.py +0 -0
  180. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/primary_picker.py +0 -0
  181. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/proof_breaks.py +0 -0
  182. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/repair_result.py +0 -0
  183. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/repairability_classifier.py +0 -0
  184. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/schema.py +0 -0
  185. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/templates/analyze_meta.md +0 -0
  186. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/templates/propose_meta.md +0 -0
  187. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/templates/repair_strategy_meta.md +0 -0
  188. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/templates/repairability_meta.md +0 -0
  189. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair/verify_runner.py +0 -0
  190. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/repair_slice.py +0 -0
  191. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/require.py +0 -0
  192. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/require_plugins.py +0 -0
  193. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/require_propagate.py +0 -0
  194. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/required_artifacts/defaults/cli.yaml +0 -0
  195. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/required_artifacts/defaults/iot.yaml +0 -0
  196. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/required_artifacts/defaults/mobile.yaml +0 -0
  197. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/required_artifacts/defaults/web.yaml +0 -0
  198. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/required_artifacts_deriver.py +0 -0
  199. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/requirement_completeness/defaults/cli.yaml +0 -0
  200. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/requirement_completeness/defaults/iot.yaml +0 -0
  201. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/requirement_completeness/defaults/mobile.yaml +0 -0
  202. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/requirement_completeness/defaults/web.yaml +0 -0
  203. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/requirement_completeness_auditor.py +0 -0
  204. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/restore.py +0 -0
  205. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/routes_extractor.py +0 -0
  206. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/scanner.py +0 -0
  207. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/schema_refs.py +0 -0
  208. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/screen_flow_validator.py +0 -0
  209. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/screen_transition_extractor.py +0 -0
  210. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/screen_transitions/defaults.yaml +0 -0
  211. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/synth.py +0 -0
  212. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/codd.yaml.tmpl +0 -0
  213. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/conventions.yaml.tmpl +0 -0
  214. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/data_dependencies.yaml.tmpl +0 -0
  215. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/doc_links.yaml.tmpl +0 -0
  216. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/extract_ai_prompt_baseline.md +0 -0
  217. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/extracted/api-contract.md.j2 +0 -0
  218. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/extracted/architecture-overview.md.j2 +0 -0
  219. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/extracted/module-detail.md.j2 +0 -0
  220. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/extracted/schema-design.md.j2 +0 -0
  221. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/extracted/system-context.md.j2 +0 -0
  222. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/gitignore.tmpl +0 -0
  223. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/lexicon_questions.md +0 -0
  224. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/lexicon_schema.yaml +0 -0
  225. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/templates/overrides.yaml.tmpl +0 -0
  226. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/traceability.py +0 -0
  227. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/validator.py +0 -0
  228. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/watch/__init__.py +0 -0
  229. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/watch/events.py +0 -0
  230. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/watch/propagation_log.py +0 -0
  231. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/watch/propagation_pipeline.py +0 -0
  232. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/watch/test_runner.py +0 -0
  233. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/watch/watcher.py +0 -0
  234. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd/wiring.py +0 -0
  235. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ai_governance_eu_act/coverage_matrix.md +0 -0
  236. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ai_governance_eu_act/elicit_extend.md +0 -0
  237. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ai_governance_eu_act/lexicon.yaml +0 -0
  238. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ai_governance_eu_act/manifest.yaml +0 -0
  239. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ai_governance_eu_act/recommended_kinds.yaml +0 -0
  240. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ai_governance_eu_act/severity_rules.yaml +0 -0
  241. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/api_rest_openapi/coverage_matrix.md +0 -0
  242. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/api_rest_openapi/elicit_extend.md +0 -0
  243. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/api_rest_openapi/lexicon.yaml +0 -0
  244. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/api_rest_openapi/manifest.yaml +0 -0
  245. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/api_rest_openapi/recommended_kinds.yaml +0 -0
  246. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/api_rest_openapi/severity_rules.yaml +0 -0
  247. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/babok/elicit_extend.md +0 -0
  248. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/babok/lexicon.yaml +0 -0
  249. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/babok/manifest.yaml +0 -0
  250. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/babok/recommended_kinds.yaml +0 -0
  251. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/babok/severity_rules.yaml +0 -0
  252. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_event_cloudevents/coverage_matrix.md +0 -0
  253. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_event_cloudevents/elicit_extend.md +0 -0
  254. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_event_cloudevents/lexicon.yaml +0 -0
  255. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_event_cloudevents/manifest.yaml +0 -0
  256. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_event_cloudevents/recommended_kinds.yaml +0 -0
  257. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_event_cloudevents/severity_rules.yaml +0 -0
  258. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_graphql/coverage_matrix.md +0 -0
  259. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_graphql/elicit_extend.md +0 -0
  260. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_graphql/lexicon.yaml +0 -0
  261. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_graphql/manifest.yaml +0 -0
  262. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_graphql/recommended_kinds.yaml +0 -0
  263. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_graphql/severity_rules.yaml +0 -0
  264. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_grpc_proto/coverage_matrix.md +0 -0
  265. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_grpc_proto/elicit_extend.md +0 -0
  266. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_grpc_proto/lexicon.yaml +0 -0
  267. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_grpc_proto/manifest.yaml +0 -0
  268. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_grpc_proto/recommended_kinds.yaml +0 -0
  269. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/backend_grpc_proto/severity_rules.yaml +0 -0
  270. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_hipaa/coverage_matrix.md +0 -0
  271. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_hipaa/elicit_extend.md +0 -0
  272. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_hipaa/lexicon.yaml +0 -0
  273. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_hipaa/manifest.yaml +0 -0
  274. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_hipaa/recommended_kinds.yaml +0 -0
  275. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_hipaa/severity_rules.yaml +0 -0
  276. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_iso27001/coverage_matrix.md +0 -0
  277. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_iso27001/elicit_extend.md +0 -0
  278. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_iso27001/lexicon.yaml +0 -0
  279. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_iso27001/manifest.yaml +0 -0
  280. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_iso27001/recommended_kinds.yaml +0 -0
  281. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_iso27001/severity_rules.yaml +0 -0
  282. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_pci_dss_4/coverage_matrix.md +0 -0
  283. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_pci_dss_4/elicit_extend.md +0 -0
  284. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_pci_dss_4/lexicon.yaml +0 -0
  285. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_pci_dss_4/manifest.yaml +0 -0
  286. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_pci_dss_4/recommended_kinds.yaml +0 -0
  287. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/compliance_pci_dss_4/severity_rules.yaml +0 -0
  288. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/coverage_matrix.md +0 -0
  289. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/elicit_extend.md +0 -0
  290. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/lexicon.yaml +0 -0
  291. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/manifest.yaml +0 -0
  292. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/recommended_kinds.yaml +0 -0
  293. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_eventsourcing_es_cqrs/severity_rules.yaml +0 -0
  294. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_governance_appi_gdpr/coverage_matrix.md +0 -0
  295. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_governance_appi_gdpr/elicit_extend.md +0 -0
  296. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_governance_appi_gdpr/lexicon.yaml +0 -0
  297. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_governance_appi_gdpr/manifest.yaml +0 -0
  298. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_governance_appi_gdpr/recommended_kinds.yaml +0 -0
  299. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_governance_appi_gdpr/severity_rules.yaml +0 -0
  300. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_nosql_jsonschema/coverage_matrix.md +0 -0
  301. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_nosql_jsonschema/elicit_extend.md +0 -0
  302. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_nosql_jsonschema/lexicon.yaml +0 -0
  303. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_nosql_jsonschema/manifest.yaml +0 -0
  304. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_nosql_jsonschema/recommended_kinds.yaml +0 -0
  305. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_nosql_jsonschema/severity_rules.yaml +0 -0
  306. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_relational_iso_sql/coverage_matrix.md +0 -0
  307. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_relational_iso_sql/elicit_extend.md +0 -0
  308. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_relational_iso_sql/lexicon.yaml +0 -0
  309. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_relational_iso_sql/manifest.yaml +0 -0
  310. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_relational_iso_sql/recommended_kinds.yaml +0 -0
  311. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/data_relational_iso_sql/severity_rules.yaml +0 -0
  312. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_a11y_native/coverage_matrix.md +0 -0
  313. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_a11y_native/elicit_extend.md +0 -0
  314. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_a11y_native/lexicon.yaml +0 -0
  315. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_a11y_native/manifest.yaml +0 -0
  316. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_a11y_native/recommended_kinds.yaml +0 -0
  317. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_a11y_native/severity_rules.yaml +0 -0
  318. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_android_material3/coverage_matrix.md +0 -0
  319. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_android_material3/elicit_extend.md +0 -0
  320. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_android_material3/lexicon.yaml +0 -0
  321. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_android_material3/manifest.yaml +0 -0
  322. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_android_material3/recommended_kinds.yaml +0 -0
  323. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_android_material3/severity_rules.yaml +0 -0
  324. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_ios_hig/coverage_matrix.md +0 -0
  325. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_ios_hig/elicit_extend.md +0 -0
  326. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_ios_hig/lexicon.yaml +0 -0
  327. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_ios_hig/manifest.yaml +0 -0
  328. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_ios_hig/recommended_kinds.yaml +0 -0
  329. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/mobile_ios_hig/severity_rules.yaml +0 -0
  330. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_cicd_pipeline/coverage_matrix.md +0 -0
  331. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_cicd_pipeline/elicit_extend.md +0 -0
  332. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_cicd_pipeline/lexicon.yaml +0 -0
  333. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_cicd_pipeline/manifest.yaml +0 -0
  334. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_cicd_pipeline/recommended_kinds.yaml +0 -0
  335. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_cicd_pipeline/severity_rules.yaml +0 -0
  336. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_iac_terraform/coverage_matrix.md +0 -0
  337. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_iac_terraform/elicit_extend.md +0 -0
  338. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_iac_terraform/lexicon.yaml +0 -0
  339. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_iac_terraform/manifest.yaml +0 -0
  340. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_iac_terraform/recommended_kinds.yaml +0 -0
  341. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_iac_terraform/severity_rules.yaml +0 -0
  342. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_kubernetes/coverage_matrix.md +0 -0
  343. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_kubernetes/elicit_extend.md +0 -0
  344. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_kubernetes/lexicon.yaml +0 -0
  345. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_kubernetes/manifest.yaml +0 -0
  346. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_kubernetes/recommended_kinds.yaml +0 -0
  347. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_kubernetes/severity_rules.yaml +0 -0
  348. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_observability_otel/coverage_matrix.md +0 -0
  349. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_observability_otel/elicit_extend.md +0 -0
  350. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_observability_otel/lexicon.yaml +0 -0
  351. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_observability_otel/manifest.yaml +0 -0
  352. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_observability_otel/recommended_kinds.yaml +0 -0
  353. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/ops_observability_otel/severity_rules.yaml +0 -0
  354. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_iso25010/coverage_matrix.md +0 -0
  355. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_iso25010/elicit_extend.md +0 -0
  356. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_iso25010/lexicon.yaml +0 -0
  357. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_iso25010/manifest.yaml +0 -0
  358. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_iso25010/recommended_kinds.yaml +0 -0
  359. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_iso25010/severity_rules.yaml +0 -0
  360. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_test_iso29119/coverage_matrix.md +0 -0
  361. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_test_iso29119/elicit_extend.md +0 -0
  362. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_test_iso29119/lexicon.yaml +0 -0
  363. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_test_iso29119/manifest.yaml +0 -0
  364. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_test_iso29119/recommended_kinds.yaml +0 -0
  365. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/process_test_iso29119/severity_rules.yaml +0 -0
  366. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/coverage_matrix.md +0 -0
  367. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/elicit_extend.md +0 -0
  368. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/lexicon.yaml +0 -0
  369. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/manifest.yaml +0 -0
  370. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/recommended_kinds.yaml +0 -0
  371. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_a11y_wcag22_aa/severity_rules.yaml +0 -0
  372. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_authn_webauthn/coverage_matrix.md +0 -0
  373. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_authn_webauthn/elicit_extend.md +0 -0
  374. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_authn_webauthn/lexicon.yaml +0 -0
  375. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_authn_webauthn/manifest.yaml +0 -0
  376. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_authn_webauthn/recommended_kinds.yaml +0 -0
  377. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_authn_webauthn/severity_rules.yaml +0 -0
  378. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_browser_compat/coverage_matrix.md +0 -0
  379. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_browser_compat/elicit_extend.md +0 -0
  380. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_browser_compat/lexicon.yaml +0 -0
  381. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_browser_compat/manifest.yaml +0 -0
  382. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_browser_compat/recommended_kinds.yaml +0 -0
  383. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_browser_compat/severity_rules.yaml +0 -0
  384. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_forms_html5/coverage_matrix.md +0 -0
  385. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_forms_html5/elicit_extend.md +0 -0
  386. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_forms_html5/lexicon.yaml +0 -0
  387. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_forms_html5/manifest.yaml +0 -0
  388. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_forms_html5/recommended_kinds.yaml +0 -0
  389. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_forms_html5/severity_rules.yaml +0 -0
  390. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_performance_core_web_vitals/coverage_matrix.md +0 -0
  391. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_performance_core_web_vitals/elicit_extend.md +0 -0
  392. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_performance_core_web_vitals/lexicon.yaml +0 -0
  393. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_performance_core_web_vitals/manifest.yaml +0 -0
  394. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_performance_core_web_vitals/recommended_kinds.yaml +0 -0
  395. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_performance_core_web_vitals/severity_rules.yaml +0 -0
  396. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_pwa_manifest/coverage_matrix.md +0 -0
  397. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_pwa_manifest/elicit_extend.md +0 -0
  398. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_pwa_manifest/lexicon.yaml +0 -0
  399. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_pwa_manifest/manifest.yaml +0 -0
  400. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_pwa_manifest/recommended_kinds.yaml +0 -0
  401. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_pwa_manifest/severity_rules.yaml +0 -0
  402. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_responsive/coverage_matrix.md +0 -0
  403. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_responsive/elicit_extend.md +0 -0
  404. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_responsive/lexicon.yaml +0 -0
  405. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_responsive/manifest.yaml +0 -0
  406. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_responsive/recommended_kinds.yaml +0 -0
  407. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_responsive/severity_rules.yaml +0 -0
  408. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_security_owasp/coverage_matrix.md +0 -0
  409. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_security_owasp/elicit_extend.md +0 -0
  410. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_security_owasp/lexicon.yaml +0 -0
  411. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_security_owasp/manifest.yaml +0 -0
  412. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_security_owasp/recommended_kinds.yaml +0 -0
  413. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_security_owasp/severity_rules.yaml +0 -0
  414. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_seo_schemaorg/coverage_matrix.md +0 -0
  415. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_seo_schemaorg/elicit_extend.md +0 -0
  416. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_seo_schemaorg/lexicon.yaml +0 -0
  417. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_seo_schemaorg/manifest.yaml +0 -0
  418. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_seo_schemaorg/recommended_kinds.yaml +0 -0
  419. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/lexicons/web_seo_schemaorg/severity_rules.yaml +0 -0
  420. {codd_dev-2.4.0 → codd_dev-2.6.0}/codd_plugins/stack_map.yaml +0 -0
  421. {codd_dev-2.4.0 → codd_dev-2.6.0}/docs/cookbook/cdp_browser/README.md +0 -0
  422. {codd_dev-2.4.0 → codd_dev-2.6.0}/docs/requirements/README.md +0 -0
  423. {codd_dev-2.4.0 → codd_dev-2.6.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.4.0
3
+ Version: 2.6.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
@@ -16,7 +16,7 @@ import yaml
16
16
 
17
17
  from codd.bridge import PRO_COMMAND_INSTALL_MESSAGE, get_command_handler
18
18
  from codd.config import find_codd_dir, load_project_config
19
- from codd.lexicon import LEXICON_FILENAME, load_lexicon
19
+ from codd.lexicon import LEXICON_FILENAME, load_lexicon, load_project_extends
20
20
 
21
21
  TEMPLATES_DIR = Path(__file__).parent / "templates"
22
22
 
@@ -1087,7 +1087,7 @@ def elicit(
1087
1087
 
1088
1088
  project_root = Path(project_path).resolve()
1089
1089
  try:
1090
- lexicon_config = _load_elicit_lexicon(project_root, lexicon_path) if lexicon_path else None
1090
+ lexicon_config = _load_elicit_lexicon_configs(project_root, lexicon_path)
1091
1091
  elicit_result = ElicitEngine(ai_command=ai_cmd).run(project_root, lexicon_config=lexicon_config)
1092
1092
  except (OSError, ValueError, json.JSONDecodeError, yaml.YAMLError) as exc:
1093
1093
  click.echo(f"Error: {exc}")
@@ -1128,6 +1128,18 @@ def elicit(
1128
1128
  click.echo(f"Output: {_display_path(output_path, project_root)}")
1129
1129
 
1130
1130
 
1131
+ def _load_elicit_lexicon_configs(project_root: Path, lexicon_path: str | None):
1132
+ selectors = _split_elicit_lexicon_selectors(lexicon_path) if lexicon_path else load_project_extends(project_root)
1133
+ if not selectors:
1134
+ return None
1135
+ configs = [_load_elicit_lexicon(project_root, selector) for selector in selectors]
1136
+ return configs[0] if len(configs) == 1 else configs
1137
+
1138
+
1139
+ def _split_elicit_lexicon_selectors(value: str) -> list[str]:
1140
+ return [item.strip() for item in value.split(",") if item.strip()]
1141
+
1142
+
1131
1143
  def _load_elicit_lexicon(project_root: Path, lexicon_path: str):
1132
1144
  from codd.elicit.lexicon_loader import load_lexicon
1133
1145
 
@@ -2,10 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from collections.abc import Callable, Mapping
6
5
  import json
7
- from pathlib import Path
8
6
  import re
7
+ import warnings
8
+ from collections.abc import Callable, Mapping
9
+ from dataclasses import replace
10
+ from pathlib import Path
9
11
  from typing import Any
10
12
 
11
13
  import yaml
@@ -36,15 +38,30 @@ class ElicitEngine:
36
38
  def run(self, project_root: Path, lexicon_config: Any | None = None) -> ElicitResult:
37
39
  root = Path(project_root)
38
40
  project_scope, project_phase = _project_scope_phase(root)
41
+ lexicon_configs = _as_lexicon_configs(lexicon_config)
42
+ if len(lexicon_configs) > 1:
43
+ return self._run_many(root, lexicon_configs, scope=project_scope, phase=project_phase)
44
+ config = lexicon_configs[0] if lexicon_configs else None
45
+ return self._run_one(root, config, scope=project_scope, phase=project_phase)
46
+
47
+ def _run_one(
48
+ self,
49
+ root: Path,
50
+ lexicon_config: Any | None,
51
+ *,
52
+ scope: str,
53
+ phase: str,
54
+ ) -> ElicitResult:
39
55
  prompt = self.build_prompt(root, lexicon_config=lexicon_config)
40
56
  raw_output = self.invoke(prompt, root)
41
57
  result = self.deserialize_result(raw_output)
42
58
  result.findings = _apply_scope_phase(
43
59
  result.findings,
44
60
  lexicon_config=lexicon_config,
45
- scope=project_scope,
46
- phase=project_phase,
61
+ scope=scope,
62
+ phase=phase,
47
63
  )
64
+ _attach_lexicon_source(result.findings, _string_attr(lexicon_config, "lexicon_name"))
48
65
  result.findings = ElicitPersistence(root).filter_known(result.findings)
49
66
  if not result.findings and result.lexicon_coverage_report:
50
67
  non_gap = all(
@@ -55,6 +72,42 @@ class ElicitEngine:
55
72
  result.all_covered = True
56
73
  return result
57
74
 
75
+ def _run_many(
76
+ self,
77
+ root: Path,
78
+ lexicon_configs: list[Any],
79
+ *,
80
+ scope: str,
81
+ phase: str,
82
+ ) -> ElicitResult:
83
+ prepared = _prepare_lexicon_configs(lexicon_configs)
84
+ combined = ElicitResult()
85
+ for config, duplicate_axes in prepared:
86
+ result = self._run_one(root, config, scope=scope, phase=phase)
87
+ if duplicate_axes:
88
+ result.findings = [
89
+ finding
90
+ for finding in result.findings
91
+ if _finding_axis(finding) not in duplicate_axes
92
+ ]
93
+ combined.findings.extend(result.findings)
94
+ for axis, status in result.lexicon_coverage_report.items():
95
+ if axis in combined.lexicon_coverage_report:
96
+ warnings.warn(
97
+ f"duplicate lexicon dimension '{axis}' ignored; first lexicon wins",
98
+ RuntimeWarning,
99
+ stacklevel=2,
100
+ )
101
+ continue
102
+ combined.lexicon_coverage_report[axis] = status
103
+
104
+ if combined.lexicon_coverage_report and not combined.findings:
105
+ combined.all_covered = all(
106
+ str(status).lower() != "gap"
107
+ for status in combined.lexicon_coverage_report.values()
108
+ )
109
+ return combined
110
+
58
111
  def build_prompt(self, project_root: Path, lexicon_config: Any | None = None) -> str:
59
112
  root = Path(project_root)
60
113
  template = self._template_text(lexicon_config)
@@ -86,6 +139,9 @@ class ElicitEngine:
86
139
  return ElicitResult.from_payload(payload)
87
140
 
88
141
  def _template_text(self, lexicon_config: Any | None) -> str:
142
+ configs = _as_lexicon_configs(lexicon_config)
143
+ if configs:
144
+ lexicon_config = configs[0]
89
145
  extension = _string_attr(lexicon_config, "prompt_extension_content")
90
146
  if extension:
91
147
  return extension
@@ -147,6 +203,60 @@ def _read_documents(paths: list[Path], project_root: Path, max_chars: int) -> st
147
203
  return "\n".join(chunks) if chunks else "(none provided)"
148
204
 
149
205
 
206
+ def _as_lexicon_configs(lexicon_config: Any | None) -> list[Any]:
207
+ if lexicon_config is None:
208
+ return []
209
+ if isinstance(lexicon_config, (list, tuple)):
210
+ return [item for item in lexicon_config if item is not None]
211
+ return [lexicon_config]
212
+
213
+
214
+ def _prepare_lexicon_configs(lexicon_configs: list[Any]) -> list[tuple[Any, set[str]]]:
215
+ prepared: list[tuple[Any, set[str]]] = []
216
+ seen_axes: set[str] = set()
217
+ for config in lexicon_configs:
218
+ kept_axes: list[dict[str, Any]] = []
219
+ duplicate_axes: set[str] = set()
220
+ for axis in _list_attr(config, "coverage_axes"):
221
+ if not isinstance(axis, Mapping):
222
+ continue
223
+ axis_type = axis.get("axis_type")
224
+ if not isinstance(axis_type, str) or not axis_type.strip():
225
+ kept_axes.append(dict(axis))
226
+ continue
227
+ normalized_axis = axis_type.strip()
228
+ if normalized_axis in seen_axes:
229
+ duplicate_axes.add(normalized_axis)
230
+ warnings.warn(
231
+ f"duplicate lexicon dimension '{normalized_axis}' ignored; first lexicon wins",
232
+ RuntimeWarning,
233
+ stacklevel=2,
234
+ )
235
+ continue
236
+ seen_axes.add(normalized_axis)
237
+ kept_axes.append(dict(axis))
238
+ prepared.append((_with_coverage_axes(config, kept_axes), duplicate_axes))
239
+ return prepared
240
+
241
+
242
+ def _with_coverage_axes(config: Any, coverage_axes: list[dict[str, Any]]) -> Any:
243
+ if isinstance(config, Mapping):
244
+ updated = dict(config)
245
+ updated["coverage_axes"] = coverage_axes
246
+ return updated
247
+ try:
248
+ return replace(config, coverage_axes=coverage_axes)
249
+ except TypeError:
250
+ return config
251
+
252
+
253
+ def _attach_lexicon_source(findings: list[Finding], lexicon_name: str | None) -> None:
254
+ if not lexicon_name:
255
+ return
256
+ for finding in findings:
257
+ finding.details["lexicon_source"] = lexicon_name
258
+
259
+
150
260
  def _project_lexicon_text(project_root: Path, lexicon_config: Any | None, max_chars: int) -> str:
151
261
  chunks: list[str] = []
152
262
  for name in ("project_lexicon.yaml", "project_lexicon.yml"):
@@ -154,12 +264,13 @@ def _project_lexicon_text(project_root: Path, lexicon_config: Any | None, max_ch
154
264
  if path.is_file():
155
265
  chunks.append(path.read_text(encoding="utf-8", errors="replace").strip())
156
266
  break
157
- lexicon_name = _string_attr(lexicon_config, "lexicon_name")
158
- recommended = getattr(lexicon_config, "recommended_kinds", None)
159
- if lexicon_name:
160
- chunks.append(f"loaded_lexicon: {lexicon_name}")
161
- if isinstance(recommended, list) and recommended:
162
- chunks.append(yaml.safe_dump({"recommended_kinds": recommended}, sort_keys=False).strip())
267
+ for config in _as_lexicon_configs(lexicon_config):
268
+ lexicon_name = _string_attr(config, "lexicon_name")
269
+ recommended = getattr(config, "recommended_kinds", None)
270
+ if lexicon_name:
271
+ chunks.append(f"loaded_lexicon: {lexicon_name}")
272
+ if isinstance(recommended, list) and recommended:
273
+ chunks.append(yaml.safe_dump({"recommended_kinds": recommended}, sort_keys=False).strip())
163
274
  text = "\n\n".join(chunk for chunk in chunks if chunk)
164
275
  return text[:max_chars] if text else "(none provided)"
165
276
 
@@ -5,12 +5,15 @@ from __future__ import annotations
5
5
  from collections.abc import Iterable, Sequence
6
6
  from dataclasses import dataclass
7
7
  from pathlib import Path
8
- from typing import Any
9
8
  import re
10
9
 
11
10
  import yaml
12
11
 
13
- from codd.lexicon import LEXICON_FILENAME
12
+ from codd.lexicon import (
13
+ LEXICON_FILENAME,
14
+ merge_lexicon_entries,
15
+ normalize_project_lexicon_data,
16
+ )
14
17
 
15
18
 
16
19
  @dataclass(frozen=True)
@@ -77,17 +80,10 @@ def describe_lexicons(lexicon_ids: Iterable[str], lexicon_root: Path | None = No
77
80
  def append_suggested_lexicons(project_root: Path, lexicon_ids: Sequence[str]) -> Path:
78
81
  path = Path(project_root) / LEXICON_FILENAME
79
82
  data = _load_project_lexicon(path)
80
- current = data.get("suggested_lexicons", [])
83
+ current = data.get("extends", [])
81
84
  if not isinstance(current, list):
82
- raise ValueError("project_lexicon.yaml suggested_lexicons must be a list")
83
- known = {_lexicon_id(item) for item in current}
84
- merged = list(current)
85
- for lexicon_id in lexicon_ids:
86
- if lexicon_id in known:
87
- continue
88
- merged.append(lexicon_id)
89
- known.add(lexicon_id)
90
- data["suggested_lexicons"] = merged
85
+ raise ValueError("project_lexicon.yaml extends must be a list")
86
+ data["extends"] = merge_lexicon_entries(current, list(lexicon_ids))
91
87
  path.write_text(yaml.safe_dump(data, sort_keys=False, allow_unicode=True), encoding="utf-8")
92
88
  return path
93
89
 
@@ -97,7 +93,7 @@ def _load_project_lexicon(path: Path) -> dict[str, Any]:
97
93
  payload = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
98
94
  if not isinstance(payload, dict):
99
95
  raise ValueError("project_lexicon.yaml must contain a YAML mapping")
100
- return payload
96
+ return normalize_project_lexicon_data(payload)
101
97
  return {
102
98
  "version": "1.0",
103
99
  "node_vocabulary": [],
@@ -106,12 +102,3 @@ def _load_project_lexicon(path: Path) -> dict[str, Any]:
106
102
  "Review suggested lexicons before treating project conventions as approved.",
107
103
  ],
108
104
  }
109
-
110
-
111
- def _lexicon_id(item: Any) -> str:
112
- if isinstance(item, str):
113
- return item
114
- if isinstance(item, dict):
115
- return str(item.get("id", item.get("name", item.get("lexicon_name", ""))))
116
- return str(item)
117
-
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import warnings
5
6
  from copy import deepcopy
6
7
  from dataclasses import asdict, dataclass, field
7
8
  from pathlib import Path
@@ -15,6 +16,9 @@ LEXICON_FILENAME = "project_lexicon.yaml"
15
16
  REQUIRED_ARTIFACT_SOURCES = {"ai_derived", "user_override", "default_template"}
16
17
  DEFAULT_SCOPE = "full"
17
18
  DEFAULT_PHASE = "production"
19
+ LEGACY_SUGGESTED_LEXICONS_WARNING = (
20
+ "suggested_lexicons is deprecated, renamed to extends; auto-merged"
21
+ )
18
22
 
19
23
 
20
24
  @dataclass
@@ -45,7 +49,7 @@ class AskItem:
45
49
  answered_at: str = ""
46
50
 
47
51
 
48
- class LexiconError(Exception):
52
+ class LexiconError(ValueError):
49
53
  """Raised when a project lexicon is malformed."""
50
54
 
51
55
 
@@ -90,6 +94,10 @@ class ProjectLexicon:
90
94
  for item in self._data.get("coverage_decisions", [])
91
95
  ]
92
96
 
97
+ @property
98
+ def extends(self) -> list[str]:
99
+ return lexicon_ids_from_entries(self._data.get("extends", []))
100
+
93
101
  @property
94
102
  def required_artifacts(self) -> list[dict[str, Any]]:
95
103
  return deepcopy(self._data.get("required_artifacts", []))
@@ -152,10 +160,83 @@ def load_lexicon(project_root: str | Path) -> ProjectLexicon | None:
152
160
  if not path.exists():
153
161
  return None
154
162
  data = yaml.safe_load(path.read_text(encoding="utf-8"))
163
+ if not isinstance(data, dict):
164
+ raise LexiconError("project_lexicon.yaml must contain a YAML mapping")
165
+ data = normalize_project_lexicon_data(data)
155
166
  validate_lexicon(data)
156
167
  return ProjectLexicon(data)
157
168
 
158
169
 
170
+ def load_project_extends(project_root: str | Path) -> list[str]:
171
+ """Load project-level lexicon IDs from extends, with legacy shim support."""
172
+ path = Path(project_root) / LEXICON_FILENAME
173
+ if not path.exists():
174
+ return []
175
+ data = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
176
+ if not isinstance(data, dict):
177
+ raise LexiconError("project_lexicon.yaml must contain a YAML mapping")
178
+ normalized = normalize_project_lexicon_data(data)
179
+ return lexicon_ids_from_entries(normalized.get("extends", []))
180
+
181
+
182
+ def normalize_project_lexicon_data(data: dict[str, Any]) -> dict[str, Any]:
183
+ """Return lexicon data with legacy suggested_lexicons merged into extends.
184
+
185
+ The legacy field remains in the returned mapping for backward compatibility;
186
+ only the canonical runtime list is merged into ``extends``.
187
+ """
188
+ normalized = deepcopy(data)
189
+ current = _optional_lexicon_entries(normalized, "extends")
190
+ if "suggested_lexicons" not in normalized:
191
+ return normalized
192
+
193
+ legacy = _optional_lexicon_entries(normalized, "suggested_lexicons")
194
+ warnings.warn(
195
+ LEGACY_SUGGESTED_LEXICONS_WARNING,
196
+ DeprecationWarning,
197
+ stacklevel=2,
198
+ )
199
+ normalized["extends"] = merge_lexicon_entries(current, legacy)
200
+ return normalized
201
+
202
+
203
+ def merge_lexicon_entries(primary: list[Any], secondary: list[Any]) -> list[Any]:
204
+ merged = list(primary)
205
+ known = set(lexicon_ids_from_entries(merged))
206
+ for item in secondary:
207
+ lexicon_id = lexicon_id_from_entry(item)
208
+ if not lexicon_id or lexicon_id in known:
209
+ continue
210
+ merged.append(item)
211
+ known.add(lexicon_id)
212
+ return merged
213
+
214
+
215
+ def lexicon_ids_from_entries(entries: Any) -> list[str]:
216
+ if not isinstance(entries, list):
217
+ return []
218
+ seen: set[str] = set()
219
+ ids: list[str] = []
220
+ for item in entries:
221
+ lexicon_id = lexicon_id_from_entry(item)
222
+ if not lexicon_id or lexicon_id in seen:
223
+ continue
224
+ seen.add(lexicon_id)
225
+ ids.append(lexicon_id)
226
+ return ids
227
+
228
+
229
+ def lexicon_id_from_entry(item: Any) -> str:
230
+ if isinstance(item, str):
231
+ return item.strip()
232
+ if isinstance(item, dict):
233
+ for key in ("id", "name", "lexicon_name"):
234
+ value = item.get(key)
235
+ if isinstance(value, str) and value.strip():
236
+ return value.strip()
237
+ return str(item).strip()
238
+
239
+
159
240
  def ask_option_from_dict(data: dict[str, Any]) -> AskOption:
160
241
  """Build an AskOption from YAML-safe dict data."""
161
242
  if not isinstance(data, dict):
@@ -258,6 +339,10 @@ def validate_lexicon(data: dict[str, Any]) -> None:
258
339
  if not isinstance(design_principles, list):
259
340
  raise LexiconError("design_principles must be a list")
260
341
 
342
+ for field_name in ("extends", "suggested_lexicons"):
343
+ if field_name in data and not isinstance(data[field_name], list):
344
+ raise LexiconError(f"{field_name} must be a list")
345
+
261
346
  failure_modes = data.get("failure_modes", [])
262
347
  _validate_list_of_mappings(failure_modes, "failure_modes")
263
348
 
@@ -323,6 +408,15 @@ def _validate_list_of_mappings(value: Any, name: str) -> None:
323
408
  raise LexiconError(f"{name} items must be mappings: {item}")
324
409
 
325
410
 
411
+ def _optional_lexicon_entries(data: dict[str, Any], field_name: str) -> list[Any]:
412
+ value = data.get(field_name, [])
413
+ if value is None:
414
+ return []
415
+ if not isinstance(value, list):
416
+ raise LexiconError(f"{field_name} must be a list")
417
+ return list(value)
418
+
419
+
326
420
  def _optional_str(value: Any) -> str | None:
327
421
  if value is None:
328
422
  return None
@@ -9,7 +9,7 @@ from typing import Any
9
9
  import yaml
10
10
 
11
11
  from codd.init.lexicon_suggest import append_suggested_lexicons, default_lexicon_root
12
- from codd.lexicon import LEXICON_FILENAME, load_lexicon as load_project_lexicon
12
+ from codd.lexicon import LEXICON_FILENAME, load_project_extends
13
13
 
14
14
 
15
15
  @dataclass(frozen=True)
@@ -44,21 +44,14 @@ class LexiconManager:
44
44
  if not path.is_file():
45
45
  return []
46
46
 
47
- data: dict[str, Any] | None = None
48
47
  try:
49
- loaded = load_project_lexicon(self.project_root)
50
- data = loaded.as_dict() if loaded is not None else None
48
+ return load_project_extends(self.project_root)
51
49
  except Exception:
52
50
  payload = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
53
- if isinstance(payload, dict):
54
- data = payload
55
- if not data:
51
+ if not isinstance(payload, dict):
56
52
  return []
57
-
58
- raw = data.get("suggested_lexicons", [])
59
- if not isinstance(raw, list):
60
- return []
61
- return _dedupe(_lexicon_id(item) for item in raw)
53
+ raw = payload.get("extends", payload.get("suggested_lexicons", []))
54
+ return _dedupe(_lexicon_id(item) for item in raw) if isinstance(raw, list) else []
62
55
 
63
56
  def available(self) -> list[LexiconRecord]:
64
57
  installed = set(self.installed_ids())
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "codd-dev"
7
- version = "2.4.0"
7
+ version = "2.6.0"
8
8
  description = "CoDD: Coherence-Driven Development — cross-artifact change impact analysis"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes