@nekostack/schema 1.0.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.
Files changed (214) hide show
  1. package/CHANGELOG.md +422 -0
  2. package/LICENSE +202 -0
  3. package/README.md +656 -0
  4. package/dist/src/builders/array.d.ts +12 -0
  5. package/dist/src/builders/array.d.ts.map +1 -0
  6. package/dist/src/builders/array.js +29 -0
  7. package/dist/src/builders/array.js.map +1 -0
  8. package/dist/src/builders/object.d.ts +62 -0
  9. package/dist/src/builders/object.d.ts.map +1 -0
  10. package/dist/src/builders/object.js +263 -0
  11. package/dist/src/builders/object.js.map +1 -0
  12. package/dist/src/builders/primitives.d.ts +37 -0
  13. package/dist/src/builders/primitives.d.ts.map +1 -0
  14. package/dist/src/builders/primitives.js +125 -0
  15. package/dist/src/builders/primitives.js.map +1 -0
  16. package/dist/src/builders/s.d.ts +27 -0
  17. package/dist/src/builders/s.d.ts.map +1 -0
  18. package/dist/src/builders/s.js +39 -0
  19. package/dist/src/builders/s.js.map +1 -0
  20. package/dist/src/builders/schema.d.ts +70 -0
  21. package/dist/src/builders/schema.d.ts.map +1 -0
  22. package/dist/src/builders/schema.js +98 -0
  23. package/dist/src/builders/schema.js.map +1 -0
  24. package/dist/src/cli-integration.d.ts +43 -0
  25. package/dist/src/cli-integration.d.ts.map +1 -0
  26. package/dist/src/cli-integration.js +48 -0
  27. package/dist/src/cli-integration.js.map +1 -0
  28. package/dist/src/errors/issue.d.ts +34 -0
  29. package/dist/src/errors/issue.d.ts.map +1 -0
  30. package/dist/src/errors/issue.js +89 -0
  31. package/dist/src/errors/issue.js.map +1 -0
  32. package/dist/src/generators/errors.d.ts +31 -0
  33. package/dist/src/generators/errors.d.ts.map +1 -0
  34. package/dist/src/generators/errors.js +34 -0
  35. package/dist/src/generators/errors.js.map +1 -0
  36. package/dist/src/generators/header.d.ts +42 -0
  37. package/dist/src/generators/header.d.ts.map +1 -0
  38. package/dist/src/generators/header.js +43 -0
  39. package/dist/src/generators/header.js.map +1 -0
  40. package/dist/src/generators/json-schema-meta.d.ts +36 -0
  41. package/dist/src/generators/json-schema-meta.d.ts.map +1 -0
  42. package/dist/src/generators/json-schema-meta.js +35 -0
  43. package/dist/src/generators/json-schema-meta.js.map +1 -0
  44. package/dist/src/generators/json-schema.d.ts +26 -0
  45. package/dist/src/generators/json-schema.d.ts.map +1 -0
  46. package/dist/src/generators/json-schema.js +88 -0
  47. package/dist/src/generators/json-schema.js.map +1 -0
  48. package/dist/src/generators/openapi.d.ts +33 -0
  49. package/dist/src/generators/openapi.d.ts.map +1 -0
  50. package/dist/src/generators/openapi.js +61 -0
  51. package/dist/src/generators/openapi.js.map +1 -0
  52. package/dist/src/generators/schema-fragment.d.ts +55 -0
  53. package/dist/src/generators/schema-fragment.d.ts.map +1 -0
  54. package/dist/src/generators/schema-fragment.js +253 -0
  55. package/dist/src/generators/schema-fragment.js.map +1 -0
  56. package/dist/src/generators/ts.d.ts +19 -0
  57. package/dist/src/generators/ts.d.ts.map +1 -0
  58. package/dist/src/generators/ts.js +252 -0
  59. package/dist/src/generators/ts.js.map +1 -0
  60. package/dist/src/generators/types.d.ts +96 -0
  61. package/dist/src/generators/types.d.ts.map +1 -0
  62. package/dist/src/generators/types.js +10 -0
  63. package/dist/src/generators/types.js.map +1 -0
  64. package/dist/src/generators/version.d.ts +11 -0
  65. package/dist/src/generators/version.d.ts.map +1 -0
  66. package/dist/src/generators/version.js +11 -0
  67. package/dist/src/generators/version.js.map +1 -0
  68. package/dist/src/generators/zod-mapping.d.ts +90 -0
  69. package/dist/src/generators/zod-mapping.d.ts.map +1 -0
  70. package/dist/src/generators/zod-mapping.js +174 -0
  71. package/dist/src/generators/zod-mapping.js.map +1 -0
  72. package/dist/src/generators/zod.d.ts +17 -0
  73. package/dist/src/generators/zod.d.ts.map +1 -0
  74. package/dist/src/generators/zod.js +118 -0
  75. package/dist/src/generators/zod.js.map +1 -0
  76. package/dist/src/index.d.ts +21 -0
  77. package/dist/src/index.d.ts.map +1 -0
  78. package/dist/src/index.js +43 -0
  79. package/dist/src/index.js.map +1 -0
  80. package/dist/src/ir/hash.d.ts +19 -0
  81. package/dist/src/ir/hash.d.ts.map +1 -0
  82. package/dist/src/ir/hash.js +22 -0
  83. package/dist/src/ir/hash.js.map +1 -0
  84. package/dist/src/ir/nodes.d.ts +121 -0
  85. package/dist/src/ir/nodes.d.ts.map +1 -0
  86. package/dist/src/ir/nodes.js +14 -0
  87. package/dist/src/ir/nodes.js.map +1 -0
  88. package/dist/src/ir/serialize.d.ts +8 -0
  89. package/dist/src/ir/serialize.d.ts.map +1 -0
  90. package/dist/src/ir/serialize.js +23 -0
  91. package/dist/src/ir/serialize.js.map +1 -0
  92. package/dist/src/migrations/build-migration-registry.d.ts +46 -0
  93. package/dist/src/migrations/build-migration-registry.d.ts.map +1 -0
  94. package/dist/src/migrations/build-migration-registry.js +134 -0
  95. package/dist/src/migrations/build-migration-registry.js.map +1 -0
  96. package/dist/src/migrations/handlers/list.d.ts +35 -0
  97. package/dist/src/migrations/handlers/list.d.ts.map +1 -0
  98. package/dist/src/migrations/handlers/list.js +55 -0
  99. package/dist/src/migrations/handlers/list.js.map +1 -0
  100. package/dist/src/migrations/handlers/plan.d.ts +26 -0
  101. package/dist/src/migrations/handlers/plan.d.ts.map +1 -0
  102. package/dist/src/migrations/handlers/plan.js +28 -0
  103. package/dist/src/migrations/handlers/plan.js.map +1 -0
  104. package/dist/src/migrations/handlers/stub.d.ts +22 -0
  105. package/dist/src/migrations/handlers/stub.d.ts.map +1 -0
  106. package/dist/src/migrations/handlers/stub.js +24 -0
  107. package/dist/src/migrations/handlers/stub.js.map +1 -0
  108. package/dist/src/migrations/handlers/verify.d.ts +25 -0
  109. package/dist/src/migrations/handlers/verify.d.ts.map +1 -0
  110. package/dist/src/migrations/handlers/verify.js +27 -0
  111. package/dist/src/migrations/handlers/verify.js.map +1 -0
  112. package/dist/src/migrations/parse-provenance.d.ts +78 -0
  113. package/dist/src/migrations/parse-provenance.d.ts.map +1 -0
  114. package/dist/src/migrations/parse-provenance.js +157 -0
  115. package/dist/src/migrations/parse-provenance.js.map +1 -0
  116. package/dist/src/migrations/plan-migration.d.ts +50 -0
  117. package/dist/src/migrations/plan-migration.d.ts.map +1 -0
  118. package/dist/src/migrations/plan-migration.js +256 -0
  119. package/dist/src/migrations/plan-migration.js.map +1 -0
  120. package/dist/src/migrations/stub.d.ts +55 -0
  121. package/dist/src/migrations/stub.d.ts.map +1 -0
  122. package/dist/src/migrations/stub.js +201 -0
  123. package/dist/src/migrations/stub.js.map +1 -0
  124. package/dist/src/migrations/types.d.ts +297 -0
  125. package/dist/src/migrations/types.d.ts.map +1 -0
  126. package/dist/src/migrations/types.js +28 -0
  127. package/dist/src/migrations/types.js.map +1 -0
  128. package/dist/src/migrations/verify-provenance.d.ts +46 -0
  129. package/dist/src/migrations/verify-provenance.d.ts.map +1 -0
  130. package/dist/src/migrations/verify-provenance.js +158 -0
  131. package/dist/src/migrations/verify-provenance.js.map +1 -0
  132. package/dist/src/registry/build-registry.d.ts +65 -0
  133. package/dist/src/registry/build-registry.d.ts.map +1 -0
  134. package/dist/src/registry/build-registry.js +172 -0
  135. package/dist/src/registry/build-registry.js.map +1 -0
  136. package/dist/src/registry/diff.d.ts +25 -0
  137. package/dist/src/registry/diff.d.ts.map +1 -0
  138. package/dist/src/registry/diff.js +497 -0
  139. package/dist/src/registry/diff.js.map +1 -0
  140. package/dist/src/registry/handlers/check.d.ts +57 -0
  141. package/dist/src/registry/handlers/check.d.ts.map +1 -0
  142. package/dist/src/registry/handlers/check.js +181 -0
  143. package/dist/src/registry/handlers/check.js.map +1 -0
  144. package/dist/src/registry/handlers/diff.d.ts +33 -0
  145. package/dist/src/registry/handlers/diff.d.ts.map +1 -0
  146. package/dist/src/registry/handlers/diff.js +61 -0
  147. package/dist/src/registry/handlers/diff.js.map +1 -0
  148. package/dist/src/registry/handlers/generate.d.ts +87 -0
  149. package/dist/src/registry/handlers/generate.d.ts.map +1 -0
  150. package/dist/src/registry/handlers/generate.js +223 -0
  151. package/dist/src/registry/handlers/generate.js.map +1 -0
  152. package/dist/src/registry/handlers/list.d.ts +36 -0
  153. package/dist/src/registry/handlers/list.d.ts.map +1 -0
  154. package/dist/src/registry/handlers/list.js +84 -0
  155. package/dist/src/registry/handlers/list.js.map +1 -0
  156. package/dist/src/registry/parse-provenance.d.ts +63 -0
  157. package/dist/src/registry/parse-provenance.d.ts.map +1 -0
  158. package/dist/src/registry/parse-provenance.js +182 -0
  159. package/dist/src/registry/parse-provenance.js.map +1 -0
  160. package/dist/src/registry/source-hash.d.ts +28 -0
  161. package/dist/src/registry/source-hash.d.ts.map +1 -0
  162. package/dist/src/registry/source-hash.js +32 -0
  163. package/dist/src/registry/source-hash.js.map +1 -0
  164. package/dist/src/registry/types.d.ts +185 -0
  165. package/dist/src/registry/types.d.ts.map +1 -0
  166. package/dist/src/registry/types.js +22 -0
  167. package/dist/src/registry/types.js.map +1 -0
  168. package/dist/src/runtime/compile.d.ts +38 -0
  169. package/dist/src/runtime/compile.d.ts.map +1 -0
  170. package/dist/src/runtime/compile.js +45 -0
  171. package/dist/src/runtime/compile.js.map +1 -0
  172. package/dist/src/runtime/errors.d.ts +25 -0
  173. package/dist/src/runtime/errors.d.ts.map +1 -0
  174. package/dist/src/runtime/errors.js +43 -0
  175. package/dist/src/runtime/errors.js.map +1 -0
  176. package/dist/src/runtime/normalize-issues.d.ts +65 -0
  177. package/dist/src/runtime/normalize-issues.d.ts.map +1 -0
  178. package/dist/src/runtime/normalize-issues.js +208 -0
  179. package/dist/src/runtime/normalize-issues.js.map +1 -0
  180. package/dist/src/runtime/parse.d.ts +62 -0
  181. package/dist/src/runtime/parse.d.ts.map +1 -0
  182. package/dist/src/runtime/parse.js +107 -0
  183. package/dist/src/runtime/parse.js.map +1 -0
  184. package/dist/src/runtime/strip-defaults.d.ts +51 -0
  185. package/dist/src/runtime/strip-defaults.d.ts.map +1 -0
  186. package/dist/src/runtime/strip-defaults.js +81 -0
  187. package/dist/src/runtime/strip-defaults.js.map +1 -0
  188. package/dist/src/runtime/zod-compile.d.ts +27 -0
  189. package/dist/src/runtime/zod-compile.d.ts.map +1 -0
  190. package/dist/src/runtime/zod-compile.js +92 -0
  191. package/dist/src/runtime/zod-compile.js.map +1 -0
  192. package/dist/src/types.d.ts +116 -0
  193. package/dist/src/types.d.ts.map +1 -0
  194. package/dist/src/types.js +2 -0
  195. package/dist/src/types.js.map +1 -0
  196. package/docs/ABSENCE_SEMANTICS.md +37 -0
  197. package/docs/BENCHMARKS.md +64 -0
  198. package/docs/COMPOSITION.md +206 -0
  199. package/docs/DIFF_CLASSIFICATION.md +137 -0
  200. package/docs/EXAMPLES.md +221 -0
  201. package/docs/HEADER_FORMAT.md +66 -0
  202. package/docs/INVARIANTS.md +58 -0
  203. package/docs/IR_CONTRACT.md +67 -0
  204. package/docs/ISSUE_CODES.md +99 -0
  205. package/docs/JSON_SCHEMA_MAPPING.md +149 -0
  206. package/docs/MIGRATIONS.md +406 -0
  207. package/docs/MIGRATION_GUIDE.md +150 -0
  208. package/docs/OPENAPI_MAPPING.md +66 -0
  209. package/docs/REGISTRY.md +336 -0
  210. package/docs/RUNTIME.md +279 -0
  211. package/docs/SCOPE.md +119 -0
  212. package/docs/USAGE.md +376 -0
  213. package/docs/ZOD_MODIFIER_ORDERING.md +77 -0
  214. package/package.json +45 -0
@@ -0,0 +1,497 @@
1
+ /**
2
+ * Schema diff classifier (Master plan Step 7).
3
+ *
4
+ * `diffNodes(before, after)` walks two `SchemaNode` trees and emits a
5
+ * list of `DiffChange`s with severity per the locked Master plan
6
+ * Decision #12 table. The **input-acceptance compatibility** lens is
7
+ * primary: severity reflects whether the new schema accepts every
8
+ * input the old one did (additive) or rejects some (breaking).
9
+ * Output-side caveats are reflected in `kind` / `message` where they
10
+ * matter (`default_removed`, etc.) but do not split the severity.
11
+ *
12
+ * **Pure.** No registry lookup, no `Issue[]` surface, no filesystem.
13
+ * The function returns `readonly DiffChange[]`; an empty array means
14
+ * the schemas are equivalent. `worstSeverity` aggregation lives in
15
+ * `diffHandler` (Step 9).
16
+ *
17
+ * Unsupported IR kinds (`date`, `union`, `recursiveRef`, `transform`)
18
+ * throw `UnsupportedNodeKindError({ generator: "diff", kind })` per
19
+ * Master plan Decision #14 — same fail-loud discipline as the v0.3 /
20
+ * v0.6 generators.
21
+ */
22
+ import { UnsupportedNodeKindError } from "../generators/errors.js";
23
+ const SUPPORTED_KINDS = new Set([
24
+ "string",
25
+ "number",
26
+ "boolean",
27
+ "literal",
28
+ "enum",
29
+ "array",
30
+ "object",
31
+ ]);
32
+ export function diffNodes(before, after) {
33
+ ensureSupported(before);
34
+ ensureSupported(after);
35
+ return walk(before, after, []);
36
+ }
37
+ // =============================================================================
38
+ // Walker
39
+ // =============================================================================
40
+ function walk(before, after, path) {
41
+ const out = [];
42
+ // Top-level kind mismatch: cannot meaningfully diff further.
43
+ if (before.kind !== after.kind) {
44
+ out.push({
45
+ severity: "breaking",
46
+ path,
47
+ kind: "type_changed",
48
+ before: before.kind,
49
+ after: after.kind,
50
+ message: `Type changed from \`${before.kind}\` to \`${after.kind}\``,
51
+ });
52
+ return out;
53
+ }
54
+ // Same-kind: diff each axis independently.
55
+ out.push(...diffMetadata(before.metadata, after.metadata, path));
56
+ out.push(...diffDefault(before.modifiers, after.modifiers, path));
57
+ out.push(...diffAbsence(before.modifiers, after.modifiers, path));
58
+ out.push(...diffRefinements(before.refinements, after.refinements, path));
59
+ switch (before.kind) {
60
+ case "object":
61
+ out.push(...diffObject(before, after, path));
62
+ break;
63
+ case "array":
64
+ out.push(...walk(before.element, after.element, [...path, "[]"]));
65
+ break;
66
+ case "enum":
67
+ out.push(...diffEnum(before, after, path));
68
+ break;
69
+ case "literal":
70
+ out.push(...diffLiteral(before, after, path));
71
+ break;
72
+ case "string":
73
+ case "number":
74
+ case "boolean":
75
+ // No kind-specific data beyond modifiers + refinements.
76
+ break;
77
+ default:
78
+ // Should not be reachable — ensureSupported() gated unsupported
79
+ // kinds at the entry point. Belt-and-suspenders.
80
+ throw new UnsupportedNodeKindError({
81
+ kind: before.kind,
82
+ generator: "diff",
83
+ });
84
+ }
85
+ return out;
86
+ }
87
+ // =============================================================================
88
+ // Metadata (cosmetic)
89
+ // =============================================================================
90
+ function diffMetadata(before, after, path) {
91
+ const out = [];
92
+ const b = before ?? {};
93
+ const a = after ?? {};
94
+ if (b.version !== a.version) {
95
+ out.push({
96
+ severity: "cosmetic",
97
+ path,
98
+ kind: "schema_version_changed",
99
+ before: b.version ?? null,
100
+ after: a.version ?? null,
101
+ message: `schemaVersion changed from \`${b.version ?? "null"}\` to \`${a.version ?? "null"}\``,
102
+ });
103
+ }
104
+ if (b.description !== a.description) {
105
+ out.push({
106
+ severity: "cosmetic",
107
+ path,
108
+ kind: "metadata_changed",
109
+ before: b.description ?? null,
110
+ after: a.description ?? null,
111
+ message: "Description changed",
112
+ });
113
+ }
114
+ if ((b.deprecated ?? false) !== (a.deprecated ?? false)) {
115
+ out.push({
116
+ severity: "cosmetic",
117
+ path,
118
+ kind: "metadata_changed",
119
+ before: b.deprecated ?? false,
120
+ after: a.deprecated ?? false,
121
+ message: `Deprecated flag changed to ${a.deprecated ?? false}`,
122
+ });
123
+ }
124
+ if (b.id !== a.id) {
125
+ out.push({
126
+ severity: "cosmetic",
127
+ path,
128
+ kind: "metadata_changed",
129
+ before: b.id ?? null,
130
+ after: a.id ?? null,
131
+ message: `schemaId changed from \`${b.id ?? "null"}\` to \`${a.id ?? "null"}\``,
132
+ });
133
+ }
134
+ return out;
135
+ }
136
+ // =============================================================================
137
+ // Default add / remove / value-change
138
+ // =============================================================================
139
+ function diffDefault(before, after, path) {
140
+ const beforeDefault = before?.default;
141
+ const afterDefault = after?.default;
142
+ if (beforeDefault === undefined && afterDefault === undefined)
143
+ return [];
144
+ if (beforeDefault === undefined && afterDefault !== undefined) {
145
+ return [
146
+ {
147
+ severity: "additive",
148
+ path,
149
+ kind: "default_added",
150
+ after: afterDefault.value,
151
+ message: `Default added (value: ${formatValue(afterDefault.value)})`,
152
+ },
153
+ ];
154
+ }
155
+ if (beforeDefault !== undefined && afterDefault === undefined) {
156
+ return [
157
+ {
158
+ severity: "breaking",
159
+ path,
160
+ kind: "default_removed",
161
+ before: beforeDefault.value,
162
+ message: `Default removed (was: ${formatValue(beforeDefault.value)})`,
163
+ },
164
+ ];
165
+ }
166
+ // Both have a default — compare values.
167
+ if (!jsonEqual(beforeDefault.value, afterDefault.value)) {
168
+ return [
169
+ {
170
+ severity: "breaking",
171
+ path,
172
+ kind: "default_value_changed",
173
+ before: beforeDefault.value,
174
+ after: afterDefault.value,
175
+ message: `Default value changed from ${formatValue(beforeDefault.value)} to ${formatValue(afterDefault.value)}`,
176
+ },
177
+ ];
178
+ }
179
+ return [];
180
+ }
181
+ function diffAbsence(before, after, path) {
182
+ // The `optional` flag set as a side effect of `default()` is masked
183
+ // here — default add/remove is the change being tracked, not the
184
+ // implicit optional flip. Per Decision #12, "Add default to existing
185
+ // required field" is one row, additive — not two rows.
186
+ const beforeState = absenceStateOf(before);
187
+ const afterState = absenceStateOf(after);
188
+ if (beforeState === afterState)
189
+ return [];
190
+ return [
191
+ {
192
+ severity: absenceSeverity(beforeState, afterState),
193
+ path,
194
+ kind: "absence_modifier_changed",
195
+ before: beforeState,
196
+ after: afterState,
197
+ message: `Absence modifier changed: ${beforeState} → ${afterState}`,
198
+ },
199
+ ];
200
+ }
201
+ function absenceStateOf(mod) {
202
+ // Mask optional-by-default; that's tracked by the default axis.
203
+ const opt = mod?.optional === true && mod?.default === undefined;
204
+ const nul = mod?.nullable === true;
205
+ if (opt && nul)
206
+ return "nullish";
207
+ if (opt)
208
+ return "optional";
209
+ if (nul)
210
+ return "nullable";
211
+ return "required";
212
+ }
213
+ /**
214
+ * Transition severity per the v0.7 input-acceptance lens. The new
215
+ * state's accepted set vs. the old: superset → additive, otherwise
216
+ * breaking. No-op (same state) is handled upstream.
217
+ */
218
+ function absenceSeverity(from, to) {
219
+ // Required is the smallest accepted set; nullish is the largest.
220
+ // Anything that drops a previously-accepted shape is breaking.
221
+ const SUPERSET = {
222
+ required: new Set(["required"]),
223
+ optional: new Set(["required", "optional"]),
224
+ nullable: new Set(["required", "nullable"]),
225
+ nullish: new Set(["required", "optional", "nullable", "nullish"]),
226
+ };
227
+ return SUPERSET[to].has(from) ? "additive" : "breaking";
228
+ }
229
+ // =============================================================================
230
+ // Refinements
231
+ // =============================================================================
232
+ function diffRefinements(before, after, path) {
233
+ const beforeRefs = (before ?? []).filter(isPortable);
234
+ const afterRefs = (after ?? []).filter(isPortable);
235
+ const beforeByName = new Map();
236
+ for (const r of beforeRefs)
237
+ beforeByName.set(r.name, r);
238
+ const afterByName = new Map();
239
+ for (const r of afterRefs)
240
+ afterByName.set(r.name, r);
241
+ const out = [];
242
+ // Refinements present in `before` but not in `after` → loosened →
243
+ // additive.
244
+ for (const [name, r] of beforeByName) {
245
+ if (!afterByName.has(name)) {
246
+ out.push({
247
+ severity: "additive",
248
+ path,
249
+ kind: "refinement_changed",
250
+ before: r,
251
+ message: `Refinement \`${name}\` removed (loosened)`,
252
+ });
253
+ }
254
+ }
255
+ // Refinements present in `after` but not in `before` → tightened →
256
+ // breaking.
257
+ for (const [name, r] of afterByName) {
258
+ if (!beforeByName.has(name)) {
259
+ out.push({
260
+ severity: "breaking",
261
+ path,
262
+ kind: "refinement_changed",
263
+ after: r,
264
+ message: `Refinement \`${name}\` added (tightened)`,
265
+ });
266
+ }
267
+ }
268
+ // Refinements present in both with different params.
269
+ for (const [name, beforeR] of beforeByName) {
270
+ const afterR = afterByName.get(name);
271
+ if (afterR === undefined)
272
+ continue;
273
+ if (!jsonEqual(beforeR.params ?? {}, afterR.params ?? {})) {
274
+ out.push({
275
+ severity: refinementParamSeverity(name, beforeR, afterR),
276
+ path,
277
+ kind: "refinement_changed",
278
+ before: beforeR,
279
+ after: afterR,
280
+ message: `Refinement \`${name}\` parameters changed`,
281
+ });
282
+ }
283
+ }
284
+ // If no changes detected so far, check for reorder (same set,
285
+ // different order). Cosmetic.
286
+ if (out.length === 0) {
287
+ const beforeOrder = beforeRefs.map((r) => r.name).join(",");
288
+ const afterOrder = afterRefs.map((r) => r.name).join(",");
289
+ if (beforeOrder !== afterOrder &&
290
+ [...beforeRefs.map((r) => r.name)].sort().join(",") ===
291
+ [...afterRefs.map((r) => r.name)].sort().join(",")) {
292
+ out.push({
293
+ severity: "cosmetic",
294
+ path,
295
+ kind: "refinements_reordered",
296
+ before: beforeOrder,
297
+ after: afterOrder,
298
+ message: "Refinements reordered (same set, different order)",
299
+ });
300
+ }
301
+ }
302
+ return out;
303
+ }
304
+ function isPortable(r) {
305
+ return r.kind === "portable";
306
+ }
307
+ /**
308
+ * For a refinement that exists on both sides with different params,
309
+ * decide whether the change tightens (breaking) or loosens (additive)
310
+ * the accepted set. Numeric bounds have a defined direction; literal-
311
+ * matching refinements (`regex`, `length`, `multipleOf`) are
312
+ * conservatively breaking on any value change.
313
+ */
314
+ function refinementParamSeverity(name, before, after) {
315
+ const beforeValue = before.params?.value;
316
+ const afterValue = after.params?.value;
317
+ if (typeof beforeValue !== "number" || typeof afterValue !== "number") {
318
+ return "breaking";
319
+ }
320
+ switch (name) {
321
+ case "minLength":
322
+ case "min":
323
+ case "minItems":
324
+ case "gt":
325
+ return afterValue > beforeValue ? "breaking" : "additive";
326
+ case "maxLength":
327
+ case "max":
328
+ case "maxItems":
329
+ case "lt":
330
+ return afterValue < beforeValue ? "breaking" : "additive";
331
+ case "length":
332
+ case "multipleOf":
333
+ case "regex":
334
+ default:
335
+ return "breaking";
336
+ }
337
+ }
338
+ // =============================================================================
339
+ // Object: fields + unknownKeys policy
340
+ // =============================================================================
341
+ function diffObject(before, after, path) {
342
+ const out = [];
343
+ // Unknown-keys policy
344
+ if (before.unknownKeys !== after.unknownKeys) {
345
+ out.push({
346
+ severity: unknownKeysSeverity(before.unknownKeys, after.unknownKeys),
347
+ path,
348
+ kind: "unknown_keys_changed",
349
+ before: before.unknownKeys,
350
+ after: after.unknownKeys,
351
+ message: `unknownKeys policy changed: ${before.unknownKeys} → ${after.unknownKeys}`,
352
+ });
353
+ }
354
+ // Field-level diff
355
+ const beforeKeys = Object.keys(before.fields);
356
+ const afterKeys = Object.keys(after.fields);
357
+ const allKeys = new Set([...beforeKeys, ...afterKeys]);
358
+ for (const key of allKeys) {
359
+ const beforeField = before.fields[key];
360
+ const afterField = after.fields[key];
361
+ const childPath = [...path, key];
362
+ if (beforeField === undefined && afterField !== undefined) {
363
+ // Field added — severity depends on the new field's modifiers.
364
+ out.push({
365
+ severity: newFieldSeverity(afterField),
366
+ path: childPath,
367
+ kind: "field_added",
368
+ after: afterField,
369
+ message: `Field \`${key}\` added (${absenceStateOf(afterField.modifiers)}${afterField.modifiers?.default !== undefined ? ", default-bearing" : ""})`,
370
+ });
371
+ continue;
372
+ }
373
+ if (beforeField !== undefined && afterField === undefined) {
374
+ out.push({
375
+ severity: "breaking",
376
+ path: childPath,
377
+ kind: "field_removed",
378
+ before: beforeField,
379
+ message: `Field \`${key}\` removed`,
380
+ });
381
+ continue;
382
+ }
383
+ if (beforeField !== undefined && afterField !== undefined) {
384
+ out.push(...walk(beforeField, afterField, childPath));
385
+ }
386
+ }
387
+ return out;
388
+ }
389
+ /**
390
+ * Per Master plan Decision #12: adding a new field's severity depends
391
+ * on whether that field accepts the *absence* of the value (i.e., old
392
+ * inputs lacking the key still validate).
393
+ */
394
+ function newFieldSeverity(node) {
395
+ const mod = node.modifiers;
396
+ const hasDefault = mod?.default !== undefined;
397
+ const isOptional = mod?.optional === true;
398
+ const isNullable = mod?.nullable === true;
399
+ // additive: input-optional (the key may be absent and the schema
400
+ // still validates).
401
+ if (hasDefault)
402
+ return "additive";
403
+ if (isOptional && isNullable)
404
+ return "additive"; // nullish
405
+ if (isOptional)
406
+ return "additive";
407
+ // breaking: nullable-only is required-but-may-be-null (old inputs
408
+ // lacking the key fail); required is the same fail mode.
409
+ if (isNullable)
410
+ return "breaking";
411
+ return "breaking";
412
+ }
413
+ function unknownKeysSeverity(before, after) {
414
+ // strict accepts the smallest set (no unknown keys).
415
+ // passthrough / stripUnknown both accept arbitrary unknown keys.
416
+ // For input-acceptance: strict → passthrough/stripUnknown grows the
417
+ // accepted set (additive); the reverse shrinks it (breaking).
418
+ // passthrough ↔ stripUnknown both accept the same input set (the
419
+ // output behavior differs — preserve vs. drop — but at the
420
+ // input-acceptance lens this is cosmetic).
421
+ if (before === "strict" && after !== "strict")
422
+ return "additive";
423
+ if (after === "strict" && before !== "strict")
424
+ return "breaking";
425
+ return "cosmetic";
426
+ }
427
+ // =============================================================================
428
+ // Enum
429
+ // =============================================================================
430
+ function diffEnum(before, after, path) {
431
+ const out = [];
432
+ const beforeSet = new Set(before.values.map((v) => JSON.stringify(v)));
433
+ const afterSet = new Set(after.values.map((v) => JSON.stringify(v)));
434
+ for (const v of after.values) {
435
+ if (!beforeSet.has(JSON.stringify(v))) {
436
+ out.push({
437
+ severity: "additive",
438
+ path,
439
+ kind: "enum_value_added",
440
+ after: v,
441
+ message: `Enum value added: ${formatValue(v)}`,
442
+ });
443
+ }
444
+ }
445
+ for (const v of before.values) {
446
+ if (!afterSet.has(JSON.stringify(v))) {
447
+ out.push({
448
+ severity: "breaking",
449
+ path,
450
+ kind: "enum_value_removed",
451
+ before: v,
452
+ message: `Enum value removed: ${formatValue(v)}`,
453
+ });
454
+ }
455
+ }
456
+ return out;
457
+ }
458
+ // =============================================================================
459
+ // Literal
460
+ // =============================================================================
461
+ function diffLiteral(before, after, path) {
462
+ if (jsonEqual(before.value, after.value))
463
+ return [];
464
+ return [
465
+ {
466
+ severity: "breaking",
467
+ path,
468
+ kind: "literal_changed",
469
+ before: before.value,
470
+ after: after.value,
471
+ message: `Literal changed from ${formatValue(before.value)} to ${formatValue(after.value)}`,
472
+ },
473
+ ];
474
+ }
475
+ // =============================================================================
476
+ // Helpers
477
+ // =============================================================================
478
+ function ensureSupported(node) {
479
+ if (!SUPPORTED_KINDS.has(node.kind)) {
480
+ throw new UnsupportedNodeKindError({
481
+ kind: node.kind,
482
+ generator: "diff",
483
+ });
484
+ }
485
+ }
486
+ function jsonEqual(a, b) {
487
+ return JSON.stringify(a) === JSON.stringify(b);
488
+ }
489
+ function formatValue(v) {
490
+ try {
491
+ return JSON.stringify(v);
492
+ }
493
+ catch {
494
+ return String(v);
495
+ }
496
+ }
497
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/registry/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * `checkHandler({ registry, committedArtifacts })` — freshness check
3
+ * via the two-hash matrix from Master plan §"Freshness verdict —
4
+ * two-hash discipline".
5
+ *
6
+ * Pure. No filesystem, no `import()`, no `process.*`, no `console.*`.
7
+ * The CLI reads each artifact's bytes from disk and hands them in;
8
+ * this function parses provenance, looks up the matching
9
+ * `RegistryEntry`, and produces one `FreshnessVerdict` per artifact.
10
+ * Master plan Decision #1 boundary.
11
+ *
12
+ * ## Two-hash matrix
13
+ *
14
+ * | artifact irHash | artifact sourceHash | verdict |
15
+ * |---|---|---|
16
+ * | matches registry | matches registry | `clean` |
17
+ * | matches registry | **differs** | `cosmetic_drift` |
18
+ * | **differs** | **differs** | `stale` |
19
+ * | **differs** | matches registry | `integrity_error` (the impossible row — should never happen unless the artifact was hand-edited or the recorded sourceHash was tampered with) |
20
+ *
21
+ * ## v0.6 backward compatibility (Master plan Decision #8)
22
+ *
23
+ * Artifacts emitted before Step 4 (`@nekostack/schema@0.6.0` and
24
+ * earlier) have no `sourceHash` field/line. `parseProvenanceFromText`
25
+ * returns `sourceHash: undefined` for those. Treat as:
26
+ *
27
+ * - `irHash` matches registry → `clean`
28
+ * - `irHash` differs from registry → `stale`
29
+ *
30
+ * Absent `sourceHash` is **never** an integrity error by itself — the
31
+ * artifact simply predates the two-hash discipline. Once the user
32
+ * regenerates the artifact at v0.7+, full matrix participation
33
+ * resumes.
34
+ *
35
+ * ## Failure paths (Result<...> failure)
36
+ *
37
+ * - **Malformed provenance** — `parseProvenanceFromText` already
38
+ * returns an `integrity_error` Issue; this handler forwards those
39
+ * issues with the artifact path attached.
40
+ * - **Anonymous artifact** (provenance `schemaId === null`) —
41
+ * `schema_not_found` with `metadata.reason = "anonymous_artifact"`.
42
+ * The registry never indexes anonymous schemas (Master plan
43
+ * Decision #5), so there's nothing to validate against.
44
+ * - **schemaId not in registry** — `schema_not_found`. The user
45
+ * likely deleted a schema source file but forgot to delete the
46
+ * generated artifacts.
47
+ * - **schemaId present but version not in registry** —
48
+ * `version_not_found`. Distinct code so the CLI can format
49
+ * orphan-by-id vs. orphan-by-version differently.
50
+ *
51
+ * Any artifact failure surfaces as `Result.failure` for the whole
52
+ * check call. Per-artifact verdicts are returned only when EVERY
53
+ * artifact parses + resolves cleanly.
54
+ */
55
+ import type { CheckOpts, CheckResult } from "../types.js";
56
+ export declare function checkHandler(opts: CheckOpts): CheckResult;
57
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../../src/registry/handlers/check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAKH,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EAKZ,MAAM,aAAa,CAAC;AAErB,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW,CAiBzD"}