metaobjects 0.22.0__tar.gz → 0.23.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 (408) hide show
  1. {metaobjects-0.22.0 → metaobjects-0.23.0}/PKG-INFO +1 -1
  2. {metaobjects-0.22.0 → metaobjects-0.23.0}/pyproject.toml +1 -1
  3. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/entity_model.py +25 -3
  4. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/core_types.py +44 -8
  5. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/requirement/meta_requirement.py +44 -8
  6. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/requirement/requirement_constants.py +31 -0
  7. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/documentation.json +4 -4
  8. metaobjects-0.23.0/src/metaobjects/spec_metamodel/requirement.json +209 -0
  9. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_validation_conformance.py +21 -14
  10. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/postgres_container.py +84 -14
  11. {metaobjects-0.22.0 → metaobjects-0.23.0}/uv.lock +1 -1
  12. metaobjects-0.22.0/src/metaobjects/spec_metamodel/requirement.json +0 -140
  13. {metaobjects-0.22.0 → metaobjects-0.23.0}/.gitignore +0 -0
  14. {metaobjects-0.22.0 → metaobjects-0.23.0}/LICENSE +0 -0
  15. {metaobjects-0.22.0 → metaobjects-0.23.0}/README.md +0 -0
  16. {metaobjects-0.22.0 → metaobjects-0.23.0}/hatch_build.py +0 -0
  17. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/__init__.py +0 -0
  18. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/agent_context/__init__.py +0 -0
  19. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/agent_context/scaffold.py +0 -0
  20. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/__init__.py +0 -0
  21. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/api_model.py +0 -0
  22. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/builder.py +0 -0
  23. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/naming.py +0 -0
  24. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/paths.py +0 -0
  25. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/renderer.py +0 -0
  26. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/attr_class_map.py +0 -0
  27. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/cli.py +0 -0
  28. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/KNOWN_GAPS.md +0 -0
  29. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/__init__.py +0 -0
  30. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/collision_names.py +0 -0
  31. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/config.py +0 -0
  32. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/constants.py +0 -0
  33. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
  34. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
  35. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/format.py +0 -0
  36. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
  37. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generator.py +0 -0
  38. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generator_registry.py +0 -0
  39. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/__init__.py +0 -0
  40. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
  41. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +0 -0
  42. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/fr019_shared_enum.py +0 -0
  43. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/m2m_codegen.py +0 -0
  44. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
  45. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
  46. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/payload_vo_generator.py +0 -0
  47. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
  48. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/router_generator.py +0 -0
  49. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/template_generator.py +0 -0
  50. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
  51. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
  52. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/instance_artifacts.py +0 -0
  53. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/metaobjects-config.schema.json +0 -0
  54. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
  55. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/overwrite_policy.py +0 -0
  56. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/project_config.py +0 -0
  57. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/runner.py +0 -0
  58. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/runtime/__init__.py +0 -0
  59. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
  60. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
  61. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
  62. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
  63. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
  64. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/type_map.py +0 -0
  65. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/datatype.py +0 -0
  66. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/documentation/__init__.py +0 -0
  67. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/documentation/doc_constants.py +0 -0
  68. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/documentation/doc_provider.py +0 -0
  69. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/documentation/doc_schema.py +0 -0
  70. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/errors.py +0 -0
  71. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/__init__.py +0 -0
  72. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/merge.py +0 -0
  73. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/meta_data_loader.py +0 -0
  74. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/registered_validation.py +0 -0
  75. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/sources/__init__.py +0 -0
  76. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/sources/directory_source.py +0 -0
  77. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/sources/file_source.py +0 -0
  78. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
  79. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/sources/uri_source.py +0 -0
  80. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_discriminator.py +0 -0
  81. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_enum_normalize_ambiguity.py +0 -0
  82. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_field_readonly.py +0 -0
  83. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_source_escapes.py +0 -0
  84. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
  85. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
  86. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validation_passes.py +0 -0
  87. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/__init__.py +0 -0
  88. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/__init__.py +0 -0
  89. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/attr/__init__.py +0 -0
  90. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/attr/attr_constants.py +0 -0
  91. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/attr/meta_attr.py +0 -0
  92. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/field/__init__.py +0 -0
  93. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/field/field_constants.py +0 -0
  94. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/field/meta_field.py +0 -0
  95. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/identity/__init__.py +0 -0
  96. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
  97. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
  98. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/index/__init__.py +0 -0
  99. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/index/index_constants.py +0 -0
  100. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/index/meta_index.py +0 -0
  101. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/__init__.py +0 -0
  102. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/meta_object.py +0 -0
  103. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
  104. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
  105. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/object_constants.py +0 -0
  106. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/object_extract.py +0 -0
  107. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/value_object.py +0 -0
  108. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
  109. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
  110. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
  111. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
  112. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/requirement/__init__.py +0 -0
  113. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/validator/__init__.py +0 -0
  114. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
  115. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/meta_data.py +0 -0
  116. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/meta_root.py +0 -0
  117. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/__init__.py +0 -0
  118. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
  119. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
  120. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
  121. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
  122. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
  123. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -0
  124. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
  125. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/source/meta_source.py +0 -0
  126. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/source/source_constants.py +0 -0
  127. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/__init__.py +0 -0
  128. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
  129. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
  130. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
  131. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
  132. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
  133. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
  134. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
  135. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
  136. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/provider_extends.py +0 -0
  137. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/template/__init__.py +0 -0
  138. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/template/meta_template.py +0 -0
  139. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/template/prompt_provider.py +0 -0
  140. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/template/template_constants.py +0 -0
  141. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/naming_refs.py +0 -0
  142. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/parser.py +0 -0
  143. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/parser_yaml.py +0 -0
  144. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/provider.py +0 -0
  145. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/py.typed +0 -0
  146. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/registry.py +0 -0
  147. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/registry_manifest.py +0 -0
  148. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/__init__.py +0 -0
  149. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/email_document.py +0 -0
  150. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/escapers.py +0 -0
  151. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
  152. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/__init__.py +0 -0
  153. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/coerce.py +0 -0
  154. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/extract.py +0 -0
  155. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/extract_map.py +0 -0
  156. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
  157. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/locate.py +0 -0
  158. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/normalize.py +0 -0
  159. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/strip.py +0 -0
  160. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/types.py +0 -0
  161. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/xml_forgiving_reader.py +0 -0
  162. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/filesystem_provider.py +0 -0
  163. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/__init__.py +0 -0
  164. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
  165. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
  166. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/prompt_field.py +0 -0
  167. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
  168. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/prompt_style.py +0 -0
  169. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/renderer.py +0 -0
  170. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/verify.py +0 -0
  171. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/runtime/__init__.py +0 -0
  172. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/runtime/llm_recorder.py +0 -0
  173. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/runtime/n2m_resolver.py +0 -0
  174. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/runtime/object_manager.py +0 -0
  175. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/runtime/tph.py +0 -0
  176. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/serializer_json.py +0 -0
  177. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/shared/__init__.py +0 -0
  178. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/shared/base_types.py +0 -0
  179. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/shared/separators.py +0 -0
  180. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/shared/structural.py +0 -0
  181. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/source/__init__.py +0 -0
  182. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/source/error_source.py +0 -0
  183. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/source/json_path.py +0 -0
  184. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/source/semantic_diff.py +0 -0
  185. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/source/yaml_positions.py +0 -0
  186. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/__init__.py +0 -0
  187. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/attr.json +0 -0
  188. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/db.json +0 -0
  189. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/field.json +0 -0
  190. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/identity.json +0 -0
  191. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/index.json +0 -0
  192. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/layout.json +0 -0
  193. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/object.json +0 -0
  194. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/origin.json +0 -0
  195. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/prompt.json +0 -0
  196. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/relationship.json +0 -0
  197. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/source.json +0 -0
  198. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/template.json +0 -0
  199. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/ui-web.json +0 -0
  200. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/ui.json +0 -0
  201. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/validator.json +0 -0
  202. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/view.json +0 -0
  203. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/super_resolve.py +0 -0
  204. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/validation_types.py +0 -0
  205. {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/yaml_desugar.py +0 -0
  206. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/__init__.py +0 -0
  207. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/__init__.py +0 -0
  208. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
  209. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/extends/expected/Program.py +0 -0
  210. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/extends/meta.json +0 -0
  211. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +0 -0
  212. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/nested-array/expected/PostBrief.py +0 -0
  213. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/nested-array/meta.json +0 -0
  214. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/scalars/expected/Metric.py +0 -0
  215. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/scalars/expected/Report.py +0 -0
  216. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/scalars/meta.json +0 -0
  217. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/vanilla/expected/Subscriber.py +0 -0
  218. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/vanilla/meta.json +0 -0
  219. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_abstract_conformance.py +0 -0
  220. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_api_docs_builder.py +0 -0
  221. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_api_docs_paths.py +0 -0
  222. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli.py +0 -0
  223. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_config_gen.py +0 -0
  224. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_config_verify.py +0 -0
  225. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_providers.py +0 -0
  226. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_registry.py +0 -0
  227. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_staleness_nudge.py +0 -0
  228. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_verify_strict.py +0 -0
  229. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_verify_subverbs.py +0 -0
  230. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_constants_config.py +0 -0
  231. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_entity_model.py +0 -0
  232. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_enum_conformance.py +0 -0
  233. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
  234. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_extract_tier_collision.py +0 -0
  235. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_extractor_generator.py +0 -0
  236. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_filter_allowlist_generator.py +0 -0
  237. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_format.py +0 -0
  238. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
  239. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_fr010_output_codegen.py +0 -0
  240. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
  241. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_generator.py +0 -0
  242. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_generator_extension_seams.py +0 -0
  243. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_golden.py +0 -0
  244. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
  245. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_inheritance_conformance.py +0 -0
  246. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_instance_artifacts.py +0 -0
  247. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_m2m_codegen.py +0 -0
  248. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_origin_nullability.py +0 -0
  249. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_output_parser_generator.py +0 -0
  250. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_overwrite_policy.py +0 -0
  251. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_payload_vo_generator.py +0 -0
  252. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_project_config.py +0 -0
  253. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_projection_compile.py +0 -0
  254. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_render_helper_conformance.py +0 -0
  255. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_render_helper_generator.py +0 -0
  256. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_reverse_finders.py +0 -0
  257. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_router_autoset.py +0 -0
  258. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_router_generator.py +0 -0
  259. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_runner.py +0 -0
  260. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_sourceless_projection.py +0 -0
  261. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_data.py +0 -0
  262. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_generator.py +0 -0
  263. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_output_pattern.py +0 -0
  264. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_scope_helpers.py +0 -0
  265. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_scope_walk.py +0 -0
  266. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_spec.py +0 -0
  267. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_tph_codegen.py +0 -0
  268. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_trace_helper_generator.py +0 -0
  269. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_type_map.py +0 -0
  270. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_write_through.py +0 -0
  271. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/__init__.py +0 -0
  272. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/capabilities.py +0 -0
  273. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/conformance-expected-failures.json +0 -0
  274. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/conformance_adapter.py +0 -0
  275. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/corpus.py +0 -0
  276. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/expected_failures.py +0 -0
  277. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/fixture_discovery.py +0 -0
  278. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/navigator.py +0 -0
  279. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
  280. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_conformance.py +0 -0
  281. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_extract_conformance.py +0 -0
  282. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_extract_object_verdict.py +0 -0
  283. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_fr010_loader_attrs.py +0 -0
  284. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_fr011_attrs.py +0 -0
  285. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_generator_registry_conformance.py +0 -0
  286. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_object_model_conformance.py +0 -0
  287. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_provider_composition_conformance.py +0 -0
  288. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_registry_conformance.py +0 -0
  289. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_runner_hardfail.py +0 -0
  290. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_spec_metamodel_embed.py +0 -0
  291. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_strict_attr_load.py +0 -0
  292. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_template_codegen_conformance.py +0 -0
  293. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_template_generator_conformance.py +0 -0
  294. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_yaml_conformance.py +0 -0
  295. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
  296. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/__init__.py +0 -0
  297. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/api_contract_assertions.py +0 -0
  298. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/api_contract_jsonb_server.py +0 -0
  299. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/api_contract_m2m_server.py +0 -0
  300. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/api_contract_server.py +0 -0
  301. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/generated_jsonb_app.py +0 -0
  302. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/generated_m2m_app.py +0 -0
  303. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/generated_router_app.py +0 -0
  304. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/generated_tph_app.py +0 -0
  305. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/meta_ai_trace.yaml +0 -0
  306. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/normalization.py +0 -0
  307. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/query_runner.py +0 -0
  308. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/scenarios.py +0 -0
  309. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract.py +0 -0
  310. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract_generated.py +0 -0
  311. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract_jsonb.py +0 -0
  312. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract_m2m.py +0 -0
  313. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract_m2m_generated.py +0 -0
  314. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract_tph_generated.py +0 -0
  315. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_generated_router_uuid_pk.py +0 -0
  316. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_llm_call_trace.py +0 -0
  317. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_normalization.py +0 -0
  318. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_query_scenarios.py +0 -0
  319. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_runtime_return_types.py +0 -0
  320. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/loader/__init__.py +0 -0
  321. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/loader/test_enum_extends_values_conflict.py +0 -0
  322. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/loader/test_template_payload_target_210.py +0 -0
  323. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/open_closed_proof_test.py +0 -0
  324. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/__init__.py +0 -0
  325. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/__init__.py +0 -0
  326. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_coerce.py +0 -0
  327. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_extract.py +0 -0
  328. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_extract_map.py +0 -0
  329. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_json_forgiving_reader.py +0 -0
  330. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_locate.py +0 -0
  331. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_model.py +0 -0
  332. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_normalize.py +0 -0
  333. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_strip.py +0 -0
  334. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
  335. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/prompt/__init__.py +0 -0
  336. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/prompt/test_output_format_renderer.py +0 -0
  337. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_email_document.py +0 -0
  338. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_filesystem_provider.py +0 -0
  339. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_output_format_renderer_nested.py +0 -0
  340. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_output_prompt_conformance.py +0 -0
  341. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_render_conformance.py +0 -0
  342. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_render_max_chars.py +0 -0
  343. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_verify.py +0 -0
  344. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_verify_conformance.py +0 -0
  345. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/__init__.py +0 -0
  346. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_fr5c_merge_attribution.py +0 -0
  347. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_fr5d_reference_resolution.py +0 -0
  348. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_fr5e_database_source_shape.py +0 -0
  349. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_json_path.py +0 -0
  350. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_semantic_diff.py +0 -0
  351. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_source_on_node.py +0 -0
  352. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_yaml_positions.py +0 -0
  353. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/test_api_docs_accuracy.py +0 -0
  354. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/__init__.py +0 -0
  355. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_agent_context_staleness.py +0 -0
  356. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_capabilities.py +0 -0
  357. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_common_attrs.py +0 -0
  358. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_core_types.py +0 -0
  359. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_effective_package.py +0 -0
  360. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_errors.py +0 -0
  361. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_field_enum.py +0 -0
  362. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_field_map_validation.py +0 -0
  363. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
  364. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_fr016_source_name_and_kind_aliases.py +0 -0
  365. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_index_lookup.py +0 -0
  366. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_llm_recorder.py +0 -0
  367. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_loader.py +0 -0
  368. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_loader_bom.py +0 -0
  369. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_loader_class.py +0 -0
  370. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_merge.py +0 -0
  371. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_meta_attr.py +0 -0
  372. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_meta_data.py +0 -0
  373. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_meta_source.py +0 -0
  374. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_module_shortcuts.py +0 -0
  375. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_n2m_resolver.py +0 -0
  376. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_n2m_resolver_inherited.py +0 -0
  377. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_object_manager_autoset_stamping.py +0 -0
  378. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
  379. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_object_manager_write_through.py +0 -0
  380. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_one_primary_source.py +0 -0
  381. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_parser.py +0 -0
  382. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_parser_yaml.py +0 -0
  383. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_provider.py +0 -0
  384. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_provider_extension.py +0 -0
  385. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_registry.py +0 -0
  386. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_registry_completeness.py +0 -0
  387. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_registry_extend.py +0 -0
  388. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_registry_sealed.py +0 -0
  389. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_relationship_referential_actions.py +0 -0
  390. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_resolution_key.py +0 -0
  391. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
  392. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_serializer.py +0 -0
  393. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_shared_constants.py +0 -0
  394. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_smoke.py +0 -0
  395. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_source_escapes.py +0 -0
  396. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_sources.py +0 -0
  397. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_strict_child_placement.py +0 -0
  398. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_super_resolve.py +0 -0
  399. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_template_toolcall.py +0 -0
  400. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
  401. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_attr_schema.py +0 -0
  402. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_filter_values.py +0 -0
  403. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_origin_195.py +0 -0
  404. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_origin_paths.py +0 -0
  405. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_sort_field.py +0 -0
  406. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_warnings.py +0 -0
  407. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_write_coercion_arrays.py +0 -0
  408. {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_yaml_desugar.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: metaobjects
3
- Version: 0.22.0
3
+ Version: 0.23.0
4
4
  Summary: Cross-language metadata standard: declare typed entities once, generate idiomatic drift-checked code across languages — Python port.
5
5
  Project-URL: Homepage, https://metaobjects.dev
6
6
  Project-URL: Repository, https://github.com/metaobjectsdev/metaobjects
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "metaobjects"
3
- version = "0.22.0"
3
+ version = "0.23.0"
4
4
  description = "Cross-language metadata standard: declare typed entities once, generate idiomatic drift-checked code across languages — Python port."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -372,8 +372,25 @@ def _auto_gen_pk_field_names(entity: MetaObject) -> set[str]:
372
372
  return set(_primary_identity_field_names(entity))
373
373
 
374
374
 
375
+ def _assigned_pk_field_names(entity: MetaObject) -> set[str]:
376
+ """Primary-key field names the CALLER must supply on create: an ASSIGNED primary key
377
+ — a natural key or an externally-issued id, i.e. an ``identity.primary`` carrying no
378
+ ``@generation`` (or an explicit ``assigned``).
379
+
380
+ These are create-REQUIRED regardless of ``@required``: nothing else can produce the
381
+ value, so a create body omitting one can only fail at the database. Excludes the
382
+ ``increment|uuid`` keys, which ``_auto_gen_pk_field_names`` already drops from the
383
+ create shape entirely. A PK carrying a ``@default`` stays optional (the column has
384
+ that default) — handled at the call site, which knows the field.
385
+
386
+ Mirrors the TS ``assignedPkFieldNames``; gated cross-port by the
387
+ ``assigned-pk-missing`` case in ``fixtures/validation-conformance``."""
388
+ auto_gen = _auto_gen_pk_field_names(entity)
389
+ return {n for n in _primary_identity_field_names(entity) if n not in auto_gen}
390
+
391
+
375
392
  def _create_field_line(
376
- field: MetaField, imports: set[str], config: GenConfig
393
+ field: MetaField, imports: set[str], config: GenConfig, *, force_required: bool = False
377
394
  ) -> tuple[str, bool]:
378
395
  """A CREATE-model field line (FR-036): keyed by the WIRE name (``field.name``) and
379
396
  carrying the WIRE-TIER per-field constraints (#224 — includes FR-036 Pin 1
@@ -397,7 +414,9 @@ def _create_field_line(
397
414
  # ANY @default (literal or SQL-expr) or @autoSet means the DB fills it, so the wire
398
415
  # body may omit it (the FR-036 #1 regression fix).
399
416
  server_filled = default_raw is not None or is_auto_set
400
- create_required = required and not server_filled
417
+ # An assigned PK is create-REQUIRED whatever @required says (see
418
+ # _assigned_pk_field_names) — unless it is server-filled by a @default.
419
+ create_required = (required or force_required) and not server_filled
401
420
 
402
421
  parts = _constraint_parts(_validator_constraints(field, wire=True))
403
422
  uses_field = bool(parts)
@@ -534,6 +553,7 @@ class EntityModelGenerator:
534
553
  add/transform create-model lines."""
535
554
  cfg = config if config is not None else GenConfig(out_dir="")
536
555
  auto_gen_pk = _auto_gen_pk_field_names(entity)
556
+ assigned_pk = _assigned_pk_field_names(entity)
537
557
  binding = tph_subtype_binding(entity)
538
558
  disc_field = binding[0] if binding is not None else None
539
559
  uses_field = False
@@ -550,7 +570,9 @@ class EntityModelGenerator:
550
570
  continue # FR-013 — a read-only column is DB/owner-written, not create input
551
571
  if f.is_derived():
552
572
  continue # FR-024 §7 (#214) — a derived (origin.*) field is view-computed, not create input
553
- line, used = _create_field_line(f, imports, cfg)
573
+ line, used = _create_field_line(
574
+ f, imports, cfg, force_required=f.name in assigned_pk
575
+ )
554
576
  uses_field = uses_field or used
555
577
  lines.append(line)
556
578
  # FR-017 TPH: pin the inherited discriminator to this subtype's value (with a
@@ -64,13 +64,16 @@ from .meta.core.object.object_constants import (
64
64
  from .meta.core.relationship.meta_relationship import MetaRelationship
65
65
  from .meta.core.requirement.meta_requirement import MetaRequirement
66
66
  from .meta.core.requirement.requirement_constants import (
67
+ REQUIREMENT_ATTR_DISPOSITION,
67
68
  REQUIREMENT_ATTR_IMPLEMENTED_BY,
68
69
  REQUIREMENT_ATTR_LEVEL,
69
70
  REQUIREMENT_ATTR_STATEMENT,
70
71
  REQUIREMENT_ATTR_STATUS,
71
72
  REQUIREMENT_ATTR_SUPERSEDED_BY,
73
+ REQUIREMENT_ATTR_TRACKED_BY,
72
74
  REQUIREMENT_ATTR_VERIFIED_BY,
73
75
  REQUIREMENT_ATTR_VIOLATION,
76
+ REQUIREMENT_DISPOSITIONS,
74
77
  REQUIREMENT_STATUSES,
75
78
  REQUIREMENT_SUBTYPE_ARCHITECTURAL,
76
79
  REQUIREMENT_SUBTYPE_FUNCTIONAL,
@@ -589,6 +592,23 @@ _REQUIREMENT_COMMON_ATTRS = [
589
592
  required=True,
590
593
  allowed_values=REQUIREMENT_STATUSES,
591
594
  ),
595
+ # What was DECIDED about the outstanding work -- a different question from
596
+ # whether the work is done, which is what @status answers. ABSENT means
597
+ # UNDECIDED, a real state and the one a review exists to find.
598
+ AttrSchema(
599
+ name=REQUIREMENT_ATTR_DISPOSITION,
600
+ value_type=ATTR_SUBTYPE_STRING,
601
+ required=False,
602
+ allowed_values=REQUIREMENT_DISPOSITIONS,
603
+ ),
604
+ # Issue/ticket references for outstanding work. Free-form and never resolved:
605
+ # verify has no network, so unlike @verifiedBy nothing here is checked to exist.
606
+ AttrSchema(
607
+ name=REQUIREMENT_ATTR_TRACKED_BY,
608
+ value_type=ATTR_SUBTYPE_STRING,
609
+ required=False,
610
+ is_array=True,
611
+ ),
592
612
  AttrSchema(name=REQUIREMENT_ATTR_STATEMENT, value_type=ATTR_SUBTYPE_STRING, required=True),
593
613
  AttrSchema(name=REQUIREMENT_ATTR_VIOLATION, value_type=ATTR_SUBTYPE_STRING, required=True),
594
614
  AttrSchema(
@@ -597,6 +617,12 @@ _REQUIREMENT_COMMON_ATTRS = [
597
617
  required=False,
598
618
  is_array=True,
599
619
  ),
620
+ AttrSchema(
621
+ name=REQUIREMENT_ATTR_VERIFIED_BY,
622
+ value_type=ATTR_SUBTYPE_STRING,
623
+ required=False,
624
+ is_array=True,
625
+ ),
600
626
  AttrSchema(name=REQUIREMENT_ATTR_SUPERSEDED_BY, value_type=ATTR_SUBTYPE_STRING, required=False),
601
627
  ]
602
628
  core_provider.add(
@@ -605,14 +631,10 @@ core_provider.add(
605
631
  sub_type=REQUIREMENT_SUBTYPE_FUNCTIONAL,
606
632
  factory=MetaRequirement,
607
633
  attrs=[
634
+ # REQUIRED on functional: levels are the object-in-focus decomposition
635
+ # and a functional requirement always sits at one.
608
636
  AttrSchema(name=REQUIREMENT_ATTR_LEVEL, value_type=ATTR_SUBTYPE_INT, required=True),
609
637
  *_REQUIREMENT_COMMON_ATTRS,
610
- AttrSchema(
611
- name=REQUIREMENT_ATTR_VERIFIED_BY,
612
- value_type=ATTR_SUBTYPE_STRING,
613
- required=False,
614
- is_array=True,
615
- ),
616
638
  ],
617
639
  child_rules=[
618
640
  ChildRule(TYPE_ATTR, "*"),
@@ -626,8 +648,22 @@ core_provider.add(
626
648
  type=TYPE_REQUIREMENT,
627
649
  sub_type=REQUIREMENT_SUBTYPE_ARCHITECTURAL,
628
650
  factory=MetaRequirement,
629
- attrs=list(_REQUIREMENT_COMMON_ATTRS),
630
- child_rules=[ChildRule(TYPE_ATTR, "*")],
651
+ attrs=[
652
+ # OPTIONAL on architectural: absent means a flat, object-independent
653
+ # policy (the original and still the default form); present opts the
654
+ # node into a levelled tree, e.g. a quality taxonomy over the
655
+ # non-functional set. Opt-in precisely so that adding a taxonomy over
656
+ # existing flat policies cannot invalidate them.
657
+ AttrSchema(name=REQUIREMENT_ATTR_LEVEL, value_type=ATTR_SUBTYPE_INT, required=False),
658
+ *_REQUIREMENT_COMMON_ATTRS,
659
+ ],
660
+ child_rules=[
661
+ ChildRule(TYPE_ATTR, "*"),
662
+ # BOTH subtypes nest. Declaring this on `functional` only was an
663
+ # omission, not a design: it made an architectural node nestable under
664
+ # a FUNCTIONAL parent but never under another architectural one.
665
+ ChildRule(TYPE_REQUIREMENT, "*"),
666
+ ],
631
667
  )
632
668
  )
633
669
 
@@ -9,12 +9,16 @@ from __future__ import annotations
9
9
 
10
10
  from ...meta_data import MetaData
11
11
  from .requirement_constants import (
12
+ REQUIREMENT_ATTR_DISPOSITION,
12
13
  REQUIREMENT_ATTR_IMPLEMENTED_BY,
13
14
  REQUIREMENT_ATTR_LEVEL,
14
15
  REQUIREMENT_ATTR_STATUS,
16
+ REQUIREMENT_ATTR_TRACKED_BY,
15
17
  REQUIREMENT_ATTR_VERIFIED_BY,
16
18
  REQUIREMENT_LINK_FLOOR_LEVEL,
19
+ REQUIREMENT_STATUS_PLANNED,
17
20
  REQUIREMENT_STATUSES_REQUIRING_LIVE_NODES,
21
+ REQUIREMENT_STATUSES_WITH_OUTSTANDING_WORK,
18
22
  REQUIREMENT_SUBTYPE_ARCHITECTURAL,
19
23
  REQUIREMENT_SUBTYPE_FUNCTIONAL,
20
24
  )
@@ -31,8 +35,9 @@ class MetaRequirement(MetaData):
31
35
 
32
36
  def level(self) -> int | None:
33
37
  """ADR-0039: resolving. 1 solution · 2 segment · 3 service · 4 object ·
34
- 5 member. Architectural requirements carry none — they are
35
- object-independent by definition."""
38
+ 5 member. REQUIRED on functional; OPTIONAL on architectural, where absent
39
+ means a flat object-independent policy and present opts the node into a
40
+ levelled tree (e.g. a quality taxonomy over the non-functional set)."""
36
41
  v = self.get_meta_attr(REQUIREMENT_ATTR_LEVEL)
37
42
  return v if isinstance(v, int) and not isinstance(v, bool) else None
38
43
 
@@ -53,15 +58,46 @@ class MetaRequirement(MetaData):
53
58
  v = self.get_meta_attr(REQUIREMENT_ATTR_VERIFIED_BY)
54
59
  return [str(x) for x in v] if isinstance(v, list) else []
55
60
 
61
+ def disposition(self) -> str | None:
62
+ """ADR-0039: resolving. What was DECIDED about the outstanding work — a
63
+ different question from whether the work is done, which is what
64
+ ``status`` answers. ``None`` means UNDECIDED, a real state and the one a
65
+ review exists to find."""
66
+ v = self.get_meta_attr(REQUIREMENT_ATTR_DISPOSITION)
67
+ return v if isinstance(v, str) else None
68
+
69
+ def tracked_by(self) -> list[str]:
70
+ """ADR-0039: resolving. Issue/ticket references for outstanding work.
71
+ Free-form and NEVER resolved — verify has no network, so unlike
72
+ ``verified_by`` nothing here is checked to exist."""
73
+ v = self.get_meta_attr(REQUIREMENT_ATTR_TRACKED_BY)
74
+ return [str(x) for x in v] if isinstance(v, list) else []
75
+
76
+ def is_planned(self) -> bool:
77
+ """Intended but not built. Its nodes may legitimately not exist yet, and
78
+ it must NOT count toward object coverage — planning a capability cannot
79
+ be allowed to silence the warning that nothing implements it."""
80
+ return self.status() == REQUIREMENT_STATUS_PLANNED
81
+
82
+ def has_outstanding_work(self) -> bool:
83
+ """True when there is outstanding work, so a ``disposition`` says
84
+ something."""
85
+ s = self.status()
86
+ return s is not None and s in REQUIREMENT_STATUSES_WITH_OUTSTANDING_WORK
87
+
56
88
  def may_reference_model(self) -> bool:
57
89
  """True when this requirement is permitted to reference the model at all.
58
- Architectural requirements always may (their claim set is the point);
59
- functional ones only at or below the link floor, so the organisational
60
- tiers stay organisational."""
61
- if self.is_architectural():
62
- return True
90
+
91
+ An UNLEVELLED architectural requirement always may — its claim set is the
92
+ whole point, and that is the original flat form. Once a level is PRESENT
93
+ the node has opted into a tree, and the link floor applies to it exactly
94
+ as it does to a functional one, so an "ISO 25010 Security" grouping node
95
+ cannot quietly start naming entities. Levelling is the opt-in; enforcing
96
+ the floor unconditionally would have broken every existing flat policy."""
63
97
  lvl = self.level()
64
- return lvl is not None and lvl >= REQUIREMENT_LINK_FLOOR_LEVEL
98
+ if lvl is None:
99
+ return self.is_architectural()
100
+ return lvl >= REQUIREMENT_LINK_FLOOR_LEVEL
65
101
 
66
102
  def requires_live_nodes(self) -> bool:
67
103
  """True when a dangling ``@implementedBy`` is an ERROR rather than
@@ -26,6 +26,8 @@ REQUIREMENT_SUBTYPES = (
26
26
  #: 1 solution · 2 segment (app/library) · 3 service · 4 object · 5 member.
27
27
  REQUIREMENT_ATTR_LEVEL = "level"
28
28
  REQUIREMENT_ATTR_STATUS = "status"
29
+ REQUIREMENT_ATTR_DISPOSITION = "disposition"
30
+ REQUIREMENT_ATTR_TRACKED_BY = "trackedBy"
29
31
  REQUIREMENT_ATTR_STATEMENT = "statement"
30
32
  REQUIREMENT_ATTR_VIOLATION = "violation"
31
33
  REQUIREMENT_ATTR_IMPLEMENTED_BY = "implementedBy"
@@ -35,12 +37,17 @@ REQUIREMENT_ATTR_SUPERSEDED_BY = "supersededBy"
35
37
  # ---------------------------------------------------------------------------
36
38
  # Status — a closed enum, enforced by the registry via allowed_values.
37
39
  # ---------------------------------------------------------------------------
40
+ # Intended but not built. Its references may legitimately dangle, and it never
41
+ # contributes to object coverage -- planning a capability must not silence the
42
+ # warning that nothing implements it.
43
+ REQUIREMENT_STATUS_PLANNED = "planned"
38
44
  REQUIREMENT_STATUS_LIVE = "live"
39
45
  REQUIREMENT_STATUS_PARTIAL = "partial"
40
46
  REQUIREMENT_STATUS_ABANDONED = "abandoned"
41
47
  REQUIREMENT_STATUS_SUPERSEDED = "superseded"
42
48
 
43
49
  REQUIREMENT_STATUSES = (
50
+ REQUIREMENT_STATUS_PLANNED,
44
51
  REQUIREMENT_STATUS_LIVE,
45
52
  REQUIREMENT_STATUS_PARTIAL,
46
53
  REQUIREMENT_STATUS_ABANDONED,
@@ -59,6 +66,30 @@ REQUIREMENT_STATUSES_REQUIRING_LIVE_NODES = (
59
66
  # ---------------------------------------------------------------------------
60
67
  # Levels — organisational above the link floor, model-referencing at or below.
61
68
  # ---------------------------------------------------------------------------
69
+ # Statuses with outstanding work, so a @disposition is meaningful on them. On any
70
+ # other status the decision IS the status, and recording a second one can only
71
+ # agree with it or contradict it.
72
+ REQUIREMENT_STATUSES_WITH_OUTSTANDING_WORK = (
73
+ REQUIREMENT_STATUS_PLANNED,
74
+ REQUIREMENT_STATUS_PARTIAL,
75
+ )
76
+
77
+ # ---------------------------------------------------------------------------
78
+ # Disposition -- what was DECIDED about the outstanding work. Orthogonal to
79
+ # status, which says whether the work is done. ABSENT means UNDECIDED, and that
80
+ # is the state a review exists to find; collapsing it into the status enum would
81
+ # make "there is a gap" and "we chose to live with it" the same fact.
82
+ # ---------------------------------------------------------------------------
83
+
84
+ REQUIREMENT_DISPOSITION_ACCEPTED = "accepted"
85
+ REQUIREMENT_DISPOSITION_DEFERRED = "deferred"
86
+
87
+ # Declaration order is contractual -- see REQUIREMENT_STATUSES.
88
+ REQUIREMENT_DISPOSITIONS = (
89
+ REQUIREMENT_DISPOSITION_ACCEPTED,
90
+ REQUIREMENT_DISPOSITION_DEFERRED,
91
+ )
92
+
62
93
  REQUIREMENT_LEVEL_SOLUTION = 1
63
94
  REQUIREMENT_LEVEL_SEGMENT = 2
64
95
  REQUIREMENT_LEVEL_SERVICE = 3
@@ -12,7 +12,7 @@
12
12
  "name": "description",
13
13
  "min": 0,
14
14
  "max": 1,
15
- "description": "Free-form user-facing prose. Markdown allowed, multi-line via YAML '|' block scalar. Flows into doc-gen surfaces (JSDoc / XML-doc / Postgres COMMENT / Mermaid prose)."
15
+ "description": "What this element IS and COVERS, written for someone using it. Markdown allowed, multi-line via YAML '|' block scalar. Flows into doc-gen surfaces (JSDoc / XML-doc / Postgres COMMENT / Mermaid prose). State scope and boundary — what it covers, what it deliberately does NOT, and which sibling owns the rest — all of which is derivable from the model itself. Anything you had to read the implementation to learn belongs in @notes, not here."
16
16
  },
17
17
  {
18
18
  "type": "attr",
@@ -20,7 +20,7 @@
20
20
  "name": "summary",
21
21
  "min": 0,
22
22
  "max": 1,
23
- "description": "Short single-line tagline (OpenAPI `summary` pattern) — used in index tables, sidebar previews, and AI prompts where the full @description is too long. Optional supplement to @description; when @summary is unset, doc surfaces typically fall back to the first sentence of @description."
23
+ "description": "Short single-line SENTENCE (OpenAPI `summary` pattern) — used in index tables, sidebar previews, and AI prompts where the full @description is too long. Distinct from @title, which is a noun label rather than a sentence. When @summary is unset, doc surfaces typically fall back to the first sentence of @description."
24
24
  },
25
25
  {
26
26
  "type": "attr",
@@ -28,7 +28,7 @@
28
28
  "name": "title",
29
29
  "min": 0,
30
30
  "max": 1,
31
- "description": "Short single-line human label (e.g. 'Email' for a `field.string email`). Optional supplement to description."
31
+ "description": "Short single-line human label — a NOUN PHRASE naming the element (e.g. 'Email' for a `field.string email`), never a sentence. What a tab, an index row or a sidebar shows when the name is an identifier rather than a label. See @summary for the one-line sentence form."
32
32
  },
33
33
  {
34
34
  "type": "attr",
@@ -36,7 +36,7 @@
36
36
  "name": "notes",
37
37
  "min": 0,
38
38
  "max": 1,
39
- "description": "Internal-only rationale. Stays in metadata; never emitted to user-facing docs."
39
+ "description": "Internal-only rationale, never emitted to user-facing docs — the slot for what you had to look OUTSIDE the model to learn: evidence, measurements, citations, the control that proved an absence was real, and what breaks if this changes. It is NOT a longer @description, and restating the description here is the failure mode this slot invites. Mechanical test: a sentence belongs in @notes exactly when it would have to change because the IMPLEMENTATION changed while the model did not."
40
40
  },
41
41
  {
42
42
  "type": "attr",
@@ -0,0 +1,209 @@
1
+ {
2
+ "provider": "metaobjects-core-types",
3
+ "types": [
4
+ {
5
+ "type": "requirement",
6
+ "subType": "functional",
7
+ "description": "What the product does for a user, stated as one violable claim. Its check is EXISTENCE: it fails when nothing implements it. Hierarchy is nesting — an L1 solution contains its L2 segments, which contain L3 services, and so on down to the levels that reference the model.",
8
+ "whenToUse": "Something exists because someone asked for it. L1-L3 are levels of ABSTRACTION AND OWNERSHIP in the problem domain — whose need is this, and at what altitude — and are never a directory, package, deployable or module. Binding to technical constructs happens only at L4 (an object) and L5 (a member), which is the allocation step. Test every node: if a refactor that changes no behaviour would force it to move, its level is wrong.",
9
+ "children": [
10
+ {
11
+ "type": "attr",
12
+ "subType": "int",
13
+ "name": "level",
14
+ "min": 1,
15
+ "max": 1,
16
+ "description": "1 solution, 2 segment, 3 service, 4 object, 5 member. L1-L3 are levels of abstraction and ownership in the problem domain, NOT of code structure. Nesting depth must agree with it; skipping a level is legal, going back up is not."
17
+ },
18
+ {
19
+ "type": "attr",
20
+ "subType": "string",
21
+ "name": "status",
22
+ "min": 1,
23
+ "max": 1,
24
+ "allowedValues": [
25
+ "planned",
26
+ "live",
27
+ "partial",
28
+ "abandoned",
29
+ "superseded"
30
+ ],
31
+ "description": "planned intended but not built yet; live implemented and in use; partial implemented with known gaps; abandoned built then deliberately retired; superseded replaced by a different mechanism. A dangling @implementedBy is an ERROR on live/partial (the model moved, the requirement is stale) and ALLOWED on planned/abandoned/superseded — on planned the nodes do not exist YET, on the other two they are meant to be gone, and that is the entry doing its job. A planned requirement also never contributes to object coverage: planning a capability must not silence the warning that nothing implements it."
32
+ },
33
+ {
34
+ "type": "attr",
35
+ "subType": "string",
36
+ "name": "disposition",
37
+ "min": 0,
38
+ "max": 1,
39
+ "allowedValues": [
40
+ "accepted",
41
+ "deferred"
42
+ ],
43
+ "description": "What has been DECIDED about outstanding work — a different question from whether the work is done, which is what @status answers. accepted: the gap is understood and deliberately not being closed. deferred: it will be closed, but not now. ABSENT MEANS UNDECIDED, which is a real and useful state — it is what an unreviewed gap looks like, and it is the one a review should be able to find. Meaningful on planned and partial only; on a status with no outstanding work it is a WARNING. Deliberately NOT a workflow vocabulary: which sprint, who owns it and whether it is in progress belong in the tracker named by @trackedBy, because two systems holding that answer will drift and only one of them is refreshed daily."
44
+ },
45
+ {
46
+ "type": "attr",
47
+ "subType": "string",
48
+ "name": "trackedBy",
49
+ "isArray": true,
50
+ "min": 0,
51
+ "max": 1,
52
+ "description": "Issue or ticket references for outstanding work — a URL, an owner/repo#123 shorthand, or a tracker key. Free-form and NOT resolved by verify, which does not reach the network; unlike @verifiedBy, nothing here is checked to exist. Its job is to stop a deferred gap becoming invisible, so verify warns when a deferred requirement names no ticket. Also the right place to link the ticket that a planned requirement will be built under."
53
+ },
54
+ {
55
+ "type": "attr",
56
+ "subType": "string",
57
+ "name": "statement",
58
+ "min": 1,
59
+ "max": 1,
60
+ "description": "What the capability is, in one sentence."
61
+ },
62
+ {
63
+ "type": "attr",
64
+ "subType": "string",
65
+ "name": "violation",
66
+ "min": 1,
67
+ "max": 1,
68
+ "description": "What breaking it looks like, in one sentence. A requirement MUST be violable: 'every entity has a uuid primary key' is (point at one with a composite string key); 'things are persisted' is not, and is a description rather than a requirement."
69
+ },
70
+ {
71
+ "type": "attr",
72
+ "subType": "string",
73
+ "name": "implementedBy",
74
+ "isArray": true,
75
+ "min": 0,
76
+ "max": 1,
77
+ "description": "FQN references to the model nodes realising this requirement. Legal on level 4 (an object) and level 5 (a field, view or identity) only; an organisational level carrying it is ERR_REQUIREMENT_LINK_ABOVE_FLOOR. Many-to-many by construction — several requirements may name the same node."
78
+ },
79
+ {
80
+ "type": "attr",
81
+ "subType": "string",
82
+ "name": "verifiedBy",
83
+ "isArray": true,
84
+ "min": 0,
85
+ "max": 1,
86
+ "description": "Names of the tests proving the behaviour. verify checks each exists and is not skipped; it never runs them."
87
+ },
88
+ {
89
+ "type": "attr",
90
+ "subType": "string",
91
+ "name": "supersededBy",
92
+ "min": 0,
93
+ "max": 1,
94
+ "description": "The requirement that replaced this one. Expected on status=superseded."
95
+ },
96
+ {
97
+ "type": "requirement",
98
+ "subType": "*",
99
+ "name": "*",
100
+ "min": 0,
101
+ "max": null,
102
+ "description": "Nested child requirements. Hierarchy IS nesting — an L1 solution contains its L2 segments, which contain L3 services — so regrouping moves a node rather than editing a parent string, and a requirement is addressable by the same dotted child-name path as every other node."
103
+ }
104
+ ]
105
+ },
106
+ {
107
+ "type": "requirement",
108
+ "subType": "architectural",
109
+ "description": "How the system is built, applied uniformly across the model. Its check is UNIVERSALITY: it fails when something VIOLATES it, which is the opposite polarity to a functional requirement. Flat by default and object-independent; it may optionally sit in a levelled tree when a quality taxonomy is being used to organise non-functional requirements.",
110
+ "whenToUse": "Something exists because every entity here looks like this — a uuid primary key, an @autoSet createdAt, a change-attribution column, tenant scoping. The discriminator is mechanical: did this exist because someone asked for something, or because it is the architecture? For a non-functional tree, an established quality taxonomy makes a good fixed upper structure (e.g. an ISO/IEC 25010 characteristic at L1, its sub-characteristic or a control-catalogue category at L2), with the model-binding claims at L4 and L5 as usual.",
111
+ "children": [
112
+ {
113
+ "type": "attr",
114
+ "subType": "int",
115
+ "name": "level",
116
+ "min": 0,
117
+ "max": 1,
118
+ "description": "OPTIONAL here, unlike on a functional requirement where it is required. ABSENT means a flat, object-independent policy that may reference the model directly — the original and still the default form. PRESENT means this node sits in a levelled tree, and then the same rules as functional apply: nesting must agree with the level, and only L4/L5 may carry @implementedBy. Levelling is opt-in so that adding a taxonomy on top of existing flat policies does not invalidate them."
119
+ },
120
+ {
121
+ "type": "attr",
122
+ "subType": "string",
123
+ "name": "status",
124
+ "min": 1,
125
+ "max": 1,
126
+ "allowedValues": [
127
+ "planned",
128
+ "live",
129
+ "partial",
130
+ "abandoned",
131
+ "superseded"
132
+ ],
133
+ "description": "As on requirement.functional. A live or partial architectural requirement claimed by NOTHING is an error: a policy declared and applied to nothing. A planned one is exempt from that check — it is not applied yet by definition."
134
+ },
135
+ {
136
+ "type": "attr",
137
+ "subType": "string",
138
+ "name": "disposition",
139
+ "min": 0,
140
+ "max": 1,
141
+ "allowedValues": [
142
+ "accepted",
143
+ "deferred"
144
+ ],
145
+ "description": "As on requirement.functional. On an architectural requirement, accepted is the common and important case: a policy that is genuinely not universal, where the exceptions are known and tolerated, is more honest as partial+accepted than as a live claim nobody audits."
146
+ },
147
+ {
148
+ "type": "attr",
149
+ "subType": "string",
150
+ "name": "trackedBy",
151
+ "isArray": true,
152
+ "min": 0,
153
+ "max": 1,
154
+ "description": "As on requirement.functional. Issue or ticket references for outstanding work; free-form, not resolved."
155
+ },
156
+ {
157
+ "type": "attr",
158
+ "subType": "string",
159
+ "name": "statement",
160
+ "min": 1,
161
+ "max": 1,
162
+ "description": "The policy, in one sentence."
163
+ },
164
+ {
165
+ "type": "attr",
166
+ "subType": "string",
167
+ "name": "violation",
168
+ "min": 1,
169
+ "max": 1,
170
+ "description": "What breaking it looks like — the node that would contradict it. This is what makes universality checkable."
171
+ },
172
+ {
173
+ "type": "attr",
174
+ "subType": "string",
175
+ "name": "implementedBy",
176
+ "isArray": true,
177
+ "min": 0,
178
+ "max": 1,
179
+ "description": "FQN references to the nodes applying this policy. High fan-out is normal and expected: one uuid-primary-key requirement is claimed by every entity."
180
+ },
181
+ {
182
+ "type": "attr",
183
+ "subType": "string",
184
+ "name": "verifiedBy",
185
+ "isArray": true,
186
+ "min": 0,
187
+ "max": 1,
188
+ "description": "Names of the tests proving the policy holds. verify checks each exists and is not skipped; it never runs them."
189
+ },
190
+ {
191
+ "type": "attr",
192
+ "subType": "string",
193
+ "name": "supersededBy",
194
+ "min": 0,
195
+ "max": 1,
196
+ "description": "The requirement that replaced this one. Expected on status=superseded."
197
+ },
198
+ {
199
+ "type": "requirement",
200
+ "subType": "*",
201
+ "name": "*",
202
+ "min": 0,
203
+ "max": null,
204
+ "description": "Nested child requirements. Present so a non-functional tree can be organised by a quality taxonomy the same way a functional tree is organised by capability — the absence of this rule, while requirement.functional had it, is what previously made an architectural node nestable UNDER a functional one but never under another architectural one."
205
+ }
206
+ ]
207
+ }
208
+ ]
209
+ }
@@ -38,23 +38,29 @@ def _corpus_dir() -> Path:
38
38
  return repo_root / "fixtures" / "validation-conformance"
39
39
 
40
40
 
41
- def _load_account_entity() -> MetaObject:
41
+ DEFAULT_ENTITY = "Account"
42
+
43
+
44
+ def _load_entity(name: str) -> MetaObject:
42
45
  meta = (_corpus_dir() / "meta.json").read_text()
43
46
  result = MetaDataLoader.from_string(meta)
44
47
  assert not result.errors, [str(e) for e in result.errors]
45
48
  for child in result.root.children():
46
- if child.type == TYPE_OBJECT and getattr(child, "name", None) == "Account":
49
+ if child.type == TYPE_OBJECT and getattr(child, "name", None) == name:
47
50
  assert isinstance(child, MetaObject)
48
51
  return child
49
- raise AssertionError("Account entity not found in corpus meta.json")
52
+ raise AssertionError(f"{name} entity not found in corpus meta.json")
53
+
50
54
 
55
+ def _build_generated_model(entity_name: str = DEFAULT_ENTITY) -> type[BaseModel]:
56
+ """Generate the ``<Entity>Create`` Pydantic wire-validation model source and exec it
57
+ into a module namespace. #224 — the CREATE model (the generated input-validation
58
+ artifact), not the plain read model: FR-036 Pin 1 lives on the wire tier only.
51
59
 
52
- def _build_generated_model() -> type[BaseModel]:
53
- """Generate the Account Pydantic wire-validation model source and exec it into a
54
- module namespace. #224 — ``AccountCreate`` (the generated input-validation
55
- artifact), not the plain ``Account`` read model: FR-036 Pin 1 lives on the wire
56
- tier only."""
57
- source = render_entity_model(_load_account_entity())
60
+ A case may name a different corpus entity (``Ledger`` — an ASSIGNED primary key,
61
+ a shape ``Account``'s ``@generation``-backed key cannot express).
62
+ """
63
+ source = render_entity_model(_load_entity(entity_name))
58
64
  # Import the generated source as a REAL module rather than exec'ing it into a
59
65
  # bare dict: under ``from __future__ import annotations`` Pydantic resolves
60
66
  # type annotations lazily via the class's module globals, so a non-builtin
@@ -63,14 +69,15 @@ def _build_generated_model() -> type[BaseModel]:
63
69
  # exec namespace has no ``__name__`` (forward refs fall back to builtins and
64
70
  # fail — #234); a proper module import mirrors the TS runner's temp-module.
65
71
  tmp_dir = tempfile.mkdtemp()
66
- mod_path = Path(tmp_dir) / "generated_account.py"
72
+ mod_name = f"generated_{entity_name.lower()}"
73
+ mod_path = Path(tmp_dir) / f"{mod_name}.py"
67
74
  mod_path.write_text(source)
68
- spec = importlib.util.spec_from_file_location("generated_account", mod_path)
75
+ spec = importlib.util.spec_from_file_location(mod_name, mod_path)
69
76
  assert spec and spec.loader
70
77
  module = importlib.util.module_from_spec(spec)
71
- sys.modules["generated_account"] = module
78
+ sys.modules[mod_name] = module
72
79
  spec.loader.exec_module(module)
73
- model = module.AccountCreate
80
+ model = getattr(module, f"{entity_name}Create")
74
81
  assert isinstance(model, type) and issubclass(model, BaseModel)
75
82
  return model
76
83
 
@@ -81,7 +88,7 @@ def _load_cases() -> list[dict]:
81
88
 
82
89
  @pytest.mark.parametrize("case", _load_cases(), ids=lambda c: c["name"])
83
90
  def test_validation_conformance(case: dict) -> None:
84
- model = _build_generated_model()
91
+ model = _build_generated_model(case.get("entity", DEFAULT_ENTITY))
85
92
  try:
86
93
  model(**case["payload"])
87
94
  valid = True