@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,84 @@
1
+ /**
2
+ * `listHandler({ registry })` — enumerate every `RegistryEntry` in a
3
+ * `Registry`, in a stable order, as a `Result<{ entries }>`.
4
+ *
5
+ * The simplest of the four v0.7 handlers; landing this commit first
6
+ * pins the handler shape and the `Result<T>` discriminated-union
7
+ * contract before `diff` / `check` / `generate` add per-handler
8
+ * complexity (Master plan sequencing step 8).
9
+ *
10
+ * **Pure.** No filesystem, no `import()`, no `process.*`, no
11
+ * `console.*`. Takes an already-built `Registry` (Step 6's
12
+ * `buildRegistry` output) and returns a `Result` over a flat array.
13
+ * Master plan Decision #1 boundary.
14
+ *
15
+ * Ordering (deterministic; documented in tests):
16
+ *
17
+ * 1. **Across `schemaId`**: alphabetical ascending.
18
+ * 2. **Within one `schemaId`**: versioned entries first, ascending
19
+ * by numeric major.minor.patch semver (so `1.0.0` < `2.0.0` <
20
+ * `10.0.0`, never lexicographic `10.0.0` < `2.0.0`). Unversioned
21
+ * entries (the empty-string inner key from Step 6) come **last**.
22
+ *
23
+ * Rationale for "unversioned last":
24
+ * - Putting unversioned first would sort empty-string `""` before
25
+ * any semver — visually surprising in CLI output.
26
+ * - Unversioned schemas are the v0.7 fallback for `.id()`-without-
27
+ * `.version()`. Most workspaces won't have any. Sorting them at
28
+ * the tail makes them visually distinct from the canonical
29
+ * versioned list.
30
+ *
31
+ * Empty registry: returns `{ success: true, data: { entries: [] } }`.
32
+ * Never returns failure — list is read-only, has no failure mode.
33
+ */
34
+ export function listHandler(opts) {
35
+ const entries = [];
36
+ const schemaIds = [...opts.registry.keys()].sort();
37
+ for (const schemaId of schemaIds) {
38
+ const inner = opts.registry.get(schemaId);
39
+ if (inner === undefined)
40
+ continue; // unreachable given iteration source
41
+ const versionKeys = [];
42
+ let hasUnversioned = false;
43
+ for (const key of inner.keys()) {
44
+ if (key === "")
45
+ hasUnversioned = true;
46
+ else
47
+ versionKeys.push(key);
48
+ }
49
+ versionKeys.sort(compareSemver);
50
+ for (const v of versionKeys) {
51
+ const entry = inner.get(v);
52
+ if (entry !== undefined)
53
+ entries.push(entry);
54
+ }
55
+ if (hasUnversioned) {
56
+ const entry = inner.get("");
57
+ if (entry !== undefined)
58
+ entries.push(entry);
59
+ }
60
+ }
61
+ return { success: true, data: { entries } };
62
+ }
63
+ /**
64
+ * Numeric semver compare on `major.minor.patch`. Falls back to
65
+ * `localeCompare` for non-matching inputs so non-standard version
66
+ * strings (e.g., `"1.0.0-rc.1"`) sort deterministically without
67
+ * throwing. Duplicates `build-registry.ts`'s private helper; the
68
+ * two consumers are small enough that DRY-vs-coupling is a wash
69
+ * for v0.7. If a third consumer emerges, factor into a registry-
70
+ * internal `semver.ts`.
71
+ */
72
+ function compareSemver(a, b) {
73
+ const ax = a.match(/(\d+)\.(\d+)\.(\d+)/);
74
+ const bx = b.match(/(\d+)\.(\d+)\.(\d+)/);
75
+ if (!ax || !bx)
76
+ return a.localeCompare(b);
77
+ for (let i = 1; i <= 3; i++) {
78
+ const d = Number(ax[i]) - Number(bx[i]);
79
+ if (d !== 0)
80
+ return d;
81
+ }
82
+ return a.localeCompare(b);
83
+ }
84
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../../src/registry/handlers/list.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAQH,MAAM,UAAU,WAAW,CAAC,IAAc;IACxC,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS,CAAC,qCAAqC;QAExE,MAAM,WAAW,GAAa,EAAE,CAAC;QACjC,IAAI,cAAc,GAAG,KAAK,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/B,IAAI,GAAG,KAAK,EAAE;gBAAE,cAAc,GAAG,IAAI,CAAC;;gBACjC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAEhC,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC5B,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,aAAa,CAAC,CAAS,EAAE,CAAS;IACzC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Provenance parser for generated artifacts (Master plan Step 5).
3
+ *
4
+ * Reads the provenance metadata back out of an emitted artifact so
5
+ * `checkHandler` (Step 10) can compare it against the current schema
6
+ * source. Two carrier shapes are supported, mirroring the Step 4
7
+ * emitter side:
8
+ *
9
+ * - **JSDoc header** (TS / Zod) — `/** ... * /` block at the top of
10
+ * the file. Each provenance field lives on its own `* <name>: <value>`
11
+ * line. The `@generated` line, the `// anonymous schema` line, the
12
+ * blank `*` line, and the `DO NOT EDIT MANUALLY` line are skipped.
13
+ *
14
+ * - **`x-nekostack` block** (JSON Schema / OpenAPI) — a single object
15
+ * under the `x-nekostack` key at the document root. The provenance
16
+ * fields are own properties of that object.
17
+ *
18
+ * The function is **pure**: no `fs.*`, no `import()`, no path argument.
19
+ * The CLI reads the artifact text from disk and hands it in; this
20
+ * module parses and returns. Master plan Decision #1 boundary applies.
21
+ *
22
+ * **Backward compatibility (Master plan Decision #8):** v0.6-era
23
+ * artifacts have no `sourceHash` line / field. They are parsed
24
+ * successfully; `sourceHash` is `undefined` on the result, never
25
+ * `null`. The freshness verdict in `checkHandler` treats absent
26
+ * `sourceHash` as "unknown" — NOT as an integrity error.
27
+ *
28
+ * **Malformed / missing provenance** surfaces as `Result<...>` failure
29
+ * with one `Issue` of code `"integrity_error"`. `metadata.reason`
30
+ * records the specific sub-mode (unknown_format, missing_field,
31
+ * malformed_hash, json_parse_error, etc.) so consumers downstream can
32
+ * triage without parsing `message`. The CLI's `checkHandler` step
33
+ * (Step 10) maps an integrity_error result onto the
34
+ * `FreshnessVerdict.status = "integrity_error"` shape with exit code 4.
35
+ */
36
+ import type { Result } from "../errors/issue.js";
37
+ /**
38
+ * Parsed provenance fields. Matches the union of what TS/Zod JSDoc
39
+ * headers and JSON-side `x-nekostack` blocks carry.
40
+ *
41
+ * `schemaId` / `schemaVersion` are `null` for anonymous / unversioned
42
+ * schemas (the emitter writes the literal string `"null"` in JSDoc and
43
+ * the JSON value `null` in `x-nekostack`; both decode to JS `null`
44
+ * here). `sourceHash` is `undefined` when absent — never `null`.
45
+ */
46
+ export interface ParsedProvenance {
47
+ readonly generator: string;
48
+ readonly generatorVersion: string;
49
+ readonly schemaId: string | null;
50
+ readonly schemaVersion: string | null;
51
+ readonly irHash: `sha256:${string}`;
52
+ readonly sourceHash: `sha256:${string}` | undefined;
53
+ }
54
+ /**
55
+ * Parse the provenance block out of an artifact's text content.
56
+ *
57
+ * Auto-detects the carrier by leading non-whitespace character:
58
+ * `/` → JSDoc header (TS / Zod source artifact)
59
+ * `{` → JSON document (JSON Schema / OpenAPI artifact)
60
+ * else → integrity_error / unknown_format
61
+ */
62
+ export declare function parseProvenanceFromText(content: string): Result<ParsedProvenance>;
63
+ //# sourceMappingURL=parse-provenance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-provenance.d.ts","sourceRoot":"","sources":["../../../src/registry/parse-provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,KAAK,EAAS,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAOxD;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,UAAU,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,UAAU,MAAM,EAAE,GAAG,SAAS,CAAC;CACrD;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,gBAAgB,CAAC,CAY1B"}
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Provenance parser for generated artifacts (Master plan Step 5).
3
+ *
4
+ * Reads the provenance metadata back out of an emitted artifact so
5
+ * `checkHandler` (Step 10) can compare it against the current schema
6
+ * source. Two carrier shapes are supported, mirroring the Step 4
7
+ * emitter side:
8
+ *
9
+ * - **JSDoc header** (TS / Zod) — `/** ... * /` block at the top of
10
+ * the file. Each provenance field lives on its own `* <name>: <value>`
11
+ * line. The `@generated` line, the `// anonymous schema` line, the
12
+ * blank `*` line, and the `DO NOT EDIT MANUALLY` line are skipped.
13
+ *
14
+ * - **`x-nekostack` block** (JSON Schema / OpenAPI) — a single object
15
+ * under the `x-nekostack` key at the document root. The provenance
16
+ * fields are own properties of that object.
17
+ *
18
+ * The function is **pure**: no `fs.*`, no `import()`, no path argument.
19
+ * The CLI reads the artifact text from disk and hands it in; this
20
+ * module parses and returns. Master plan Decision #1 boundary applies.
21
+ *
22
+ * **Backward compatibility (Master plan Decision #8):** v0.6-era
23
+ * artifacts have no `sourceHash` line / field. They are parsed
24
+ * successfully; `sourceHash` is `undefined` on the result, never
25
+ * `null`. The freshness verdict in `checkHandler` treats absent
26
+ * `sourceHash` as "unknown" — NOT as an integrity error.
27
+ *
28
+ * **Malformed / missing provenance** surfaces as `Result<...>` failure
29
+ * with one `Issue` of code `"integrity_error"`. `metadata.reason`
30
+ * records the specific sub-mode (unknown_format, missing_field,
31
+ * malformed_hash, json_parse_error, etc.) so consumers downstream can
32
+ * triage without parsing `message`. The CLI's `checkHandler` step
33
+ * (Step 10) maps an integrity_error result onto the
34
+ * `FreshnessVerdict.status = "integrity_error"` shape with exit code 4.
35
+ */
36
+ import { JSON_SCHEMA_EXTENSIONS } from "../generators/json-schema-meta.js";
37
+ const PROVENANCE_KEY = JSON_SCHEMA_EXTENSIONS.provenance; // "x-nekostack"
38
+ const SHA256_PATTERN = /^sha256:[0-9a-f]{64}$/;
39
+ /**
40
+ * Parse the provenance block out of an artifact's text content.
41
+ *
42
+ * Auto-detects the carrier by leading non-whitespace character:
43
+ * `/` → JSDoc header (TS / Zod source artifact)
44
+ * `{` → JSON document (JSON Schema / OpenAPI artifact)
45
+ * else → integrity_error / unknown_format
46
+ */
47
+ export function parseProvenanceFromText(content) {
48
+ const trimmed = content.trimStart();
49
+ if (trimmed.startsWith("/**")) {
50
+ return parseJsdocHeader(content);
51
+ }
52
+ if (trimmed.startsWith("{")) {
53
+ return parseJsonProvenance(content);
54
+ }
55
+ return fail("unknown_format", "Artifact does not start with `/**` (TS/Zod) or `{` (JSON Schema / OpenAPI).");
56
+ }
57
+ // =============================================================================
58
+ // JSDoc header parsing (TS / Zod)
59
+ // =============================================================================
60
+ const JSDOC_BLOCK = /\/\*\*([\s\S]*?)\*\//;
61
+ const JSDOC_FIELD = /^\s*\*\s+(\w+):\s*(.+?)\s*$/;
62
+ function parseJsdocHeader(content) {
63
+ const block = JSDOC_BLOCK.exec(content);
64
+ if (!block) {
65
+ return fail("missing_provenance", "No `/** ... */` JSDoc header found at the top of the artifact.");
66
+ }
67
+ const fields = new Map();
68
+ for (const line of block[1].split(/\r?\n/)) {
69
+ const m = JSDOC_FIELD.exec(line);
70
+ if (!m)
71
+ continue;
72
+ fields.set(m[1], m[2]);
73
+ }
74
+ return assembleProvenance(fields);
75
+ }
76
+ // =============================================================================
77
+ // JSON `x-nekostack` parsing (JSON Schema / OpenAPI)
78
+ // =============================================================================
79
+ function parseJsonProvenance(content) {
80
+ let doc;
81
+ try {
82
+ doc = JSON.parse(content);
83
+ }
84
+ catch (e) {
85
+ return fail("json_parse_error", `Artifact failed JSON.parse: ${e.message}`);
86
+ }
87
+ if (doc === null || typeof doc !== "object" || Array.isArray(doc)) {
88
+ return fail("missing_provenance", "Parsed JSON is not an object; cannot read `x-nekostack` provenance.");
89
+ }
90
+ const root = doc;
91
+ const provenance = root[PROVENANCE_KEY];
92
+ if (provenance === null ||
93
+ typeof provenance !== "object" ||
94
+ Array.isArray(provenance)) {
95
+ return fail("missing_provenance", `Artifact has no \`${PROVENANCE_KEY}\` provenance object at the document root.`);
96
+ }
97
+ const block = provenance;
98
+ const fields = new Map();
99
+ for (const key of [
100
+ "generator",
101
+ "generatorVersion",
102
+ "schemaId",
103
+ "schemaVersion",
104
+ "irHash",
105
+ "sourceHash",
106
+ ]) {
107
+ const v = block[key];
108
+ if (v === undefined)
109
+ continue;
110
+ // `schemaId` / `schemaVersion` may be JSON `null` for anonymous /
111
+ // unversioned schemas. Normalize to the literal string "null" so
112
+ // the assembler can apply the same rule as the JSDoc path.
113
+ if (v === null) {
114
+ fields.set(key, "null");
115
+ continue;
116
+ }
117
+ if (typeof v !== "string") {
118
+ return fail("malformed_field", `Field \`${key}\` in \`${PROVENANCE_KEY}\` must be a string or null; got ${typeof v}.`);
119
+ }
120
+ fields.set(key, v);
121
+ }
122
+ return assembleProvenance(fields);
123
+ }
124
+ // =============================================================================
125
+ // Shared field assembly + validation
126
+ // =============================================================================
127
+ function assembleProvenance(fields) {
128
+ const generator = fields.get("generator");
129
+ const generatorVersion = fields.get("generatorVersion");
130
+ const schemaIdRaw = fields.get("schemaId");
131
+ const schemaVersionRaw = fields.get("schemaVersion");
132
+ const irHash = fields.get("irHash");
133
+ const sourceHashRaw = fields.get("sourceHash");
134
+ if (generator === undefined) {
135
+ return fail("missing_field", "Provenance is missing `generator`.");
136
+ }
137
+ if (generatorVersion === undefined) {
138
+ return fail("missing_field", "Provenance is missing `generatorVersion`.");
139
+ }
140
+ if (schemaIdRaw === undefined) {
141
+ return fail("missing_field", "Provenance is missing `schemaId`.");
142
+ }
143
+ if (schemaVersionRaw === undefined) {
144
+ return fail("missing_field", "Provenance is missing `schemaVersion`.");
145
+ }
146
+ if (irHash === undefined) {
147
+ return fail("missing_field", "Provenance is missing `irHash`.");
148
+ }
149
+ if (!SHA256_PATTERN.test(irHash)) {
150
+ return fail("malformed_hash", `Provenance \`irHash\` must match \`sha256:<64 hex>\`; got "${irHash}".`);
151
+ }
152
+ if (sourceHashRaw !== undefined && !SHA256_PATTERN.test(sourceHashRaw)) {
153
+ return fail("malformed_hash", `Provenance \`sourceHash\` must match \`sha256:<64 hex>\` when present; got "${sourceHashRaw}".`);
154
+ }
155
+ return {
156
+ success: true,
157
+ data: {
158
+ generator,
159
+ generatorVersion,
160
+ schemaId: schemaIdRaw === "null" ? null : schemaIdRaw,
161
+ schemaVersion: schemaVersionRaw === "null" ? null : schemaVersionRaw,
162
+ irHash: irHash,
163
+ sourceHash: sourceHashRaw === undefined
164
+ ? undefined
165
+ : sourceHashRaw,
166
+ },
167
+ };
168
+ }
169
+ // =============================================================================
170
+ // Failure helper
171
+ // =============================================================================
172
+ function fail(reason, message) {
173
+ const issue = {
174
+ code: "integrity_error",
175
+ path: [],
176
+ message,
177
+ severity: "error",
178
+ metadata: { reason },
179
+ };
180
+ return { success: false, issues: [issue] };
181
+ }
182
+ //# sourceMappingURL=parse-provenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-provenance.js","sourceRoot":"","sources":["../../../src/registry/parse-provenance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Compute the `sourceHash` of a schema source file from its raw text
3
+ * content. Master plan Decision #7: `sourceHash` is sha256 of the
4
+ * source file's raw UTF-8 bytes — not the AST, not a canonicalized
5
+ * form. The point is to detect *any* source-text edit; canonicalizing
6
+ * would mask intentional reformatting and rebuild churn.
7
+ *
8
+ * **Pure.** No filesystem access; the CLI is responsible for reading
9
+ * the file and passing the text in. This is the load-bearing
10
+ * schema/cli boundary from Master plan Decision #1.
11
+ *
12
+ * Output format: `sha256:<64 lowercase hex chars>`. The prefixed
13
+ * template-literal type is the canonical form everywhere
14
+ * `sourceHash` appears in the v0.7 surface (`RegistryEntry`,
15
+ * `GeneratedArtifact`, `ProvenanceOptions`, etc.) so consumers can't
16
+ * accidentally confuse raw hex with the prefixed form at the type
17
+ * level.
18
+ *
19
+ * Distinct from `irHash` (`../ir/hash.ts`):
20
+ * - `irHash` — semantic identity (canonicalized IR)
21
+ * - `sourceHashFromText` — source-text identity (raw bytes)
22
+ *
23
+ * The two-hash discipline in Master plan §"Freshness verdict" is
24
+ * what `checkHandler` uses to classify each artifact as
25
+ * clean / cosmetic_drift / stale / integrity_error.
26
+ */
27
+ export declare function sourceHashFromText(text: string): `sha256:${string}`;
28
+ //# sourceMappingURL=source-hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-hash.d.ts","sourceRoot":"","sources":["../../../src/registry/source-hash.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,MAAM,EAAE,CAGnE"}
@@ -0,0 +1,32 @@
1
+ import { createHash } from "node:crypto";
2
+ /**
3
+ * Compute the `sourceHash` of a schema source file from its raw text
4
+ * content. Master plan Decision #7: `sourceHash` is sha256 of the
5
+ * source file's raw UTF-8 bytes — not the AST, not a canonicalized
6
+ * form. The point is to detect *any* source-text edit; canonicalizing
7
+ * would mask intentional reformatting and rebuild churn.
8
+ *
9
+ * **Pure.** No filesystem access; the CLI is responsible for reading
10
+ * the file and passing the text in. This is the load-bearing
11
+ * schema/cli boundary from Master plan Decision #1.
12
+ *
13
+ * Output format: `sha256:<64 lowercase hex chars>`. The prefixed
14
+ * template-literal type is the canonical form everywhere
15
+ * `sourceHash` appears in the v0.7 surface (`RegistryEntry`,
16
+ * `GeneratedArtifact`, `ProvenanceOptions`, etc.) so consumers can't
17
+ * accidentally confuse raw hex with the prefixed form at the type
18
+ * level.
19
+ *
20
+ * Distinct from `irHash` (`../ir/hash.ts`):
21
+ * - `irHash` — semantic identity (canonicalized IR)
22
+ * - `sourceHashFromText` — source-text identity (raw bytes)
23
+ *
24
+ * The two-hash discipline in Master plan §"Freshness verdict" is
25
+ * what `checkHandler` uses to classify each artifact as
26
+ * clean / cosmetic_drift / stale / integrity_error.
27
+ */
28
+ export function sourceHashFromText(text) {
29
+ const digest = createHash("sha256").update(text, "utf8").digest("hex");
30
+ return `sha256:${digest}`;
31
+ }
32
+ //# sourceMappingURL=source-hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-hash.js","sourceRoot":"","sources":["../../../src/registry/source-hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,UAAU,MAAM,EAAE,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Type definitions for the v0.7 schema-side registry surface.
3
+ *
4
+ * This module is **types only** — no functions, no constants beyond
5
+ * what TypeScript requires for the type definitions themselves. All
6
+ * runtime behavior (registry construction, diff classification,
7
+ * freshness verdict computation, generation planning) lives in the
8
+ * sibling modules that import these types.
9
+ *
10
+ * Boundary recap (Master plan Decision #1):
11
+ * - `@nekostack/schema` is **pure** — no `fs.*`, no `import()`, no
12
+ * `process.*`, no `console.*`. Takes data, returns data.
13
+ * - `@nekostack/cli` is the **filesystem shell** — loads schema files
14
+ * via `tsx`, reads source bytes, reads committed artifacts, writes
15
+ * regenerated artifacts, owns stdout / stderr / exit codes.
16
+ *
17
+ * Re-exported from the package-internal integration subpath
18
+ * `@nekostack/schema/cli` (Master plan Decision #10). Root
19
+ * `@nekostack/schema` does NOT expose these names.
20
+ */
21
+ import type { SchemaNode } from "../ir/nodes.js";
22
+ import type { AnySchema } from "../builders/schema.js";
23
+ import type { IssuePath, Result } from "../errors/issue.js";
24
+ /**
25
+ * One discovered `*.schema.{ts,js}` source file, after the CLI has
26
+ * read its bytes and dynamic-imported it via `tsx`.
27
+ *
28
+ * `schemas` is the array of every `export const X = s.object(...)`
29
+ * (or any other `Schema` instance) the file exposes. A file may
30
+ * legitimately declare more than one schema; the registry indexes
31
+ * each.
32
+ */
33
+ export interface RegistrySourceEntry {
34
+ readonly sourcePath: string;
35
+ readonly sourceText: string;
36
+ readonly schemas: readonly AnySchema[];
37
+ }
38
+ /**
39
+ * One indexed schema. The registry stores these by
40
+ * `(schemaId, schemaVersion)` (Master plan Decision #4).
41
+ *
42
+ * `schemaVersion` is `undefined` when the source schema omitted
43
+ * `.version(...)`. In the `Registry` map's inner key the version is
44
+ * stored as the empty string `""` for the unversioned case, so the
45
+ * lookup type stays uniform.
46
+ */
47
+ export interface RegistryEntry {
48
+ readonly schemaId: string;
49
+ readonly schemaVersion: string | undefined;
50
+ readonly irHash: `sha256:${string}`;
51
+ readonly sourceHash: `sha256:${string}`;
52
+ readonly sourcePath: string;
53
+ readonly schema: AnySchema;
54
+ }
55
+ /**
56
+ * Two-level map: outer key is `schemaId`, inner key is `schemaVersion`
57
+ * (or the empty string `""` for an entry whose source did not call
58
+ * `.version(...)`). `buildRegistry` is the only legitimate producer
59
+ * of `Registry` values; downstream callers treat them as opaque.
60
+ */
61
+ export type Registry = ReadonlyMap<string, ReadonlyMap<string, RegistryEntry>>;
62
+ /**
63
+ * Severity of a single `DiffChange`. The `worstSeverity` field on
64
+ * `DiffResult` is the max over a change set, with `breaking` >
65
+ * `additive` > `cosmetic`. Master plan Decision #11 + #12 lock the
66
+ * classification table; this enum is the column header.
67
+ */
68
+ export type DiffSeverity = "breaking" | "additive" | "cosmetic";
69
+ /**
70
+ * What kind of change a `DiffChange` represents. The shape of change
71
+ * — not its severity. Locked per Master plan Decision #12; severity
72
+ * for each kind depends on which row of the table the specific
73
+ * before/after pair lands on.
74
+ */
75
+ export type DiffKind = "field_added" | "field_removed" | "refinement_changed" | "unknown_keys_changed" | "enum_value_added" | "enum_value_removed" | "literal_changed" | "default_added" | "default_removed" | "default_value_changed" | "absence_modifier_changed" | "metadata_changed" | "refinements_reordered" | "schema_version_changed" | "type_changed";
76
+ export interface DiffChange {
77
+ readonly severity: DiffSeverity;
78
+ readonly path: IssuePath;
79
+ readonly kind: DiffKind;
80
+ readonly before?: unknown;
81
+ readonly after?: unknown;
82
+ readonly message: string;
83
+ }
84
+ /**
85
+ * The per-artifact outcome of the two-hash freshness matrix
86
+ * (Master plan §"Freshness verdict — two-hash discipline").
87
+ *
88
+ * - `clean` — both hashes match the schema source.
89
+ * - `cosmetic_drift` — sourceHash differs, irHash matches. Source
90
+ * text edited without semantic effect. CLI
91
+ * prints a stderr warning; CI still passes.
92
+ * - `stale` — irHash differs. Regenerate required. CLI
93
+ * exits 1.
94
+ * - `integrity_error` — sourceHash matches, irHash differs. The
95
+ * impossible row of the matrix; if the artifact
96
+ * was generated from the recorded source text,
97
+ * irHash must match too. Indicates a manual
98
+ * artifact edit, provenance tampering, or
99
+ * hash inconsistency. CLI exits 4 and refuses
100
+ * to auto-regenerate.
101
+ */
102
+ export type FreshnessVerdict = {
103
+ readonly status: "clean";
104
+ readonly artifactPath: string;
105
+ } | {
106
+ readonly status: "cosmetic_drift";
107
+ readonly artifactPath: string;
108
+ } | {
109
+ readonly status: "stale";
110
+ readonly artifactPath: string;
111
+ } | {
112
+ readonly status: "integrity_error";
113
+ readonly artifactPath: string;
114
+ };
115
+ /**
116
+ * The four artifact kinds `generateHandler` plans for every schema
117
+ * in v0.7. Partial generation (subset of kinds) is explicitly NOT
118
+ * supported in v0.7 — `generate` writes all four; `check` expects
119
+ * all four (Master plan Decision #6).
120
+ */
121
+ export type GeneratorKind = "typescript" | "zod" | "jsonSchema" | "openApi";
122
+ /**
123
+ * One emit-ready artifact returned by `generateHandler`. The
124
+ * schema-side handler does NOT write the file; it returns the
125
+ * payload and the path the CLI should write it at. The
126
+ * `suggestedPath` is relative to the source schema's directory and
127
+ * follows the `<schema-dir>/generated/<basename>.<kind>` convention
128
+ * locked in Master plan Decision #6.
129
+ */
130
+ export interface GeneratedArtifact {
131
+ readonly schemaId: string;
132
+ readonly kind: GeneratorKind;
133
+ readonly suggestedPath: string;
134
+ readonly content: string;
135
+ readonly irHash: `sha256:${string}`;
136
+ readonly sourceHash: `sha256:${string}`;
137
+ }
138
+ /**
139
+ * One on-disk artifact whose bytes the CLI has already read. The
140
+ * handler parses the provenance block (JSDoc header for TS/Zod;
141
+ * `x-nekostack` for JSON Schema / OpenAPI), compares against the
142
+ * current schema source, and emits a `FreshnessVerdict`.
143
+ */
144
+ export interface CommittedArtifact {
145
+ readonly path: string;
146
+ readonly content: string;
147
+ }
148
+ export interface GenerateOpts {
149
+ readonly entries: readonly RegistrySourceEntry[];
150
+ }
151
+ export type GenerateResult = Result<{
152
+ readonly artifacts: readonly GeneratedArtifact[];
153
+ }>;
154
+ export interface CheckOpts {
155
+ /**
156
+ * Already-built registry. The CLI calls `buildRegistry` once,
157
+ * handles duplicate-detection failures upstream, and passes the
158
+ * same `Registry` to every handler (list / diff / check / generate).
159
+ */
160
+ readonly registry: Registry;
161
+ /**
162
+ * Already-read generated artifacts. The CLI owns filesystem reads;
163
+ * `checkHandler` only parses content and classifies freshness via
164
+ * the two-hash matrix.
165
+ */
166
+ readonly committedArtifacts: readonly CommittedArtifact[];
167
+ }
168
+ export type CheckResult = Result<{
169
+ readonly verdicts: readonly FreshnessVerdict[];
170
+ }>;
171
+ export interface DiffOpts {
172
+ readonly before: SchemaNode;
173
+ readonly after: SchemaNode;
174
+ }
175
+ export type DiffResult = Result<{
176
+ readonly changes: readonly DiffChange[];
177
+ readonly worstSeverity: DiffSeverity | null;
178
+ }>;
179
+ export interface ListOpts {
180
+ readonly registry: Registry;
181
+ }
182
+ export type ListResult = Result<{
183
+ readonly entries: readonly RegistryEntry[];
184
+ }>;
185
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/registry/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Type definitions for the v0.7 schema-side registry surface.
3
+ *
4
+ * This module is **types only** — no functions, no constants beyond
5
+ * what TypeScript requires for the type definitions themselves. All
6
+ * runtime behavior (registry construction, diff classification,
7
+ * freshness verdict computation, generation planning) lives in the
8
+ * sibling modules that import these types.
9
+ *
10
+ * Boundary recap (Master plan Decision #1):
11
+ * - `@nekostack/schema` is **pure** — no `fs.*`, no `import()`, no
12
+ * `process.*`, no `console.*`. Takes data, returns data.
13
+ * - `@nekostack/cli` is the **filesystem shell** — loads schema files
14
+ * via `tsx`, reads source bytes, reads committed artifacts, writes
15
+ * regenerated artifacts, owns stdout / stderr / exit codes.
16
+ *
17
+ * Re-exported from the package-internal integration subpath
18
+ * `@nekostack/schema/cli` (Master plan Decision #10). Root
19
+ * `@nekostack/schema` does NOT expose these names.
20
+ */
21
+ export {};
22
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/registry/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}