@metaobjectsdev/sdk 0.13.1 → 0.14.0

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.
@@ -103,6 +103,7 @@ export type ForgeAttr = (typeof FORGE_ATTRS)[number];
103
103
  // ---------------------------------------------------------------------------
104
104
 
105
105
  import {
106
+ type AttrSchema,
106
107
  type ChildRule,
107
108
  type MetaDataTypeProvider,
108
109
  type TypeDefinition,
@@ -110,6 +111,8 @@ import {
110
111
  TypeRegistry,
111
112
  MetaData,
112
113
  TYPE_ATTR,
114
+ TYPE_METADATA,
115
+ SUBTYPE_ROOT,
113
116
  CHILD_RULE_WILDCARD,
114
117
  } from "@metaobjectsdev/metadata";
115
118
 
@@ -124,6 +127,20 @@ function wildcardOf(childType: string): ChildRule {
124
127
  };
125
128
  }
126
129
 
130
+ // Every @forge* attr, declared (untyped, optional) as a COMMON attr — admissible
131
+ // on ANY node, exactly like the documentation provenance attrs (@description /
132
+ // @notes / @deprecated). Forge records are DESCRIPTIVE memory, not the
133
+ // prescriptive metamodel: the @forge* provenance attrs annotate both forge nodes
134
+ // AND real entities (e.g. @forgePrimaryLocation on an object.entity). Declaring
135
+ // the NAMES — without value-type coercion — is what makes a forge-annotated node
136
+ // strict-clean (ADR-0023 Check 0 keys off the attr NAME), so `meta verify`
137
+ // (strict-by-default, #96) admits them instead of ERR_UNKNOWN_ATTR.
138
+ const FORGE_ATTR_SCHEMAS: AttrSchema[] = FORGE_ATTRS.map((name) => ({
139
+ name,
140
+ required: false,
141
+ description: `Meta Forge provenance attr @${name} (descriptive memory).`,
142
+ }));
143
+
127
144
  function def(
128
145
  type: string,
129
146
  subType: string,
@@ -170,6 +187,19 @@ export const forgeTypesProvider: MetaDataTypeProvider = {
170
187
  for (const subType of FORGE_FAILURE_SUBTYPES) {
171
188
  registry.register(def(FORGE_TYPE_FAILURE, subType, `Forge failure record (${subType})`, forgeChildRules));
172
189
  }
190
+
191
+ // #96 — the @forge* provenance attrs are common (admissible on any node).
192
+ registry.registerCommonAttrs([...FORGE_ATTR_SCHEMAS]);
193
+
194
+ // FR-033 / #96 — admit the forge descriptive types as top-level children of
195
+ // metadata.root. Core (fail-closed) admits only object/field/validator/
196
+ // template there, so under strict load a real decision/principle/… record
197
+ // would otherwise be ERR_CHILD_NOT_ALLOWED. `loadMemory` bundles these types
198
+ // precisely so mixed prescriptive+descriptive content loads; wiring the
199
+ // childRule makes that hold under strict (`meta verify` strict-by-default) too.
200
+ registry.extend(TYPE_METADATA, SUBTYPE_ROOT, {
201
+ childRules: FORGE_TYPES.map((t) => wildcardOf(t)),
202
+ });
173
203
  },
174
204
  };
175
205
 
package/src/memory.ts CHANGED
@@ -43,6 +43,13 @@ export interface LoadMemoryOptions {
43
43
  * Throws if `providers` is absent or empty.
44
44
  */
45
45
  replaceDefaults?: boolean;
46
+ /**
47
+ * ADR-0023 strict-attr load. When `true`, an authored own `@-attr` matching
48
+ * no registered per-type schema and no commonAttr is `ERR_UNKNOWN_ATTR`.
49
+ * Defaults `false` (legacy open-attr policy) so a downstream app loads lax;
50
+ * the `meta verify` command opts in to `true` (strict-by-default, #96).
51
+ */
52
+ strict?: boolean;
46
53
  }
47
54
 
48
55
  /** Default provider bundle threaded by {@link loadMemory} when no options
@@ -99,6 +106,7 @@ export async function loadMemory(
99
106
 
100
107
  const loader = new MetaDataLoader({
101
108
  registry,
109
+ ...(options?.strict === true ? { strict: true } : {}),
102
110
  });
103
111
  const result = await loader.load(paths.map((p) => new FileSource(p)));
104
112