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.
- {metaobjects-0.22.0 → metaobjects-0.23.0}/PKG-INFO +1 -1
- {metaobjects-0.22.0 → metaobjects-0.23.0}/pyproject.toml +1 -1
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/entity_model.py +25 -3
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/core_types.py +44 -8
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/requirement/meta_requirement.py +44 -8
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/requirement/requirement_constants.py +31 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/documentation.json +4 -4
- metaobjects-0.23.0/src/metaobjects/spec_metamodel/requirement.json +209 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_validation_conformance.py +21 -14
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/postgres_container.py +84 -14
- {metaobjects-0.22.0 → metaobjects-0.23.0}/uv.lock +1 -1
- metaobjects-0.22.0/src/metaobjects/spec_metamodel/requirement.json +0 -140
- {metaobjects-0.22.0 → metaobjects-0.23.0}/.gitignore +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/LICENSE +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/README.md +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/hatch_build.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/agent_context/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/agent_context/scaffold.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/api_model.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/builder.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/naming.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/paths.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/apidocs/renderer.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/attr_class_map.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/cli.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/KNOWN_GAPS.md +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/collision_names.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/config.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/format.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generator_registry.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/fr019_shared_enum.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/m2m_codegen.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/payload_vo_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/router_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/template_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/instance_artifacts.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/metaobjects-config.schema.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/overwrite_policy.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/project_config.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/runner.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/runtime/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/type_map.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/datatype.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/documentation/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/documentation/doc_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/documentation/doc_provider.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/documentation/doc_schema.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/errors.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/merge.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/meta_data_loader.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/registered_validation.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/sources/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/sources/directory_source.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/sources/file_source.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/sources/uri_source.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_discriminator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_enum_normalize_ambiguity.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_field_readonly.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_source_escapes.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/loader/validation_passes.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/attr/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/attr/attr_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/attr/meta_attr.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/field/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/field/field_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/field/meta_field.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/identity/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/index/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/index/index_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/index/meta_index.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/meta_object.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/object_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/object_extract.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/object/value_object.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/requirement/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/validator/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/meta_data.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/meta_root.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/source/meta_source.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/persistence/source/source_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/provider_extends.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/template/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/template/meta_template.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/template/prompt_provider.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/template/template_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/naming_refs.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/parser.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/parser_yaml.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/provider.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/py.typed +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/registry.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/registry_manifest.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/email_document.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/escapers.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/coerce.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/extract.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/extract_map.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/locate.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/normalize.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/strip.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/types.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/extract/xml_forgiving_reader.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/filesystem_provider.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/prompt_field.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/prompt/prompt_style.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/renderer.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/render/verify.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/runtime/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/runtime/llm_recorder.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/runtime/n2m_resolver.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/runtime/object_manager.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/runtime/tph.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/serializer_json.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/shared/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/shared/base_types.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/shared/separators.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/shared/structural.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/source/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/source/error_source.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/source/json_path.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/source/semantic_diff.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/source/yaml_positions.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/attr.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/db.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/field.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/identity.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/index.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/layout.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/object.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/origin.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/prompt.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/relationship.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/source.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/template.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/ui-web.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/ui.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/validator.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/spec_metamodel/view.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/super_resolve.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/validation_types.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/yaml_desugar.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/extends/expected/Program.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/extends/meta.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/nested-array/expected/PostBrief.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/nested-array/meta.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/scalars/expected/Metric.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/scalars/expected/Report.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/scalars/meta.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/vanilla/expected/Subscriber.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/golden/vanilla/meta.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_abstract_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_api_docs_builder.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_api_docs_paths.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_config_gen.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_config_verify.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_providers.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_registry.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_staleness_nudge.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_verify_strict.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_cli_verify_subverbs.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_constants_config.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_entity_model.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_enum_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_extract_tier_collision.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_extractor_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_filter_allowlist_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_format.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_fr010_output_codegen.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_generator_extension_seams.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_golden.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_inheritance_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_instance_artifacts.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_m2m_codegen.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_origin_nullability.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_output_parser_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_overwrite_policy.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_payload_vo_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_project_config.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_projection_compile.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_render_helper_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_render_helper_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_reverse_finders.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_router_autoset.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_router_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_runner.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_sourceless_projection.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_data.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_output_pattern.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_scope_helpers.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_scope_walk.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_template_spec.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_tph_codegen.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_trace_helper_generator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_type_map.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/codegen/test_write_through.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/capabilities.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/conformance-expected-failures.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/conformance_adapter.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/corpus.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/expected_failures.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/fixture_discovery.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/navigator.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_extract_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_extract_object_verdict.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_fr010_loader_attrs.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_fr011_attrs.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_generator_registry_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_object_model_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_provider_composition_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_registry_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_runner_hardfail.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_spec_metamodel_embed.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_strict_attr_load.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_template_codegen_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_template_generator_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/test_yaml_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/api_contract_assertions.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/api_contract_jsonb_server.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/api_contract_m2m_server.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/api_contract_server.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/generated_jsonb_app.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/generated_m2m_app.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/generated_router_app.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/generated_tph_app.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/meta_ai_trace.yaml +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/normalization.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/query_runner.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/scenarios.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract_generated.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract_jsonb.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract_m2m.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract_m2m_generated.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_api_contract_tph_generated.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_generated_router_uuid_pk.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_llm_call_trace.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_normalization.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_query_scenarios.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/integration/test_runtime_return_types.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/loader/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/loader/test_enum_extends_values_conflict.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/loader/test_template_payload_target_210.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/open_closed_proof_test.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_coerce.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_extract.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_extract_map.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_json_forgiving_reader.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_locate.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_model.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_normalize.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_strip.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/prompt/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/prompt/test_output_format_renderer.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_email_document.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_filesystem_provider.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_output_format_renderer_nested.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_output_prompt_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_render_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_render_max_chars.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_verify.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/render/test_verify_conformance.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_fr5c_merge_attribution.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_fr5d_reference_resolution.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_fr5e_database_source_shape.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_json_path.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_semantic_diff.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_source_on_node.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/source/test_yaml_positions.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/test_api_docs_accuracy.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/__init__.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_agent_context_staleness.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_capabilities.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_common_attrs.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_core_types.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_effective_package.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_errors.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_field_enum.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_field_map_validation.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_fr016_source_name_and_kind_aliases.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_index_lookup.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_llm_recorder.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_loader.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_loader_bom.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_loader_class.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_merge.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_meta_attr.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_meta_data.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_meta_source.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_module_shortcuts.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_n2m_resolver.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_n2m_resolver_inherited.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_object_manager_autoset_stamping.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_object_manager_write_through.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_one_primary_source.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_parser.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_parser_yaml.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_provider.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_provider_extension.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_registry.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_registry_completeness.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_registry_extend.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_registry_sealed.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_relationship_referential_actions.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_resolution_key.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_serializer.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_shared_constants.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_smoke.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_source_escapes.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_sources.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_strict_child_placement.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_super_resolve.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_template_toolcall.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_attr_schema.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_filter_values.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_origin_195.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_origin_paths.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_sort_field.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_validation_warnings.py +0 -0
- {metaobjects-0.22.0 → metaobjects-0.23.0}/tests/unit/test_write_coercion_arrays.py +0 -0
- {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.
|
|
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.
|
|
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"
|
{metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/codegen/generators/entity_model.py
RENAMED
|
@@ -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
|
-
|
|
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(
|
|
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=
|
|
630
|
-
|
|
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
|
|
{metaobjects-0.22.0 → metaobjects-0.23.0}/src/metaobjects/meta/core/requirement/meta_requirement.py
RENAMED
|
@@ -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.
|
|
35
|
-
object-independent
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
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": "
|
|
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
|
|
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`).
|
|
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
|
|
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
|
-
|
|
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) ==
|
|
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("
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
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(
|
|
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[
|
|
78
|
+
sys.modules[mod_name] = module
|
|
72
79
|
spec.loader.exec_module(module)
|
|
73
|
-
model = module
|
|
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
|