metaobjects 0.9.0__py3-none-any.whl

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 (181) hide show
  1. metaobjects/__init__.py +75 -0
  2. metaobjects/agent_context/__init__.py +55 -0
  3. metaobjects/agent_context/_content/README.md +14 -0
  4. metaobjects/agent_context/_content/servers/csharp.meta.json +5 -0
  5. metaobjects/agent_context/_content/servers/java.meta.json +5 -0
  6. metaobjects/agent_context/_content/servers/kotlin.meta.json +5 -0
  7. metaobjects/agent_context/_content/servers/python.meta.json +5 -0
  8. metaobjects/agent_context/_content/servers/typescript.meta.json +5 -0
  9. metaobjects/agent_context/_content/skills/metaobjects-authoring/SKILL.md +301 -0
  10. metaobjects/agent_context/_content/skills/metaobjects-codegen/SKILL.md +99 -0
  11. metaobjects/agent_context/_content/skills/metaobjects-codegen/references/csharp.md +87 -0
  12. metaobjects/agent_context/_content/skills/metaobjects-codegen/references/java.md +94 -0
  13. metaobjects/agent_context/_content/skills/metaobjects-codegen/references/kotlin.md +110 -0
  14. metaobjects/agent_context/_content/skills/metaobjects-codegen/references/typescript.md +135 -0
  15. metaobjects/agent_context/_content/skills/metaobjects-prompts/SKILL.md +148 -0
  16. metaobjects/agent_context/_content/skills/metaobjects-prompts/references/csharp.md +110 -0
  17. metaobjects/agent_context/_content/skills/metaobjects-prompts/references/java.md +108 -0
  18. metaobjects/agent_context/_content/skills/metaobjects-prompts/references/kotlin.md +130 -0
  19. metaobjects/agent_context/_content/skills/metaobjects-prompts/references/python.md +116 -0
  20. metaobjects/agent_context/_content/skills/metaobjects-prompts/references/typescript.md +150 -0
  21. metaobjects/agent_context/_content/skills/metaobjects-runtime-ui/SKILL.md +130 -0
  22. metaobjects/agent_context/_content/skills/metaobjects-runtime-ui/references/java.md +96 -0
  23. metaobjects/agent_context/_content/skills/metaobjects-runtime-ui/references/kotlin.md +99 -0
  24. metaobjects/agent_context/_content/skills/metaobjects-runtime-ui/references/react.md +86 -0
  25. metaobjects/agent_context/_content/skills/metaobjects-runtime-ui/references/tanstack.md +119 -0
  26. metaobjects/agent_context/_content/skills/metaobjects-runtime-ui/references/typescript.md +92 -0
  27. metaobjects/agent_context/_content/skills/metaobjects-verify/SKILL.md +107 -0
  28. metaobjects/agent_context/_content/skills/metaobjects-verify/references/migration.md +72 -0
  29. metaobjects/agent_context/_content/templates/always-on.md.mustache +27 -0
  30. metaobjects/agent_context/assemble.py +133 -0
  31. metaobjects/agent_context/content_root.py +54 -0
  32. metaobjects/agent_context/scaffold.py +191 -0
  33. metaobjects/agent_context/types.py +44 -0
  34. metaobjects/attr_class_map.py +23 -0
  35. metaobjects/cli.py +696 -0
  36. metaobjects/codegen/__init__.py +0 -0
  37. metaobjects/codegen/config.py +11 -0
  38. metaobjects/codegen/constants.py +13 -0
  39. metaobjects/codegen/extract_delegate_emitter.py +384 -0
  40. metaobjects/codegen/extract_schema_emitter.py +139 -0
  41. metaobjects/codegen/format.py +31 -0
  42. metaobjects/codegen/fr010_field_mapping.py +220 -0
  43. metaobjects/codegen/generator.py +62 -0
  44. metaobjects/codegen/generator_registry.py +163 -0
  45. metaobjects/codegen/generators/__init__.py +0 -0
  46. metaobjects/codegen/generators/entity_model.py +263 -0
  47. metaobjects/codegen/generators/extractor_generator.py +317 -0
  48. metaobjects/codegen/generators/filter_allowlist_generator.py +309 -0
  49. metaobjects/codegen/generators/m2m_codegen.py +192 -0
  50. metaobjects/codegen/generators/output_parser_generator.py +272 -0
  51. metaobjects/codegen/generators/output_prompt_generator.py +192 -0
  52. metaobjects/codegen/generators/payload_vo_generator.py +672 -0
  53. metaobjects/codegen/generators/render_helper_generator.py +451 -0
  54. metaobjects/codegen/generators/router_generator.py +635 -0
  55. metaobjects/codegen/generators/template_generator.py +70 -0
  56. metaobjects/codegen/generators/tph_plan.py +120 -0
  57. metaobjects/codegen/generators/trace_helper_generator.py +336 -0
  58. metaobjects/codegen/instance_artifacts.py +15 -0
  59. metaobjects/codegen/output_format_spec_emitter.py +79 -0
  60. metaobjects/codegen/overwrite_policy.py +27 -0
  61. metaobjects/codegen/runner.py +110 -0
  62. metaobjects/codegen/runtime/__init__.py +6 -0
  63. metaobjects/codegen/runtime/filter_parser.py +193 -0
  64. metaobjects/codegen/type_map.py +84 -0
  65. metaobjects/core_types.py +809 -0
  66. metaobjects/datatype.py +19 -0
  67. metaobjects/documentation/__init__.py +28 -0
  68. metaobjects/documentation/doc_constants.py +20 -0
  69. metaobjects/documentation/doc_provider.py +20 -0
  70. metaobjects/documentation/doc_schema.py +24 -0
  71. metaobjects/errors.py +124 -0
  72. metaobjects/loader/__init__.py +0 -0
  73. metaobjects/loader/merge.py +287 -0
  74. metaobjects/loader/meta_data_loader.py +245 -0
  75. metaobjects/loader/sources/__init__.py +24 -0
  76. metaobjects/loader/sources/directory_source.py +50 -0
  77. metaobjects/loader/sources/file_source.py +41 -0
  78. metaobjects/loader/sources/meta_data_source.py +67 -0
  79. metaobjects/loader/sources/uri_source.py +56 -0
  80. metaobjects/loader/validate_discriminator.py +181 -0
  81. metaobjects/loader/validate_field_readonly.py +146 -0
  82. metaobjects/loader/validate_source_parameter_ref.py +159 -0
  83. metaobjects/loader/validate_source_physical_names.py +140 -0
  84. metaobjects/loader/validation_passes.py +1513 -0
  85. metaobjects/meta/__init__.py +1 -0
  86. metaobjects/meta/core/__init__.py +0 -0
  87. metaobjects/meta/core/attr/__init__.py +0 -0
  88. metaobjects/meta/core/attr/attr_constants.py +31 -0
  89. metaobjects/meta/core/attr/meta_attr.py +136 -0
  90. metaobjects/meta/core/field/__init__.py +0 -0
  91. metaobjects/meta/core/field/field_constants.py +105 -0
  92. metaobjects/meta/core/field/meta_field.py +76 -0
  93. metaobjects/meta/core/identity/__init__.py +0 -0
  94. metaobjects/meta/core/identity/identity_constants.py +19 -0
  95. metaobjects/meta/core/identity/meta_identity.py +8 -0
  96. metaobjects/meta/core/object/__init__.py +0 -0
  97. metaobjects/meta/core/object/meta_object.py +65 -0
  98. metaobjects/meta/core/object/meta_object_aware.py +43 -0
  99. metaobjects/meta/core/object/object_class_registry.py +56 -0
  100. metaobjects/meta/core/object/object_constants.py +13 -0
  101. metaobjects/meta/core/object/object_extract.py +400 -0
  102. metaobjects/meta/core/object/value_object.py +70 -0
  103. metaobjects/meta/core/relationship/__init__.py +0 -0
  104. metaobjects/meta/core/relationship/derive_m2m_fields.py +180 -0
  105. metaobjects/meta/core/relationship/meta_relationship.py +54 -0
  106. metaobjects/meta/core/relationship/relationship_constants.py +51 -0
  107. metaobjects/meta/core/validator/__init__.py +0 -0
  108. metaobjects/meta/core/validator/validator_constants.py +18 -0
  109. metaobjects/meta/meta_data.py +206 -0
  110. metaobjects/meta/meta_root.py +8 -0
  111. metaobjects/meta/persistence/__init__.py +0 -0
  112. metaobjects/meta/persistence/db/__init__.py +1 -0
  113. metaobjects/meta/persistence/db/db_constants.py +41 -0
  114. metaobjects/meta/persistence/db/db_provider.py +60 -0
  115. metaobjects/meta/persistence/origin/__init__.py +0 -0
  116. metaobjects/meta/persistence/origin/meta_origin.py +8 -0
  117. metaobjects/meta/persistence/origin/origin_constants.py +20 -0
  118. metaobjects/meta/persistence/source/__init__.py +0 -0
  119. metaobjects/meta/persistence/source/meta_source.py +137 -0
  120. metaobjects/meta/persistence/source/source_constants.py +115 -0
  121. metaobjects/meta/presentation/__init__.py +0 -0
  122. metaobjects/meta/presentation/layout/__init__.py +0 -0
  123. metaobjects/meta/presentation/layout/layout_constants.py +13 -0
  124. metaobjects/meta/presentation/layout/meta_layout.py +8 -0
  125. metaobjects/meta/presentation/view/__init__.py +0 -0
  126. metaobjects/meta/presentation/view/meta_view.py +8 -0
  127. metaobjects/meta/presentation/view/view_constants.py +22 -0
  128. metaobjects/meta/template/__init__.py +0 -0
  129. metaobjects/meta/template/meta_template.py +46 -0
  130. metaobjects/meta/template/template_constants.py +112 -0
  131. metaobjects/meta/template/template_provider.py +43 -0
  132. metaobjects/parser.py +380 -0
  133. metaobjects/parser_yaml.py +82 -0
  134. metaobjects/provider.py +111 -0
  135. metaobjects/py.typed +0 -0
  136. metaobjects/registry.py +210 -0
  137. metaobjects/registry_manifest.py +223 -0
  138. metaobjects/render/__init__.py +74 -0
  139. metaobjects/render/email_document.py +14 -0
  140. metaobjects/render/escapers.py +109 -0
  141. metaobjects/render/extract/__init__.py +59 -0
  142. metaobjects/render/extract/coerce.py +279 -0
  143. metaobjects/render/extract/extract.py +211 -0
  144. metaobjects/render/extract/extract_map.py +61 -0
  145. metaobjects/render/extract/json_forgiving_reader.py +203 -0
  146. metaobjects/render/extract/locate.py +65 -0
  147. metaobjects/render/extract/normalize.py +96 -0
  148. metaobjects/render/extract/strip.py +20 -0
  149. metaobjects/render/extract/types.py +332 -0
  150. metaobjects/render/extract/xml_forgiving_reader.py +162 -0
  151. metaobjects/render/filesystem_provider.py +51 -0
  152. metaobjects/render/prompt/__init__.py +32 -0
  153. metaobjects/render/prompt/output_format_renderer.py +340 -0
  154. metaobjects/render/prompt/output_format_spec.py +28 -0
  155. metaobjects/render/prompt/prompt_field.py +29 -0
  156. metaobjects/render/prompt/prompt_overrides.py +29 -0
  157. metaobjects/render/prompt/prompt_style.py +38 -0
  158. metaobjects/render/renderer.py +358 -0
  159. metaobjects/render/verify.py +266 -0
  160. metaobjects/runtime/__init__.py +39 -0
  161. metaobjects/runtime/llm_recorder.py +210 -0
  162. metaobjects/runtime/n2m_resolver.py +155 -0
  163. metaobjects/runtime/object_manager.py +715 -0
  164. metaobjects/runtime/tph.py +50 -0
  165. metaobjects/serializer_json.py +172 -0
  166. metaobjects/shared/__init__.py +0 -0
  167. metaobjects/shared/base_types.py +16 -0
  168. metaobjects/shared/separators.py +4 -0
  169. metaobjects/shared/structural.py +9 -0
  170. metaobjects/source/__init__.py +79 -0
  171. metaobjects/source/error_source.py +266 -0
  172. metaobjects/source/json_path.py +106 -0
  173. metaobjects/source/semantic_diff.py +98 -0
  174. metaobjects/source/yaml_positions.py +174 -0
  175. metaobjects/super_resolve.py +128 -0
  176. metaobjects/yaml_desugar.py +481 -0
  177. metaobjects-0.9.0.dist-info/METADATA +97 -0
  178. metaobjects-0.9.0.dist-info/RECORD +181 -0
  179. metaobjects-0.9.0.dist-info/WHEEL +4 -0
  180. metaobjects-0.9.0.dist-info/entry_points.txt +2 -0
  181. metaobjects-0.9.0.dist-info/licenses/LICENSE +189 -0
@@ -0,0 +1,809 @@
1
+ """The core metaobjects type provider. Composes per-concern registrations (ADR-0004)."""
2
+ from __future__ import annotations
3
+
4
+ # Importing the attr module triggers its attr-class self-registration (side effect).
5
+ from .attr_class_map import attr_class_for
6
+ from .meta.core.attr import meta_attr as _attr # noqa: F401
7
+ from .meta.core.attr.attr_constants import (
8
+ ATTR_SUBTYPE_BOOLEAN,
9
+ ATTR_SUBTYPE_FILTER,
10
+ ATTR_SUBTYPE_INT,
11
+ ATTR_SUBTYPE_PROPERTIES,
12
+ ATTR_SUBTYPE_STRING,
13
+ ATTR_SUBTYPE_STRINGARRAY,
14
+ ATTR_SUBTYPES,
15
+ )
16
+ from .meta.core.field import field_constants as fc
17
+ from .meta.core.validator import validator_constants as vc
18
+ from .meta.core.field.field_constants import (
19
+ AUTO_SET_VALUES,
20
+ FIELD_ATTR_AUTO_SET,
21
+ FIELD_ATTR_COERCE_DEFAULT,
22
+ FIELD_ATTR_COLUMN,
23
+ FIELD_ATTR_CURRENCY,
24
+ FIELD_ATTR_DEFAULT,
25
+ FIELD_ATTR_ENUM_ALIAS,
26
+ FIELD_ATTR_ENUM_DOC,
27
+ FIELD_ATTR_EXAMPLE,
28
+ FIELD_ATTR_FILTERABLE,
29
+ FIELD_ATTR_INSTRUCTION,
30
+ FIELD_ATTR_MAX_LENGTH,
31
+ FIELD_ATTR_NORMALIZE,
32
+ FIELD_ATTR_OBJECT_REF,
33
+ FIELD_ATTR_PRECISION,
34
+ FIELD_ATTR_READ_ONLY,
35
+ FIELD_ATTR_REQUIRED,
36
+ FIELD_ATTR_SCALE,
37
+ FIELD_ATTR_SORTABLE,
38
+ FIELD_ATTR_SORTABLE_DEFAULT_ORDER,
39
+ FIELD_ATTR_STORAGE,
40
+ FIELD_ATTR_UNIQUE,
41
+ FIELD_ATTR_VALUES,
42
+ FIELD_SUBTYPE_ENUM,
43
+ NORMALIZE_DEFAULT,
44
+ NORMALIZE_MODES,
45
+ SORT_ORDER_VALUES,
46
+ STORAGE_VALUES,
47
+ )
48
+ from .meta.core.field.meta_field import MetaField
49
+ from .meta.persistence.db.db_constants import (
50
+ FIELD_ATTR_DB_COLUMN_TYPE,
51
+ FIELD_ATTR_DB_INDEXED,
52
+ )
53
+ from .meta.core.identity.identity_constants import (
54
+ GENERATION_VALUES,
55
+ IDENTITY_ATTR_FIELDS,
56
+ IDENTITY_ATTR_GENERATION,
57
+ IDENTITY_ATTR_UNIQUE,
58
+ IDENTITY_REFERENCE_ATTR_ENFORCE,
59
+ IDENTITY_REFERENCE_ATTR_REFERENCES,
60
+ IDENTITY_SUBTYPE_PRIMARY,
61
+ IDENTITY_SUBTYPE_REFERENCE,
62
+ IDENTITY_SUBTYPE_SECONDARY,
63
+ )
64
+ from .meta.core.identity.meta_identity import MetaIdentity
65
+ from .meta.core.object.meta_object import MetaObject
66
+ from .meta.core.object.object_constants import (
67
+ OBJECT_ATTR_DISCRIMINATOR,
68
+ OBJECT_ATTR_DISCRIMINATOR_VALUE,
69
+ OBJECT_SUBTYPE_ENTITY,
70
+ OBJECT_SUBTYPE_VALUE,
71
+ OBJECT_SUBTYPES,
72
+ )
73
+ from .meta.core.relationship.meta_relationship import MetaRelationship
74
+ from .meta.core.relationship.relationship_constants import (
75
+ REFERENTIAL_ACTIONS,
76
+ RELATIONSHIP_ATTR_CARDINALITY,
77
+ RELATIONSHIP_ATTR_OBJECT_REF,
78
+ RELATIONSHIP_ATTR_ON_DELETE,
79
+ RELATIONSHIP_ATTR_ON_UPDATE,
80
+ RELATIONSHIP_ATTR_SOURCE_REF_FIELD,
81
+ RELATIONSHIP_ATTR_SYMMETRIC,
82
+ RELATIONSHIP_ATTR_THROUGH,
83
+ RELATIONSHIP_SUBTYPES,
84
+ )
85
+ from .meta.meta_data import MetaData
86
+ from .meta.meta_root import MetaRoot
87
+ from .meta.persistence.origin.meta_origin import MetaOrigin
88
+ from .meta.persistence.origin.origin_constants import (
89
+ ORIGIN_ATTR_AGG,
90
+ ORIGIN_ATTR_FROM,
91
+ ORIGIN_ATTR_OF,
92
+ ORIGIN_ATTR_VIA,
93
+ ORIGIN_SUBTYPE_AGGREGATE,
94
+ ORIGIN_SUBTYPE_COLLECTION,
95
+ ORIGIN_SUBTYPE_PASSTHROUGH,
96
+ )
97
+ from .meta.template.meta_template import MetaTemplate
98
+ from .meta.template import template_constants as tc
99
+ from .meta.persistence.source.meta_source import MetaSource
100
+ from .meta.persistence.source.source_constants import (
101
+ SOURCE_ATTR_FUNCTION,
102
+ SOURCE_ATTR_KIND,
103
+ SOURCE_ATTR_MATERIALIZED_VIEW,
104
+ SOURCE_ATTR_PARAMETER_REF,
105
+ SOURCE_ATTR_PROC,
106
+ SOURCE_ATTR_ROLE,
107
+ SOURCE_ATTR_SCHEMA,
108
+ SOURCE_ATTR_TABLE,
109
+ SOURCE_ATTR_VIEW,
110
+ SOURCE_RDB_KINDS,
111
+ SOURCE_ROLES,
112
+ SOURCE_SUBTYPE_RDB,
113
+ )
114
+ from .meta.presentation.layout.layout_constants import (
115
+ LAYOUT_ATTR_COLUMNS,
116
+ LAYOUT_ATTR_DEFAULT_SORT_FIELD,
117
+ LAYOUT_ATTR_DEFAULT_SORT_ORDER,
118
+ LAYOUT_ATTR_FILTER,
119
+ LAYOUT_ATTR_FILTERABLE,
120
+ LAYOUT_ATTR_PAGE_SIZE,
121
+ LAYOUT_SUBTYPES,
122
+ LAYOUT_SUBTYPE_DATA_GRID,
123
+ )
124
+ from .meta.presentation.layout.meta_layout import MetaLayout
125
+ from .meta.presentation.view.meta_view import MetaView
126
+ from .meta.presentation.view.view_constants import (
127
+ VIEW_ATTR_LOCALE,
128
+ VIEW_SUBTYPE_CURRENCY,
129
+ VIEW_SUBTYPES,
130
+ )
131
+ from .provider import Provider
132
+ from .registry import AttrSchema, ChildRule, NodeFactory, TypeDefinition, TypeRegistry
133
+ from .shared.base_types import (
134
+ SUBTYPE_BASE,
135
+ SUBTYPE_ROOT,
136
+ TYPE_ATTR,
137
+ TYPE_FIELD,
138
+ TYPE_IDENTITY,
139
+ TYPE_LAYOUT,
140
+ TYPE_METADATA,
141
+ TYPE_OBJECT,
142
+ TYPE_ORIGIN,
143
+ TYPE_RELATIONSHIP,
144
+ TYPE_SOURCE,
145
+ TYPE_TEMPLATE,
146
+ TYPE_VALIDATOR,
147
+ TYPE_VIEW,
148
+ )
149
+
150
+ class _CoreProvider(Provider):
151
+ """Subclass of Provider that also designates default subTypes for YAML authoring (ADR-0006).
152
+
153
+ `metadata` has exactly one subtype (`root`) so the default is unambiguous;
154
+ `object` defaults to `entity` (the common case). Other types (field,
155
+ validator, ...) have no default — authoring always writes the full
156
+ `type.subType`. Mirrors registerCoreTypeDefs in TS core-types.ts.
157
+ """
158
+
159
+ def register_types(self, registry: TypeRegistry) -> None:
160
+ super().register_types(registry)
161
+ registry.set_default_sub_type(TYPE_METADATA, SUBTYPE_ROOT)
162
+ registry.set_default_sub_type(TYPE_OBJECT, OBJECT_SUBTYPE_ENTITY)
163
+
164
+
165
+ core_provider = _CoreProvider("metaobjects-core-types")
166
+
167
+
168
+ def _register_subtypes(
169
+ provider: Provider,
170
+ type_name: str,
171
+ subtypes: tuple[str, ...],
172
+ factory: NodeFactory,
173
+ child_rules: list[ChildRule] | None = None,
174
+ attrs: list[AttrSchema] | None = None,
175
+ ) -> None:
176
+ """Register one TypeDefinition per subtype. Centralises loop boilerplate only —
177
+ all type knowledge (subtypes tuple, node class, child rules) stays with the caller."""
178
+ for sub in subtypes:
179
+ provider.add(
180
+ TypeDefinition(
181
+ type=type_name,
182
+ sub_type=sub,
183
+ factory=factory,
184
+ child_rules=list(child_rules) if child_rules else [],
185
+ attrs=list(attrs) if attrs else [],
186
+ )
187
+ )
188
+
189
+
190
+ # metadata.root — accepts top-level objects, root-level fields (shared abstracts),
191
+ # and template.* (FR-004).
192
+ core_provider.add(
193
+ TypeDefinition(
194
+ type=TYPE_METADATA,
195
+ sub_type=SUBTYPE_ROOT,
196
+ factory=MetaRoot,
197
+ child_rules=[
198
+ ChildRule(TYPE_OBJECT, "*"),
199
+ ChildRule(TYPE_FIELD, "*"),
200
+ ChildRule(TYPE_TEMPLATE, "*"),
201
+ ],
202
+ )
203
+ )
204
+
205
+ # object.* (entity, value)
206
+ _OBJECT_CHILD_RULES = [
207
+ ChildRule(TYPE_FIELD, "*"),
208
+ ChildRule(TYPE_IDENTITY, "*"),
209
+ ChildRule(TYPE_ATTR, "*"),
210
+ ChildRule(TYPE_SOURCE, "*"),
211
+ ChildRule(TYPE_RELATIONSHIP, "*"),
212
+ ChildRule(TYPE_LAYOUT, "*"),
213
+ # template.* under object.entity — a declared prompt/output lives WITH its
214
+ # entity (AI LLM-call trace persistence; the trace entity carries a nested
215
+ # template.prompt). Mirrors Java MetaObject.optionalChild("template","*","*").
216
+ ChildRule(TYPE_TEMPLATE, "*"),
217
+ ]
218
+ # FR-014: @discriminator / @discriminatorValue (TPH single-table inheritance) are
219
+ # registered on EVERY object subtype (base/entity/value) — cross-port contract.
220
+ _OBJECT_COMMON_ATTRS = [
221
+ AttrSchema(name=OBJECT_ATTR_DISCRIMINATOR, value_type=ATTR_SUBTYPE_STRING, required=False),
222
+ AttrSchema(
223
+ name=OBJECT_ATTR_DISCRIMINATOR_VALUE,
224
+ value_type=ATTR_SUBTYPE_STRING,
225
+ required=False,
226
+ ),
227
+ ]
228
+ # FR-011: @normalize is an object-level default for the enum fields of a payload
229
+ # value-object — registered on object.value ONLY (not entity/base). Closed enum
230
+ # (none|collapse|strip, default strip); resolved at codegen time when a field
231
+ # omits its own @normalize.
232
+ _OBJECT_VALUE_ATTRS = list(_OBJECT_COMMON_ATTRS) + [
233
+ AttrSchema(
234
+ name=FIELD_ATTR_NORMALIZE,
235
+ value_type=ATTR_SUBTYPE_STRING,
236
+ required=False,
237
+ allowed_values=NORMALIZE_MODES,
238
+ default=NORMALIZE_DEFAULT,
239
+ ),
240
+ ]
241
+ for _obj_sub in OBJECT_SUBTYPES:
242
+ core_provider.add(
243
+ TypeDefinition(
244
+ type=TYPE_OBJECT,
245
+ sub_type=_obj_sub,
246
+ factory=MetaObject,
247
+ child_rules=list(_OBJECT_CHILD_RULES),
248
+ attrs=(
249
+ list(_OBJECT_VALUE_ATTRS)
250
+ if _obj_sub == OBJECT_SUBTYPE_VALUE
251
+ else list(_OBJECT_COMMON_ATTRS)
252
+ ),
253
+ )
254
+ )
255
+
256
+ # field.* (one factory, data_type by subtype)
257
+ # Note: FIELD_SUBTYPE_ENUM is excluded from FIELD_SUBTYPES; it is registered
258
+ # separately below with its required @values AttrSchema (sharing these child rules).
259
+ _FIELD_CHILD_RULES = [
260
+ ChildRule(TYPE_ATTR, "*"),
261
+ ChildRule(TYPE_ORIGIN, "*"),
262
+ ChildRule(TYPE_VIEW, "*"),
263
+ ChildRule(TYPE_VALIDATOR, "*"),
264
+ ]
265
+ # Common field attrs declared by the core port. Each attr carries a declared
266
+ # `value_type` so the YAML desugar's D2 type-coercion guard (ADR-0006) can
267
+ # detect a YAML 1.2 silently-coerced unquoted value (e.g. `maxLength: true`
268
+ # coerced to boolean instead of the int it should be).
269
+ #
270
+ # Mirrors server/typescript/packages/metadata/src/core/field/field-schema.ts
271
+ # `commonFieldAttrs` and server/csharp/MetaObjects/Core/Field/FieldSchema.cs
272
+ # `CommonFieldAttrs` so Python's coercion coverage stays at parity.
273
+ #
274
+ # The TS port registers `@column` through a dedicated dbProvider that extends
275
+ # field types; Python keeps it on the core field defs until a full Python
276
+ # db-codegen port lands.
277
+ _FIELD_COMMON_ATTRS = [
278
+ AttrSchema(name=FIELD_ATTR_OBJECT_REF, value_type=ATTR_SUBTYPE_STRING, required=False),
279
+ # @storage applies to field.object only (cross-port); validation_passes enforces
280
+ # the shape rules + non-object-subtype guard. Declared at the common level so
281
+ # the AttrSchema parser doesn't reject it on field.object before validation runs.
282
+ AttrSchema(
283
+ name=FIELD_ATTR_STORAGE,
284
+ value_type=ATTR_SUBTYPE_STRING,
285
+ required=False,
286
+ allowed_values=STORAGE_VALUES,
287
+ ),
288
+ AttrSchema(name=FIELD_ATTR_REQUIRED, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
289
+ # @readOnly — field exposed read-only (omitted from create/update input DTOs).
290
+ # Cross-port logical field attr (every field subtype). Mirrors TS commonFieldAttrs.
291
+ AttrSchema(name=FIELD_ATTR_READ_ONLY, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
292
+ AttrSchema(name=FIELD_ATTR_UNIQUE, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
293
+ # @db.indexed — DB-domain index-intent flag on every field subtype. The TS
294
+ # port registers it through a dedicated metaobjects-db provider; Python keeps
295
+ # the DB-domain physical attrs (@column / @dbColumnType / @db.indexed) on the
296
+ # core field defs (same rationale as @column / @dbColumnType below).
297
+ AttrSchema(name=FIELD_ATTR_DB_INDEXED, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
298
+ # @default is polymorphic: its value type follows the OWNING field's
299
+ # subtype. No single fixed valueType can capture that, so value_type is
300
+ # intentionally None (declared-but-untyped). The YAML coercion guard
301
+ # skips entries with value_type=None.
302
+ AttrSchema(name=FIELD_ATTR_DEFAULT, value_type=None, required=False),
303
+ AttrSchema(name=FIELD_ATTR_MAX_LENGTH, value_type=ATTR_SUBTYPE_INT, required=False),
304
+ AttrSchema(name=FIELD_ATTR_PRECISION, value_type=ATTR_SUBTYPE_INT, required=False),
305
+ AttrSchema(name=FIELD_ATTR_SCALE, value_type=ATTR_SUBTYPE_INT, required=False),
306
+ AttrSchema(name=FIELD_ATTR_FILTERABLE, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
307
+ AttrSchema(name=FIELD_ATTR_SORTABLE, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
308
+ AttrSchema(
309
+ name=FIELD_ATTR_SORTABLE_DEFAULT_ORDER,
310
+ value_type=ATTR_SUBTYPE_STRING,
311
+ required=False,
312
+ allowed_values=SORT_ORDER_VALUES,
313
+ ),
314
+ AttrSchema(
315
+ name=FIELD_ATTR_AUTO_SET,
316
+ value_type=ATTR_SUBTYPE_STRING,
317
+ required=False,
318
+ allowed_values=AUTO_SET_VALUES,
319
+ ),
320
+ # NOTE: the DB-domain physical field attrs (@column, @dbColumnType) are NOT
321
+ # declared here — they are DB-domain concerns registered by the dedicated
322
+ # `db_provider` (metaobjects-db) via TypeRegistry.extend, mirroring the
323
+ # cross-port end-state (Java CoreDBMetaDataProvider / TS dbProvider / C#
324
+ # DbMetaDataProvider). The @dbColumnType (subtype × value) pairing legality is
325
+ # still enforced by the loader's _validate_db_column_type pass (unconditional).
326
+ # FR-010 field-teaching attrs (any field): free-text shown in the generated
327
+ # output-format prompt fragment. Never carried in comments.
328
+ AttrSchema(name=FIELD_ATTR_EXAMPLE, value_type=ATTR_SUBTYPE_STRING, required=False),
329
+ AttrSchema(name=FIELD_ATTR_INSTRUCTION, value_type=ATTR_SUBTYPE_STRING, required=False),
330
+ ]
331
+ _register_subtypes(
332
+ core_provider,
333
+ TYPE_FIELD,
334
+ fc.FIELD_SUBTYPES,
335
+ factory=MetaField,
336
+ child_rules=_FIELD_CHILD_RULES,
337
+ attrs=_FIELD_COMMON_ATTRS,
338
+ )
339
+
340
+ # field.currency carries the @currency attr (ISO 4217) IN ADDITION to the common
341
+ # field attrs. The bulk loop above registered field.currency with the common
342
+ # attrs; append @currency to that definition (mirrors TS, where field.currency's
343
+ # attr set = commonFieldAttrs + currencyFieldAttr).
344
+ for _def in core_provider._defs: # noqa: SLF001 (provider build-time enrichment)
345
+ if _def.type == TYPE_FIELD and _def.sub_type == fc.FIELD_SUBTYPE_CURRENCY:
346
+ _def.attrs.append(
347
+ AttrSchema(name=FIELD_ATTR_CURRENCY, value_type=ATTR_SUBTYPE_STRING, required=False)
348
+ )
349
+ break
350
+
351
+ # field.enum — dedicated registration with required @values attr.
352
+ # Inherits every common field attr (column / required / unique / default /
353
+ # maxLength / filterable / sortable / etc.) so the D2 type-coercion guard
354
+ # applies uniformly across all fields.
355
+ core_provider.add(
356
+ TypeDefinition(
357
+ type=TYPE_FIELD,
358
+ sub_type=FIELD_SUBTYPE_ENUM,
359
+ factory=MetaField,
360
+ attrs=list(_FIELD_COMMON_ATTRS) + [
361
+ AttrSchema(
362
+ name=FIELD_ATTR_VALUES,
363
+ value_type=ATTR_SUBTYPE_STRING,
364
+ required=True,
365
+ is_array=True,
366
+ ),
367
+ # FR-010: properties-shaped maps, field.enum only.
368
+ # @enumAlias: off-vocabulary token -> canonical member (extract alias-fold).
369
+ # @enumDoc: member -> human-readable description (guide prompt fragment).
370
+ AttrSchema(
371
+ name=FIELD_ATTR_ENUM_ALIAS,
372
+ value_type=ATTR_SUBTYPE_PROPERTIES,
373
+ required=False,
374
+ ),
375
+ AttrSchema(
376
+ name=FIELD_ATTR_ENUM_DOC,
377
+ value_type=ATTR_SUBTYPE_PROPERTIES,
378
+ required=False,
379
+ ),
380
+ # FR-011: present-but-uncoercible extract fallback member. Membership
381
+ # against the effective @values is validated post-load in
382
+ # validation_passes (ERR_BAD_ATTR_VALUE), mirroring the @values pass.
383
+ AttrSchema(
384
+ name=FIELD_ATTR_COERCE_DEFAULT,
385
+ value_type=ATTR_SUBTYPE_STRING,
386
+ required=False,
387
+ ),
388
+ # FR-011: per-field ASCII normalization mode for tolerant enum extract.
389
+ # Closed enum (none|collapse|strip); allowed_values gates it →
390
+ # ERR_BAD_ATTR_VALUE. The default ("strip") is resolved at codegen time
391
+ # (field → owning object.value → "strip").
392
+ AttrSchema(
393
+ name=FIELD_ATTR_NORMALIZE,
394
+ value_type=ATTR_SUBTYPE_STRING,
395
+ required=False,
396
+ allowed_values=NORMALIZE_MODES,
397
+ default=NORMALIZE_DEFAULT,
398
+ ),
399
+ ],
400
+ child_rules=_FIELD_CHILD_RULES,
401
+ )
402
+ )
403
+
404
+ # attr.* (factory resolved per subtype via the attr-class map at parse time)
405
+ _register_subtypes(
406
+ core_provider,
407
+ TYPE_ATTR,
408
+ ATTR_SUBTYPES,
409
+ factory=lambda t, s, n: attr_class_for(s)(t, s, n),
410
+ )
411
+
412
+ # identity.primary — @fields required stringArray; @generation optional with allowed values
413
+ core_provider.add(
414
+ TypeDefinition(
415
+ type=TYPE_IDENTITY,
416
+ sub_type=IDENTITY_SUBTYPE_PRIMARY,
417
+ factory=MetaIdentity,
418
+ attrs=[
419
+ AttrSchema(name=IDENTITY_ATTR_FIELDS, value_type=ATTR_SUBTYPE_STRING, required=True, is_array=True),
420
+ AttrSchema(
421
+ name=IDENTITY_ATTR_GENERATION,
422
+ value_type=ATTR_SUBTYPE_STRING,
423
+ required=False,
424
+ allowed_values=GENERATION_VALUES,
425
+ ),
426
+ ],
427
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
428
+ )
429
+ )
430
+
431
+ # identity.secondary — @fields required stringArray; @unique optional boolean
432
+ # (true → UNIQUE index, false → plain index). Cross-port; mirrors TS secondaryIdentityAttrs.
433
+ core_provider.add(
434
+ TypeDefinition(
435
+ type=TYPE_IDENTITY,
436
+ sub_type=IDENTITY_SUBTYPE_SECONDARY,
437
+ factory=MetaIdentity,
438
+ attrs=[
439
+ AttrSchema(name=IDENTITY_ATTR_FIELDS, value_type=ATTR_SUBTYPE_STRING, required=True, is_array=True),
440
+ AttrSchema(name=IDENTITY_ATTR_UNIQUE, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
441
+ ],
442
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
443
+ )
444
+ )
445
+
446
+ # identity.reference — @fields (required), @references (required), @enforce (optional boolean)
447
+ core_provider.add(
448
+ TypeDefinition(
449
+ type=TYPE_IDENTITY,
450
+ sub_type=IDENTITY_SUBTYPE_REFERENCE,
451
+ factory=MetaIdentity,
452
+ attrs=[
453
+ AttrSchema(name=IDENTITY_ATTR_FIELDS, value_type=ATTR_SUBTYPE_STRING, required=True, is_array=True),
454
+ AttrSchema(name=IDENTITY_REFERENCE_ATTR_REFERENCES, value_type=ATTR_SUBTYPE_STRING, required=True),
455
+ AttrSchema(name=IDENTITY_REFERENCE_ATTR_ENFORCE, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
456
+ ],
457
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
458
+ )
459
+ )
460
+
461
+ # relationship.* (base, association, aggregation, composition).
462
+ # @onDelete / @onUpdate are validated against REFERENTIAL_ACTIONS — kebab-case
463
+ # values (cascade / set-null / restrict / no-action). Defaults derive from the
464
+ # relationship subtype at consumption time, not at validation time.
465
+ _RELATIONSHIP_ATTRS = [
466
+ # Logical relationship attrs (cross-port; on every relationship subtype incl. base).
467
+ # @cardinality is an open string at the metamodel level (no allowed_values) — the
468
+ # legal-value check is a downstream concern, matching TS.
469
+ AttrSchema(name=RELATIONSHIP_ATTR_CARDINALITY, value_type=ATTR_SUBTYPE_STRING, required=False),
470
+ AttrSchema(name=RELATIONSHIP_ATTR_OBJECT_REF, value_type=ATTR_SUBTYPE_STRING, required=False),
471
+ # FR-017 slim M:N vocabulary — @through (junction entity), @sourceRefField
472
+ # (directed-self-join disambiguator), @symmetric (undirected-self-join flag).
473
+ # The pre-FR-017 @joinEntity/@joinFields attrs are REMOVED (FK fields derive
474
+ # from the junction's two identity.reference children).
475
+ AttrSchema(name=RELATIONSHIP_ATTR_THROUGH, value_type=ATTR_SUBTYPE_STRING, required=False),
476
+ AttrSchema(name=RELATIONSHIP_ATTR_SOURCE_REF_FIELD, value_type=ATTR_SUBTYPE_STRING, required=False),
477
+ AttrSchema(name=RELATIONSHIP_ATTR_SYMMETRIC, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
478
+ AttrSchema(
479
+ name=RELATIONSHIP_ATTR_ON_DELETE,
480
+ value_type=ATTR_SUBTYPE_STRING,
481
+ required=False,
482
+ allowed_values=REFERENTIAL_ACTIONS,
483
+ ),
484
+ AttrSchema(
485
+ name=RELATIONSHIP_ATTR_ON_UPDATE,
486
+ value_type=ATTR_SUBTYPE_STRING,
487
+ required=False,
488
+ allowed_values=REFERENTIAL_ACTIONS,
489
+ ),
490
+ ]
491
+ _register_subtypes(
492
+ core_provider,
493
+ TYPE_RELATIONSHIP,
494
+ RELATIONSHIP_SUBTYPES,
495
+ factory=MetaRelationship,
496
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
497
+ attrs=_RELATIONSHIP_ATTRS,
498
+ )
499
+
500
+ # source.* — base (no attrs) + rdb (paradigm subtype with @table/@kind/@role/@schema).
501
+ # ADR-0007: read-only-ness is derived from @kind; multi-source one-primary rule is
502
+ # enforced in validation_passes.py.
503
+ core_provider.add(
504
+ TypeDefinition(
505
+ type=TYPE_SOURCE,
506
+ sub_type=SUBTYPE_BASE,
507
+ factory=MetaSource,
508
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
509
+ )
510
+ )
511
+ core_provider.add(
512
+ TypeDefinition(
513
+ type=TYPE_SOURCE,
514
+ sub_type=SOURCE_SUBTYPE_RDB,
515
+ factory=MetaSource,
516
+ attrs=[
517
+ # FR-016 / ADR-0018 — per-kind physical-name aliases (all five fill
518
+ # the same internal slot; only one may be set per source).
519
+ AttrSchema(name=SOURCE_ATTR_TABLE, value_type=ATTR_SUBTYPE_STRING, required=False),
520
+ AttrSchema(name=SOURCE_ATTR_VIEW, value_type=ATTR_SUBTYPE_STRING, required=False),
521
+ AttrSchema(
522
+ name=SOURCE_ATTR_MATERIALIZED_VIEW,
523
+ value_type=ATTR_SUBTYPE_STRING,
524
+ required=False,
525
+ ),
526
+ AttrSchema(name=SOURCE_ATTR_PROC, value_type=ATTR_SUBTYPE_STRING, required=False),
527
+ AttrSchema(name=SOURCE_ATTR_FUNCTION, value_type=ATTR_SUBTYPE_STRING, required=False),
528
+ AttrSchema(
529
+ name=SOURCE_ATTR_KIND,
530
+ value_type=ATTR_SUBTYPE_STRING,
531
+ required=False,
532
+ allowed_values=SOURCE_RDB_KINDS,
533
+ ),
534
+ AttrSchema(
535
+ name=SOURCE_ATTR_ROLE,
536
+ value_type=ATTR_SUBTYPE_STRING,
537
+ required=False,
538
+ allowed_values=SOURCE_ROLES,
539
+ ),
540
+ AttrSchema(name=SOURCE_ATTR_SCHEMA, value_type=ATTR_SUBTYPE_STRING, required=False),
541
+ # FR-015 — @parameterRef: input-shape object.value for proc/table-function sources.
542
+ AttrSchema(
543
+ name=SOURCE_ATTR_PARAMETER_REF,
544
+ value_type=ATTR_SUBTYPE_STRING,
545
+ required=False,
546
+ ),
547
+ ],
548
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
549
+ )
550
+ )
551
+
552
+ # origin.base — no schema (pass-through container)
553
+ core_provider.add(
554
+ TypeDefinition(
555
+ type=TYPE_ORIGIN,
556
+ sub_type=SUBTYPE_BASE,
557
+ factory=MetaOrigin,
558
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
559
+ )
560
+ )
561
+
562
+ # origin.passthrough — @from required, @via optional
563
+ core_provider.add(
564
+ TypeDefinition(
565
+ type=TYPE_ORIGIN,
566
+ sub_type=ORIGIN_SUBTYPE_PASSTHROUGH,
567
+ factory=MetaOrigin,
568
+ attrs=[
569
+ AttrSchema(name=ORIGIN_ATTR_FROM, value_type=ATTR_SUBTYPE_STRING, required=True),
570
+ AttrSchema(name=ORIGIN_ATTR_VIA, value_type=ATTR_SUBTYPE_STRING, required=False),
571
+ ],
572
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
573
+ )
574
+ )
575
+
576
+ # origin.aggregate — @agg, @of, @via all required; @agg has allowed values
577
+ _AGG_ALLOWED = ("count", "sum", "avg", "min", "max")
578
+ core_provider.add(
579
+ TypeDefinition(
580
+ type=TYPE_ORIGIN,
581
+ sub_type=ORIGIN_SUBTYPE_AGGREGATE,
582
+ factory=MetaOrigin,
583
+ attrs=[
584
+ AttrSchema(
585
+ name=ORIGIN_ATTR_AGG,
586
+ value_type=ATTR_SUBTYPE_STRING,
587
+ required=True,
588
+ allowed_values=_AGG_ALLOWED,
589
+ ),
590
+ AttrSchema(name=ORIGIN_ATTR_OF, value_type=ATTR_SUBTYPE_STRING, required=True),
591
+ AttrSchema(name=ORIGIN_ATTR_VIA, value_type=ATTR_SUBTYPE_STRING, required=True),
592
+ ],
593
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
594
+ )
595
+ )
596
+
597
+ # origin.collection — owned-array origin (@via required, points at a relationship path).
598
+ # Mirrors Java's CollectionOrigin / TS origin.collection. Path traversal is intentionally
599
+ # NOT enforced here (matches TS).
600
+ core_provider.add(
601
+ TypeDefinition(
602
+ type=TYPE_ORIGIN,
603
+ sub_type=ORIGIN_SUBTYPE_COLLECTION,
604
+ factory=MetaOrigin,
605
+ attrs=[
606
+ AttrSchema(name=ORIGIN_ATTR_VIA, value_type=ATTR_SUBTYPE_STRING, required=True),
607
+ ],
608
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
609
+ )
610
+ )
611
+
612
+ # view.* (base + 13 control kinds). Only view.currency carries a documented attr
613
+ # (@locale); all other subtypes have none. Mirrors TS core-types view registration.
614
+ for _view_sub in VIEW_SUBTYPES:
615
+ _view_attrs = (
616
+ [AttrSchema(name=VIEW_ATTR_LOCALE, value_type=ATTR_SUBTYPE_STRING, required=False)]
617
+ if _view_sub == VIEW_SUBTYPE_CURRENCY
618
+ else []
619
+ )
620
+ core_provider.add(
621
+ TypeDefinition(
622
+ type=TYPE_VIEW,
623
+ sub_type=_view_sub,
624
+ factory=MetaView,
625
+ attrs=_view_attrs,
626
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
627
+ )
628
+ )
629
+
630
+ # layout.* (base, dataGrid); @columns is a stringArray — scalar desugars to array;
631
+ # @filter is a FilterAttr — shorthand values desugar to op-objects
632
+ _layout_datagrid_attrs = [
633
+ AttrSchema(name=LAYOUT_ATTR_COLUMNS, value_type=ATTR_SUBTYPE_STRING, is_array=True),
634
+ AttrSchema(name=LAYOUT_ATTR_DEFAULT_SORT_FIELD, value_type=ATTR_SUBTYPE_STRING),
635
+ AttrSchema(
636
+ name=LAYOUT_ATTR_DEFAULT_SORT_ORDER,
637
+ value_type=ATTR_SUBTYPE_STRING,
638
+ allowed_values=("asc", "desc"),
639
+ ),
640
+ AttrSchema(name=LAYOUT_ATTR_PAGE_SIZE, value_type=ATTR_SUBTYPE_INT),
641
+ # @filterable — boolean; the generated grid exposes column-filtering UI. Cross-port.
642
+ AttrSchema(name=LAYOUT_ATTR_FILTERABLE, value_type=ATTR_SUBTYPE_BOOLEAN),
643
+ AttrSchema(name=LAYOUT_ATTR_FILTER, value_type=ATTR_SUBTYPE_FILTER),
644
+ ]
645
+ for _sub in LAYOUT_SUBTYPES:
646
+ _attrs = list(_layout_datagrid_attrs) if _sub == LAYOUT_SUBTYPE_DATA_GRID else []
647
+ core_provider.add(
648
+ TypeDefinition(
649
+ type=TYPE_LAYOUT,
650
+ sub_type=_sub,
651
+ factory=MetaLayout,
652
+ attrs=_attrs,
653
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
654
+ )
655
+ )
656
+
657
+ # validator.* — base + required/length/regex/numeric/array. Subtype + attr
658
+ # vocabulary is cross-port identical (mirrors TS VALIDATOR_ATTRS_MAP). @min/@max
659
+ # are shared by base/length/numeric/array; regex adds @pattern. Codegen reads these
660
+ # children to emit each port's input-validation constraints (SP-C validator parity).
661
+ _VALIDATOR_MIN_MAX_ATTRS = [
662
+ AttrSchema(name=vc.VALIDATOR_ATTR_MIN, value_type=ATTR_SUBTYPE_INT),
663
+ AttrSchema(name=vc.VALIDATOR_ATTR_MAX, value_type=ATTR_SUBTYPE_INT),
664
+ ]
665
+ _VALIDATOR_ATTRS_BY_SUBTYPE: dict[str, list[AttrSchema]] = {
666
+ SUBTYPE_BASE: list(_VALIDATOR_MIN_MAX_ATTRS),
667
+ vc.VALIDATOR_SUBTYPE_REQUIRED: [],
668
+ vc.VALIDATOR_SUBTYPE_LENGTH: list(_VALIDATOR_MIN_MAX_ATTRS),
669
+ vc.VALIDATOR_SUBTYPE_REGEX: [
670
+ *_VALIDATOR_MIN_MAX_ATTRS,
671
+ AttrSchema(name=vc.VALIDATOR_ATTR_PATTERN, value_type=ATTR_SUBTYPE_STRING),
672
+ ],
673
+ vc.VALIDATOR_SUBTYPE_NUMERIC: list(_VALIDATOR_MIN_MAX_ATTRS),
674
+ vc.VALIDATOR_SUBTYPE_ARRAY: list(_VALIDATOR_MIN_MAX_ATTRS),
675
+ }
676
+ for _sub, _attrs in _VALIDATOR_ATTRS_BY_SUBTYPE.items():
677
+ core_provider.add(
678
+ TypeDefinition(
679
+ type=TYPE_VALIDATOR,
680
+ sub_type=_sub,
681
+ factory=lambda t, s, n: MetaData(t, s, n),
682
+ attrs=list(_attrs),
683
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
684
+ )
685
+ )
686
+
687
+ # template.* (FR-004) — base + prompt + output + toolcall. @payloadRef / @textRef
688
+ # / @format / @maxChars / @owner / @since / @requiredTags are shared across prompt
689
+ # + output; prompt also carries @maxTokens / @requiredSlots / @model. toolcall
690
+ # (ADR-0011) does NOT inherit the shared attrs — it declares its own
691
+ # (@toolName required + @payloadRef required + @owner + @since). No @textRef
692
+ # requirement: a tool-call has no renderable text body.
693
+ # Validation in validation_passes.py.
694
+ _TEMPLATE_SHARED_ATTRS = [
695
+ # @payloadRef is required on the concrete subtypes (output/prompt). The generic
696
+ # required-attr schema check (validation_passes Check 1) enforces it — there is
697
+ # no separate manual pass (matches TS). template.base gets NO shared attrs.
698
+ AttrSchema(name=tc.TEMPLATE_ATTR_PAYLOAD_REF, value_type=ATTR_SUBTYPE_STRING, required=True),
699
+ AttrSchema(name=tc.TEMPLATE_ATTR_TEXT_REF, value_type=ATTR_SUBTYPE_STRING),
700
+ AttrSchema(
701
+ name=tc.TEMPLATE_ATTR_FORMAT,
702
+ value_type=ATTR_SUBTYPE_STRING,
703
+ allowed_values=tc.ALLOWED_FORMATS,
704
+ ),
705
+ AttrSchema(name=tc.TEMPLATE_ATTR_MAX_CHARS, value_type=ATTR_SUBTYPE_INT),
706
+ AttrSchema(name=tc.TEMPLATE_ATTR_OWNER, value_type=ATTR_SUBTYPE_STRING),
707
+ AttrSchema(name=tc.TEMPLATE_ATTR_SINCE, value_type=ATTR_SUBTYPE_STRING),
708
+ AttrSchema(name=tc.TEMPLATE_ATTR_REQUIRED_TAGS, value_type=ATTR_SUBTYPE_STRING, is_array=True),
709
+ ]
710
+ # template.output also carries the FR-010 @promptStyle presentation attr — a
711
+ # closed enum (allowed_values), default "guide". NOT on prompt/toolcall.
712
+ #
713
+ # It also carries @kind (closed enum document|email, default "document") + the
714
+ # email part-refs (@subjectRef / @htmlBodyRef / @textBodyRef). @kind closed-enum
715
+ # membership is enforced via allowed_values (ERR_BAD_ATTR_VALUE), exactly like
716
+ # @format / @promptStyle; the conditional ref requirements live in
717
+ # validation_passes._validate_templates. @textRef is left non-required here (it is
718
+ # conditionally required by kind), matching TS/Java. NOT on prompt/toolcall.
719
+ _TEMPLATE_OUTPUT_ATTRS = list(_TEMPLATE_SHARED_ATTRS) + [
720
+ AttrSchema(
721
+ name=tc.TEMPLATE_ATTR_PROMPT_STYLE,
722
+ value_type=ATTR_SUBTYPE_STRING,
723
+ allowed_values=tc.PROMPT_STYLES,
724
+ default=tc.PROMPT_STYLE_DEFAULT,
725
+ ),
726
+ AttrSchema(
727
+ name=tc.TEMPLATE_ATTR_KIND,
728
+ value_type=ATTR_SUBTYPE_STRING,
729
+ allowed_values=tc.ALLOWED_KINDS,
730
+ default=tc.TEMPLATE_KIND_DEFAULT,
731
+ ),
732
+ AttrSchema(name=tc.TEMPLATE_ATTR_SUBJECT_REF, value_type=ATTR_SUBTYPE_STRING),
733
+ AttrSchema(name=tc.TEMPLATE_ATTR_HTML_BODY_REF, value_type=ATTR_SUBTYPE_STRING),
734
+ AttrSchema(name=tc.TEMPLATE_ATTR_TEXT_BODY_REF, value_type=ATTR_SUBTYPE_STRING),
735
+ ]
736
+ _TEMPLATE_PROMPT_ATTRS = list(_TEMPLATE_SHARED_ATTRS) + [
737
+ AttrSchema(name=tc.TEMPLATE_ATTR_MAX_TOKENS, value_type=ATTR_SUBTYPE_INT),
738
+ AttrSchema(name=tc.TEMPLATE_ATTR_REQUIRED_SLOTS, value_type=ATTR_SUBTYPE_STRING, is_array=True),
739
+ AttrSchema(name=tc.TEMPLATE_ATTR_MODEL, value_type=ATTR_SUBTYPE_STRING),
740
+ # @responseRef — template.prompt ONLY (AI trace; peer of @payloadRef).
741
+ # Cross-port vocabulary (registered in all five ports).
742
+ AttrSchema(name=tc.TEMPLATE_ATTR_RESPONSE_REF, value_type=ATTR_SUBTYPE_STRING, required=False),
743
+ ]
744
+ _TEMPLATE_TOOLCALL_ATTRS = [
745
+ AttrSchema(name=tc.TEMPLATE_ATTR_TOOL_NAME, value_type=ATTR_SUBTYPE_STRING, required=True),
746
+ AttrSchema(name=tc.TEMPLATE_ATTR_PAYLOAD_REF, value_type=ATTR_SUBTYPE_STRING, required=True),
747
+ AttrSchema(name=tc.TEMPLATE_ATTR_OWNER, value_type=ATTR_SUBTYPE_STRING),
748
+ AttrSchema(name=tc.TEMPLATE_ATTR_SINCE, value_type=ATTR_SUBTYPE_STRING),
749
+ ]
750
+ # template.base — abstract anchor; carries NO attrs (the shared attrs live only on
751
+ # the concrete subtypes prompt/output, matching TS TEMPLATE_ATTRS_MAP[base] = []).
752
+ core_provider.add(
753
+ TypeDefinition(
754
+ type=TYPE_TEMPLATE,
755
+ sub_type=SUBTYPE_BASE,
756
+ factory=MetaTemplate,
757
+ attrs=[],
758
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
759
+ )
760
+ )
761
+ core_provider.add(
762
+ TypeDefinition(
763
+ type=TYPE_TEMPLATE,
764
+ sub_type=tc.TEMPLATE_SUBTYPE_OUTPUT,
765
+ factory=MetaTemplate,
766
+ attrs=list(_TEMPLATE_OUTPUT_ATTRS),
767
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
768
+ )
769
+ )
770
+ core_provider.add(
771
+ TypeDefinition(
772
+ type=TYPE_TEMPLATE,
773
+ sub_type=tc.TEMPLATE_SUBTYPE_PROMPT,
774
+ factory=MetaTemplate,
775
+ attrs=list(_TEMPLATE_PROMPT_ATTRS),
776
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
777
+ )
778
+ )
779
+ core_provider.add(
780
+ TypeDefinition(
781
+ type=TYPE_TEMPLATE,
782
+ sub_type=tc.TEMPLATE_SUBTYPE_TOOLCALL,
783
+ factory=MetaTemplate,
784
+ attrs=list(_TEMPLATE_TOOLCALL_ATTRS),
785
+ child_rules=[ChildRule(TYPE_ATTR, "*")],
786
+ )
787
+ )
788
+
789
+
790
+ # ---------------------------------------------------------------------------
791
+ # The canonical default provider set (cross-port `coreProviders`).
792
+ #
793
+ # Mirrors TS's `coreProviders = [coreTypesProvider, dbProvider, docProvider,
794
+ # templateProvider]` and C#'s DefaultRegistry composition. The core types are
795
+ # registered first; the DB-domain (`db_provider`) and template/output domain
796
+ # (`template_provider`) then EXTEND the core field types via TypeRegistry.extend,
797
+ # and the documentation provider adds the common doc attrs. Spread to add more:
798
+ # `[*core_providers, my_provider]`.
799
+ # ---------------------------------------------------------------------------
800
+ from .meta.persistence.db.db_provider import db_provider # noqa: E402
801
+ from .meta.template.template_provider import template_provider # noqa: E402
802
+ from .documentation.doc_provider import doc_provider # noqa: E402
803
+
804
+ core_providers: list[Provider] = [
805
+ core_provider,
806
+ db_provider,
807
+ doc_provider,
808
+ template_provider,
809
+ ]