metaobjects 0.22.1__tar.gz → 0.23.1__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 (409) hide show
  1. {metaobjects-0.22.1 → metaobjects-0.23.1}/PKG-INFO +1 -1
  2. {metaobjects-0.22.1 → metaobjects-0.23.1}/pyproject.toml +1 -1
  3. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/fr019_shared_enum.py +15 -6
  4. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/core_types.py +44 -8
  5. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/requirement/meta_requirement.py +46 -9
  6. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/requirement/requirement_constants.py +31 -0
  7. metaobjects-0.23.1/src/metaobjects/render/payload_accessors.py +134 -0
  8. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/renderer.py +5 -1
  9. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/verify.py +11 -1
  10. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/documentation.json +4 -4
  11. metaobjects-0.23.1/src/metaobjects/spec_metamodel/requirement.json +209 -0
  12. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/postgres_container.py +84 -14
  13. {metaobjects-0.22.1 → metaobjects-0.23.1}/uv.lock +1 -1
  14. metaobjects-0.22.1/src/metaobjects/spec_metamodel/requirement.json +0 -140
  15. {metaobjects-0.22.1 → metaobjects-0.23.1}/.gitignore +0 -0
  16. {metaobjects-0.22.1 → metaobjects-0.23.1}/LICENSE +0 -0
  17. {metaobjects-0.22.1 → metaobjects-0.23.1}/README.md +0 -0
  18. {metaobjects-0.22.1 → metaobjects-0.23.1}/hatch_build.py +0 -0
  19. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/__init__.py +0 -0
  20. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/agent_context/__init__.py +0 -0
  21. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/agent_context/scaffold.py +0 -0
  22. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/apidocs/__init__.py +0 -0
  23. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/apidocs/api_model.py +0 -0
  24. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/apidocs/builder.py +0 -0
  25. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/apidocs/naming.py +0 -0
  26. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/apidocs/paths.py +0 -0
  27. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/apidocs/renderer.py +0 -0
  28. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/attr_class_map.py +0 -0
  29. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/cli.py +0 -0
  30. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/KNOWN_GAPS.md +0 -0
  31. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/__init__.py +0 -0
  32. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/collision_names.py +0 -0
  33. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/config.py +0 -0
  34. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/constants.py +0 -0
  35. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
  36. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
  37. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/format.py +0 -0
  38. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
  39. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generator.py +0 -0
  40. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generator_registry.py +0 -0
  41. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/__init__.py +0 -0
  42. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/entity_model.py +0 -0
  43. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
  44. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +0 -0
  45. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/m2m_codegen.py +0 -0
  46. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
  47. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
  48. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/payload_vo_generator.py +0 -0
  49. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
  50. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/router_generator.py +0 -0
  51. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/template_generator.py +0 -0
  52. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
  53. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
  54. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/instance_artifacts.py +0 -0
  55. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/metaobjects-config.schema.json +0 -0
  56. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
  57. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/overwrite_policy.py +0 -0
  58. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/project_config.py +0 -0
  59. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/runner.py +0 -0
  60. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/runtime/__init__.py +0 -0
  61. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
  62. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
  63. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
  64. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
  65. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
  66. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/codegen/type_map.py +0 -0
  67. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/datatype.py +0 -0
  68. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/documentation/__init__.py +0 -0
  69. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/documentation/doc_constants.py +0 -0
  70. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/documentation/doc_provider.py +0 -0
  71. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/documentation/doc_schema.py +0 -0
  72. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/errors.py +0 -0
  73. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/__init__.py +0 -0
  74. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/merge.py +0 -0
  75. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/meta_data_loader.py +0 -0
  76. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/registered_validation.py +0 -0
  77. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/sources/__init__.py +0 -0
  78. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/sources/directory_source.py +0 -0
  79. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/sources/file_source.py +0 -0
  80. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
  81. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/sources/uri_source.py +0 -0
  82. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/validate_discriminator.py +0 -0
  83. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/validate_enum_normalize_ambiguity.py +0 -0
  84. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/validate_field_readonly.py +0 -0
  85. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/validate_source_escapes.py +0 -0
  86. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
  87. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
  88. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/loader/validation_passes.py +0 -0
  89. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/__init__.py +0 -0
  90. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/__init__.py +0 -0
  91. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/attr/__init__.py +0 -0
  92. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/attr/attr_constants.py +0 -0
  93. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/attr/meta_attr.py +0 -0
  94. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/field/__init__.py +0 -0
  95. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/field/field_constants.py +0 -0
  96. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/field/meta_field.py +0 -0
  97. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/identity/__init__.py +0 -0
  98. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
  99. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
  100. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/index/__init__.py +0 -0
  101. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/index/index_constants.py +0 -0
  102. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/index/meta_index.py +0 -0
  103. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/object/__init__.py +0 -0
  104. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/object/meta_object.py +0 -0
  105. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
  106. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
  107. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/object/object_constants.py +0 -0
  108. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/object/object_extract.py +0 -0
  109. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/object/value_object.py +0 -0
  110. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
  111. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
  112. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
  113. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
  114. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/requirement/__init__.py +0 -0
  115. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/validator/__init__.py +0 -0
  116. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
  117. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/meta_data.py +0 -0
  118. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/meta_root.py +0 -0
  119. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/persistence/__init__.py +0 -0
  120. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
  121. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
  122. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
  123. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
  124. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
  125. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -0
  126. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
  127. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/persistence/source/meta_source.py +0 -0
  128. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/persistence/source/source_constants.py +0 -0
  129. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/presentation/__init__.py +0 -0
  130. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
  131. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
  132. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
  133. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
  134. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
  135. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
  136. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
  137. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
  138. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/provider_extends.py +0 -0
  139. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/template/__init__.py +0 -0
  140. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/template/meta_template.py +0 -0
  141. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/template/prompt_provider.py +0 -0
  142. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/meta/template/template_constants.py +0 -0
  143. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/naming_refs.py +0 -0
  144. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/parser.py +0 -0
  145. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/parser_yaml.py +0 -0
  146. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/provider.py +0 -0
  147. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/py.typed +0 -0
  148. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/registry.py +0 -0
  149. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/registry_manifest.py +0 -0
  150. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/__init__.py +0 -0
  151. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/email_document.py +0 -0
  152. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/escapers.py +0 -0
  153. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
  154. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/__init__.py +0 -0
  155. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/coerce.py +0 -0
  156. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/extract.py +0 -0
  157. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/extract_map.py +0 -0
  158. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
  159. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/locate.py +0 -0
  160. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/normalize.py +0 -0
  161. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/strip.py +0 -0
  162. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/types.py +0 -0
  163. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/extract/xml_forgiving_reader.py +0 -0
  164. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/filesystem_provider.py +0 -0
  165. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/prompt/__init__.py +0 -0
  166. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
  167. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
  168. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/prompt/prompt_field.py +0 -0
  169. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
  170. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/render/prompt/prompt_style.py +0 -0
  171. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/runtime/__init__.py +0 -0
  172. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/runtime/llm_recorder.py +0 -0
  173. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/runtime/n2m_resolver.py +0 -0
  174. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/runtime/object_manager.py +0 -0
  175. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/runtime/tph.py +0 -0
  176. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/serializer_json.py +0 -0
  177. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/shared/__init__.py +0 -0
  178. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/shared/base_types.py +0 -0
  179. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/shared/separators.py +0 -0
  180. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/shared/structural.py +0 -0
  181. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/source/__init__.py +0 -0
  182. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/source/error_source.py +0 -0
  183. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/source/json_path.py +0 -0
  184. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/source/semantic_diff.py +0 -0
  185. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/source/yaml_positions.py +0 -0
  186. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/__init__.py +0 -0
  187. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/attr.json +0 -0
  188. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/db.json +0 -0
  189. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/field.json +0 -0
  190. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/identity.json +0 -0
  191. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/index.json +0 -0
  192. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/layout.json +0 -0
  193. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/object.json +0 -0
  194. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/origin.json +0 -0
  195. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/prompt.json +0 -0
  196. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/relationship.json +0 -0
  197. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/source.json +0 -0
  198. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/template.json +0 -0
  199. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/ui-web.json +0 -0
  200. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/ui.json +0 -0
  201. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/validator.json +0 -0
  202. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/spec_metamodel/view.json +0 -0
  203. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/super_resolve.py +0 -0
  204. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/validation_types.py +0 -0
  205. {metaobjects-0.22.1 → metaobjects-0.23.1}/src/metaobjects/yaml_desugar.py +0 -0
  206. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/__init__.py +0 -0
  207. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/__init__.py +0 -0
  208. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
  209. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/extends/expected/Program.py +0 -0
  210. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/extends/meta.json +0 -0
  211. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +0 -0
  212. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/nested-array/expected/PostBrief.py +0 -0
  213. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/nested-array/meta.json +0 -0
  214. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/scalars/expected/Metric.py +0 -0
  215. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/scalars/expected/Report.py +0 -0
  216. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/scalars/meta.json +0 -0
  217. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/vanilla/expected/Subscriber.py +0 -0
  218. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/golden/vanilla/meta.json +0 -0
  219. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_abstract_conformance.py +0 -0
  220. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_api_docs_builder.py +0 -0
  221. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_api_docs_paths.py +0 -0
  222. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_cli.py +0 -0
  223. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_cli_config_gen.py +0 -0
  224. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_cli_config_verify.py +0 -0
  225. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_cli_providers.py +0 -0
  226. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_cli_registry.py +0 -0
  227. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_cli_staleness_nudge.py +0 -0
  228. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_cli_verify_strict.py +0 -0
  229. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_cli_verify_subverbs.py +0 -0
  230. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_constants_config.py +0 -0
  231. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_entity_model.py +0 -0
  232. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_enum_conformance.py +0 -0
  233. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
  234. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_extract_tier_collision.py +0 -0
  235. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_extractor_generator.py +0 -0
  236. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_filter_allowlist_generator.py +0 -0
  237. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_format.py +0 -0
  238. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
  239. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_fr010_output_codegen.py +0 -0
  240. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
  241. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_generator.py +0 -0
  242. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_generator_extension_seams.py +0 -0
  243. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_golden.py +0 -0
  244. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
  245. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_inheritance_conformance.py +0 -0
  246. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_instance_artifacts.py +0 -0
  247. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_m2m_codegen.py +0 -0
  248. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_origin_nullability.py +0 -0
  249. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_output_parser_generator.py +0 -0
  250. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_overwrite_policy.py +0 -0
  251. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_payload_vo_generator.py +0 -0
  252. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_project_config.py +0 -0
  253. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_projection_compile.py +0 -0
  254. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_render_helper_conformance.py +0 -0
  255. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_render_helper_generator.py +0 -0
  256. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_reverse_finders.py +0 -0
  257. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_router_autoset.py +0 -0
  258. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_router_generator.py +0 -0
  259. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_runner.py +0 -0
  260. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_sourceless_projection.py +0 -0
  261. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_template_data.py +0 -0
  262. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_template_generator.py +0 -0
  263. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_template_output_pattern.py +0 -0
  264. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_template_scope_helpers.py +0 -0
  265. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_template_scope_walk.py +0 -0
  266. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_template_spec.py +0 -0
  267. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_tph_codegen.py +0 -0
  268. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_trace_helper_generator.py +0 -0
  269. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_type_map.py +0 -0
  270. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_validation_conformance.py +0 -0
  271. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/codegen/test_write_through.py +0 -0
  272. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/__init__.py +0 -0
  273. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/capabilities.py +0 -0
  274. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/conformance-expected-failures.json +0 -0
  275. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/conformance_adapter.py +0 -0
  276. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/corpus.py +0 -0
  277. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/expected_failures.py +0 -0
  278. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/fixture_discovery.py +0 -0
  279. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/navigator.py +0 -0
  280. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
  281. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_conformance.py +0 -0
  282. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_extract_conformance.py +0 -0
  283. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_extract_object_verdict.py +0 -0
  284. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_fr010_loader_attrs.py +0 -0
  285. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_fr011_attrs.py +0 -0
  286. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_generator_registry_conformance.py +0 -0
  287. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_object_model_conformance.py +0 -0
  288. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_provider_composition_conformance.py +0 -0
  289. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_registry_conformance.py +0 -0
  290. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_runner_hardfail.py +0 -0
  291. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_spec_metamodel_embed.py +0 -0
  292. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_strict_attr_load.py +0 -0
  293. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_template_codegen_conformance.py +0 -0
  294. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_template_generator_conformance.py +0 -0
  295. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/test_yaml_conformance.py +0 -0
  296. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
  297. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/__init__.py +0 -0
  298. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/api_contract_assertions.py +0 -0
  299. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/api_contract_jsonb_server.py +0 -0
  300. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/api_contract_m2m_server.py +0 -0
  301. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/api_contract_server.py +0 -0
  302. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/generated_jsonb_app.py +0 -0
  303. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/generated_m2m_app.py +0 -0
  304. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/generated_router_app.py +0 -0
  305. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/generated_tph_app.py +0 -0
  306. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/meta_ai_trace.yaml +0 -0
  307. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/normalization.py +0 -0
  308. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/query_runner.py +0 -0
  309. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/scenarios.py +0 -0
  310. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_api_contract.py +0 -0
  311. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_api_contract_generated.py +0 -0
  312. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_api_contract_jsonb.py +0 -0
  313. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_api_contract_m2m.py +0 -0
  314. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_api_contract_m2m_generated.py +0 -0
  315. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_api_contract_tph_generated.py +0 -0
  316. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_generated_router_uuid_pk.py +0 -0
  317. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_llm_call_trace.py +0 -0
  318. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_normalization.py +0 -0
  319. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_query_scenarios.py +0 -0
  320. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/integration/test_runtime_return_types.py +0 -0
  321. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/loader/__init__.py +0 -0
  322. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/loader/test_enum_extends_values_conflict.py +0 -0
  323. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/loader/test_template_payload_target_210.py +0 -0
  324. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/open_closed_proof_test.py +0 -0
  325. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/__init__.py +0 -0
  326. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/extract/__init__.py +0 -0
  327. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/extract/test_coerce.py +0 -0
  328. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/extract/test_extract.py +0 -0
  329. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/extract/test_extract_map.py +0 -0
  330. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/extract/test_json_forgiving_reader.py +0 -0
  331. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/extract/test_locate.py +0 -0
  332. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/extract/test_model.py +0 -0
  333. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/extract/test_normalize.py +0 -0
  334. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/extract/test_strip.py +0 -0
  335. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
  336. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/prompt/__init__.py +0 -0
  337. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/prompt/test_output_format_renderer.py +0 -0
  338. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/test_email_document.py +0 -0
  339. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/test_filesystem_provider.py +0 -0
  340. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/test_output_format_renderer_nested.py +0 -0
  341. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/test_output_prompt_conformance.py +0 -0
  342. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/test_render_conformance.py +0 -0
  343. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/test_render_max_chars.py +0 -0
  344. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/test_verify.py +0 -0
  345. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/render/test_verify_conformance.py +0 -0
  346. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/source/__init__.py +0 -0
  347. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/source/test_fr5c_merge_attribution.py +0 -0
  348. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/source/test_fr5d_reference_resolution.py +0 -0
  349. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/source/test_fr5e_database_source_shape.py +0 -0
  350. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/source/test_json_path.py +0 -0
  351. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/source/test_semantic_diff.py +0 -0
  352. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/source/test_source_on_node.py +0 -0
  353. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/source/test_yaml_positions.py +0 -0
  354. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/test_api_docs_accuracy.py +0 -0
  355. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/__init__.py +0 -0
  356. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_agent_context_staleness.py +0 -0
  357. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_capabilities.py +0 -0
  358. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_common_attrs.py +0 -0
  359. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_core_types.py +0 -0
  360. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_effective_package.py +0 -0
  361. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_errors.py +0 -0
  362. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_field_enum.py +0 -0
  363. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_field_map_validation.py +0 -0
  364. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
  365. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_fr016_source_name_and_kind_aliases.py +0 -0
  366. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_index_lookup.py +0 -0
  367. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_llm_recorder.py +0 -0
  368. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_loader.py +0 -0
  369. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_loader_bom.py +0 -0
  370. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_loader_class.py +0 -0
  371. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_merge.py +0 -0
  372. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_meta_attr.py +0 -0
  373. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_meta_data.py +0 -0
  374. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_meta_source.py +0 -0
  375. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_module_shortcuts.py +0 -0
  376. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_n2m_resolver.py +0 -0
  377. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_n2m_resolver_inherited.py +0 -0
  378. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_object_manager_autoset_stamping.py +0 -0
  379. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
  380. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_object_manager_write_through.py +0 -0
  381. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_one_primary_source.py +0 -0
  382. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_parser.py +0 -0
  383. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_parser_yaml.py +0 -0
  384. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_provider.py +0 -0
  385. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_provider_extension.py +0 -0
  386. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_registry.py +0 -0
  387. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_registry_completeness.py +0 -0
  388. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_registry_extend.py +0 -0
  389. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_registry_sealed.py +0 -0
  390. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_relationship_referential_actions.py +0 -0
  391. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_resolution_key.py +0 -0
  392. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
  393. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_serializer.py +0 -0
  394. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_shared_constants.py +0 -0
  395. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_smoke.py +0 -0
  396. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_source_escapes.py +0 -0
  397. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_sources.py +0 -0
  398. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_strict_child_placement.py +0 -0
  399. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_super_resolve.py +0 -0
  400. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_template_toolcall.py +0 -0
  401. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
  402. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_validation_attr_schema.py +0 -0
  403. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_validation_filter_values.py +0 -0
  404. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_validation_origin_195.py +0 -0
  405. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_validation_origin_paths.py +0 -0
  406. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_validation_sort_field.py +0 -0
  407. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_validation_warnings.py +0 -0
  408. {metaobjects-0.22.1 → metaobjects-0.23.1}/tests/unit/test_write_coercion_arrays.py +0 -0
  409. {metaobjects-0.22.1 → metaobjects-0.23.1}/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.1
3
+ Version: 0.23.1
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.1"
3
+ version = "0.23.1"
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"
@@ -66,12 +66,21 @@ def resolve_shared_enum_decl(field: MetaField) -> MetaData | None:
66
66
 
67
67
 
68
68
  def is_provided(decl: MetaData) -> bool:
69
- """Effective ``@provided`` truth of an enum declaration.
70
-
71
- ADR-0039 — resolves through ``extends`` (``get_meta_attr``): a concrete enum
72
- extending an abstract ``@provided`` enum inherits the flag, so an own-only read
73
- would misclassify it."""
74
- return decl.get_meta_attr(fc.FIELD_ATTR_PROVIDED) is True
69
+ """``@provided`` truth of an enum DECLARATION.
70
+
71
+ ADR-0039 sanctioned own (Python naming inversion: ``attr()`` is the OWN read,
72
+ ``get_meta_attr()`` resolves). ``@provided`` is a declaration-layer provenance
73
+ marker — "THIS type is supplied by hand-written/third-party code", like
74
+ ``is_abstract`` — and does not flow down an ``extends`` chain.
75
+
76
+ This is only ever called on the resolved declaration (see
77
+ ``shared_enum_for_field``), never on the consuming field, so own and resolving
78
+ agree for a plain ``field extends @provided decl``. They diverge on a CHAINED
79
+ declaration (root abstract ``B extends`` root abstract ``@provided A``): a
80
+ resolving read reports B provided and emits a reference to a hand-written ``B``
81
+ the adopter never declared, instead of materializing B. Matches the JVM ports.
82
+ """
83
+ return decl.attr(fc.FIELD_ATTR_PROVIDED) is True
75
84
 
76
85
 
77
86
  def _meta_package_of(decl: MetaData) -> str:
@@ -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
 
@@ -49,19 +54,51 @@ class MetaRequirement(MetaData):
49
54
  return [str(x) for x in v] if isinstance(v, list) else []
50
55
 
51
56
  def verified_by(self) -> list[str]:
52
- """ADR-0039: resolving. Names of the tests proving the behaviour."""
57
+ """ADR-0039: resolving. Names of tests that ASSERT the behaviour — existence
58
+ evidence only; verify cannot tell whether a named test verifies this."""
53
59
  v = self.get_meta_attr(REQUIREMENT_ATTR_VERIFIED_BY)
54
60
  return [str(x) for x in v] if isinstance(v, list) else []
55
61
 
62
+ def disposition(self) -> str | None:
63
+ """ADR-0039: resolving. What was DECIDED about the outstanding work — a
64
+ different question from whether the work is done, which is what
65
+ ``status`` answers. ``None`` means UNDECIDED, a real state and the one a
66
+ review exists to find."""
67
+ v = self.get_meta_attr(REQUIREMENT_ATTR_DISPOSITION)
68
+ return v if isinstance(v, str) else None
69
+
70
+ def tracked_by(self) -> list[str]:
71
+ """ADR-0039: resolving. Issue/ticket references for outstanding work.
72
+ Free-form and NEVER resolved — verify has no network, so unlike
73
+ ``verified_by`` nothing here is checked to exist."""
74
+ v = self.get_meta_attr(REQUIREMENT_ATTR_TRACKED_BY)
75
+ return [str(x) for x in v] if isinstance(v, list) else []
76
+
77
+ def is_planned(self) -> bool:
78
+ """Intended but not built. Its nodes may legitimately not exist yet, and
79
+ it must NOT count toward object coverage — planning a capability cannot
80
+ be allowed to silence the warning that nothing implements it."""
81
+ return self.status() == REQUIREMENT_STATUS_PLANNED
82
+
83
+ def has_outstanding_work(self) -> bool:
84
+ """True when there is outstanding work, so a ``disposition`` says
85
+ something."""
86
+ s = self.status()
87
+ return s is not None and s in REQUIREMENT_STATUSES_WITH_OUTSTANDING_WORK
88
+
56
89
  def may_reference_model(self) -> bool:
57
90
  """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
91
+
92
+ An UNLEVELLED architectural requirement always may — its claim set is the
93
+ whole point, and that is the original flat form. Once a level is PRESENT
94
+ the node has opted into a tree, and the link floor applies to it exactly
95
+ as it does to a functional one, so an "ISO 25010 Security" grouping node
96
+ cannot quietly start naming entities. Levelling is the opt-in; enforcing
97
+ the floor unconditionally would have broken every existing flat policy."""
63
98
  lvl = self.level()
64
- return lvl is not None and lvl >= REQUIREMENT_LINK_FLOOR_LEVEL
99
+ if lvl is None:
100
+ return self.is_architectural()
101
+ return lvl >= REQUIREMENT_LINK_FLOOR_LEVEL
65
102
 
66
103
  def requires_live_nodes(self) -> bool:
67
104
  """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
@@ -0,0 +1,134 @@
1
+ """Derived boolean accessors — ``{{#hasFoo}}`` over a payload field ``foo``.
2
+
3
+ A prompt needs conditional sections ("include the abilities block only when there ARE
4
+ abilities"), and the payload contract answers that with a DERIVED accessor rather than an
5
+ authored boolean field: the author declares ``abilities`` and ``hasAbilities`` follows
6
+ from it. Declaring both would let them disagree.
7
+
8
+ THE RULE IS SHARED ACROSS PORTS ON PURPOSE. The JVM has carried it since 7.7.7
9
+ (``com.metaobjects.render.PayloadAccessors``, emitted onto every generated payload record
10
+ and accepted by its ``Verify``), and its comment says the emitter and the verifier share
11
+ one rule so they "can never drift apart". Python had neither half, so the same template
12
+ verified clean on the JVM and reported drift here — and rendered WRONG rather than
13
+ failing, silently dropping the section. Gated cross-port by the
14
+ ``render-derived-has-accessor`` conformance case.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import numbers
20
+ from collections.abc import Mapping, Sequence
21
+ from typing import Any
22
+
23
+ __all__ = [
24
+ "HAS_PREFIX",
25
+ "has_accessor_name",
26
+ "capitalize",
27
+ "accessor_value",
28
+ "with_derived_accessors",
29
+ "is_boolean_accessor",
30
+ ]
31
+
32
+ #: The ``has`` prefix every derived boolean accessor carries.
33
+ HAS_PREFIX = "has"
34
+
35
+ _MAX_DEPTH = 32
36
+
37
+
38
+ def capitalize(s: str) -> str:
39
+ """Capitalize the first character, leaving an already-uppercase one untouched.
40
+
41
+ Deliberately NOT ``str.capitalize()``, which also lowercases the remainder.
42
+ """
43
+ if not s:
44
+ return s
45
+ if s[0].isupper():
46
+ return s
47
+ return s[0].upper() + s[1:]
48
+
49
+
50
+ def has_accessor_name(field_name: str) -> str:
51
+ """``"has" + capitalize(name)`` (``abilities`` → ``hasAbilities``).
52
+
53
+ Byte-identical to the JVM's ``PayloadAccessors.hasAccessorName``.
54
+ """
55
+ return HAS_PREFIX + capitalize(field_name)
56
+
57
+
58
+ def accessor_value(value: Any) -> bool | None:
59
+ """Is ``value`` "present" for the purposes of ``has<Field>``?
60
+
61
+ Mirrors the JVM emitter's per-type bodies exactly: string → non-null and non-blank;
62
+ collection → non-null and non-empty; reference → non-null.
63
+
64
+ Returns ``None`` for numbers and booleans, which the JVM deliberately emits NO
65
+ accessor for — they are always-present scalars, and ``{{#hasCount}}`` over an int is
66
+ drift rather than a conditional. Returning ``None`` (rather than ``False``) keeps that
67
+ distinction: nothing is injected, so the name stays unresolved exactly as it is on a
68
+ generated record with no such method.
69
+ """
70
+ if value is None:
71
+ return False
72
+ if isinstance(value, str):
73
+ return bool(value.strip())
74
+ # bool before int — bool IS an int in Python, and a boolean field gets no accessor.
75
+ if isinstance(value, numbers.Number):
76
+ return None
77
+ if isinstance(value, Mapping):
78
+ return True
79
+ if isinstance(value, (Sequence, set, frozenset)):
80
+ return len(value) > 0
81
+ return True
82
+
83
+
84
+ def with_derived_accessors(payload: Any, depth: int = 0) -> Any:
85
+ """A view over ``payload`` carrying its derived ``has<Field>`` accessors, recursively.
86
+
87
+ NON-MUTATING — the caller's payload is never touched, because a render must not be
88
+ able to change the object it was handed. An AUTHORED key always wins: if a payload
89
+ genuinely carries ``hasFoo``, that value is kept rather than shadowed.
90
+
91
+ Recursion follows Mustache's own scoping: every nested mapping and every sequence
92
+ ELEMENT becomes a context in its own right, so a section over ``abilities`` sees the
93
+ accessors of the ability it is currently iterating.
94
+ """
95
+ if depth > _MAX_DEPTH:
96
+ return payload # pathological graph; render is not a validator
97
+ if isinstance(payload, Mapping):
98
+ out: dict[str, Any] = {
99
+ k: with_derived_accessors(v, depth + 1) for k, v in payload.items()
100
+ }
101
+ for k, v in payload.items():
102
+ if not isinstance(k, str):
103
+ continue
104
+ name = has_accessor_name(k)
105
+ if name in payload: # authored wins
106
+ continue
107
+ derived = accessor_value(v)
108
+ if derived is not None:
109
+ out[name] = derived
110
+ return out
111
+ if isinstance(payload, (str, bytes)):
112
+ return payload
113
+ if isinstance(payload, Sequence):
114
+ return [with_derived_accessors(v, depth + 1) for v in payload]
115
+ return payload
116
+
117
+
118
+ def is_boolean_accessor(stack: list[list[Any]], name: str) -> bool:
119
+ """True when ``name`` is a derived accessor over a field reachable on ``stack``.
120
+
121
+ Mirrors the JVM's ``Verify.isBooleanAccessor``, including its deliberate
122
+ permissiveness: acceptance keys off the FIELD EXISTING, not off its type. Accessors
123
+ are simple (undotted) names; a dotted path is never an accessor.
124
+ """
125
+ if "." in name:
126
+ return False
127
+ if not name.startswith(HAS_PREFIX):
128
+ return False
129
+ # Mustache outward walk (innermost → outermost).
130
+ for frame in reversed(stack):
131
+ for f in frame:
132
+ if name == has_accessor_name(f.name):
133
+ return True
134
+ return False
@@ -23,6 +23,7 @@ from dataclasses import dataclass, field
23
23
  from typing import Any
24
24
 
25
25
  from . import escapers
26
+ from .payload_accessors import with_derived_accessors
26
27
  from .verify import InMemoryProvider, Provider
27
28
 
28
29
  MAX_DEPTH = 32
@@ -59,7 +60,10 @@ def render(req: RenderRequest) -> str:
59
60
  _validate(req)
60
61
  body = req.template if req.template is not None else _resolve_or_raise(req.provider, req.ref)
61
62
  expanded = _pre_expand_partials(body, req.provider, [])
62
- out = _interpret(expanded, req.payload, req.format)
63
+ # Derived `has<Field>` accessors are part of the payload contract, not of the
64
+ # caller's object — see payload_accessors. Injected here so a `{{#hasFoo}}` section
65
+ # resolves the same way it does against a generated JVM payload record.
66
+ out = _interpret(expanded, with_derived_accessors(req.payload), req.format)
63
67
  # @maxChars is a fail-closed render budget: over-budget output RAISES (never
64
68
  # silently truncates). Canonical cross-port behavior — message shape matches
65
69
  # TS/C#/Java: "render exceeded maxChars budget: <len> > <cap>".
@@ -23,6 +23,8 @@ from __future__ import annotations
23
23
  from dataclasses import dataclass
24
24
  from typing import Protocol
25
25
 
26
+ from .payload_accessors import is_boolean_accessor
27
+
26
28
  #: A ``{{var}}`` references a field the (contextual) payload does not declare.
27
29
  ERR_VAR_NOT_ON_PAYLOAD = "ERR_VAR_NOT_ON_PAYLOAD"
28
30
  #: A ``{{> ref}}`` partial does not resolve in the provider.
@@ -215,7 +217,9 @@ def verify(
215
217
  continue # implicit iterator — always valid
216
218
  if at_root:
217
219
  referenced_at_root.add(tok.value.split(".")[0])
218
- if _resolve(stack, tok.value) is None:
220
+ if _resolve(stack, tok.value) is None and not is_boolean_accessor(
221
+ stack, tok.value
222
+ ):
219
223
  errors.append(VerifyError(ERR_VAR_NOT_ON_PAYLOAD, tok.value))
220
224
  elif isinstance(tok, _Section):
221
225
  if tok.value == ".":
@@ -225,6 +229,12 @@ def verify(
225
229
  referenced_at_root.add(tok.value.split(".")[0])
226
230
  field = _resolve(stack, tok.value)
227
231
  if field is None:
232
+ # A derived `has<Field>` gate is a BOOLEAN over the current context:
233
+ # it resolves nothing and pushes nothing, so walk the body in the SAME
234
+ # scope — what `{{#hasAbilities}}{{#abilities}}…` depends on.
235
+ if is_boolean_accessor(stack, tok.value):
236
+ walk(tok.children, stack, seen)
237
+ continue
228
238
  # Unresolved section head is itself drift; skip the body (its
229
239
  # context is unknowable, walking it would cascade false errors).
230
240
  errors.append(VerifyError(ERR_VAR_NOT_ON_PAYLOAD, tok.value))
@@ -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",