@invariant-ui/cli 0.0.0-stage → 0.2.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 (190) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +250 -2
  3. package/dist/agent-kit/apply.js +232 -0
  4. package/dist/agent-kit/guidance.js +236 -0
  5. package/dist/agent-kit/index.js +5 -0
  6. package/dist/agent-kit/integrations.js +121 -0
  7. package/dist/agent-kit/plugin.js +115 -0
  8. package/dist/artifact-generator/index.js +75 -0
  9. package/dist/browser-verify/driver.js +2 -0
  10. package/dist/browser-verify/index.js +4 -0
  11. package/dist/browser-verify/playwright.js +82 -0
  12. package/dist/browser-verify/runner.js +175 -0
  13. package/dist/browser-verify/spec.js +103 -0
  14. package/dist/cli/args.js +77 -0
  15. package/dist/cli/baseline.js +64 -0
  16. package/dist/cli/cli.js +121 -0
  17. package/dist/cli/commands-browser.js +104 -0
  18. package/dist/cli/commands-discover.js +312 -0
  19. package/dist/cli/commands-enforcement.js +35 -0
  20. package/dist/cli/commands-governance.js +179 -0
  21. package/dist/cli/commands-hook.js +269 -0
  22. package/dist/cli/commands-patterns.js +324 -0
  23. package/dist/cli/commands-setup.js +485 -0
  24. package/dist/cli/commands-validate.js +157 -0
  25. package/dist/cli/commands.js +517 -0
  26. package/dist/cli/config.js +197 -0
  27. package/dist/cli/diff.js +66 -0
  28. package/dist/cli/enforcement-log.js +83 -0
  29. package/dist/cli/enforcement-report.js +96 -0
  30. package/dist/cli/errors.js +10 -0
  31. package/dist/cli/format.js +22 -0
  32. package/dist/cli/index.js +5 -0
  33. package/dist/cli/io.js +2 -0
  34. package/dist/cli/main.js +31 -0
  35. package/dist/cli/pipeline.js +262 -0
  36. package/dist/cli/publish.js +77 -0
  37. package/dist/cli/report.js +127 -0
  38. package/dist/cli/starter-rules.js +57 -0
  39. package/dist/cli/store.js +60 -0
  40. package/dist/cli/version.js +5 -0
  41. package/dist/cli/watch.js +68 -0
  42. package/dist/cli/workflow.js +52 -0
  43. package/dist/compiler-angular/adapter.js +115 -0
  44. package/dist/compiler-angular/analyze.js +222 -0
  45. package/dist/compiler-angular/classes.js +446 -0
  46. package/dist/compiler-angular/declared.js +285 -0
  47. package/dist/compiler-angular/emit.js +183 -0
  48. package/dist/compiler-angular/index.js +4 -0
  49. package/dist/compiler-angular/template.js +142 -0
  50. package/dist/compiler-core/adapter.js +2 -0
  51. package/dist/compiler-core/adapters/inventory.js +312 -0
  52. package/dist/compiler-core/compile.js +148 -0
  53. package/dist/compiler-core/component-facts.js +123 -0
  54. package/dist/compiler-core/discovery/docs.js +66 -0
  55. package/dist/compiler-core/discovery/entries.js +270 -0
  56. package/dist/compiler-core/discovery/exports.js +207 -0
  57. package/dist/compiler-core/discovery/graph.js +59 -0
  58. package/dist/compiler-core/discovery/index.js +103 -0
  59. package/dist/compiler-core/discovery/packages.js +148 -0
  60. package/dist/compiler-core/discovery/schema.js +144 -0
  61. package/dist/compiler-core/discovery/storybook.js +232 -0
  62. package/dist/compiler-core/discovery/support.js +82 -0
  63. package/dist/compiler-core/discovery/tokens.js +186 -0
  64. package/dist/compiler-core/discovery/tooling.js +146 -0
  65. package/dist/compiler-core/fs.js +89 -0
  66. package/dist/compiler-core/glob.js +3 -0
  67. package/dist/compiler-core/index.js +16 -0
  68. package/dist/compiler-core/ir-builder.js +68 -0
  69. package/dist/compiler-core/json-schema.js +11 -0
  70. package/dist/compiler-core/testing/index.js +81 -0
  71. package/dist/compiler-core/ts/ast.js +166 -0
  72. package/dist/compiler-core/ts/members.js +163 -0
  73. package/dist/compiler-core/ts/program.js +81 -0
  74. package/dist/compiler-core/ts/static-eval.js +145 -0
  75. package/dist/compiler-core/ts/tsconfig-paths.js +60 -0
  76. package/dist/compiler-core/walk.js +46 -0
  77. package/dist/compiler-ir/index.js +4 -0
  78. package/dist/compiler-ir/ir.js +67 -0
  79. package/dist/compiler-ir/json-schema.js +6 -0
  80. package/dist/compiler-ir/validate.js +116 -0
  81. package/dist/compiler-react/adapter.js +147 -0
  82. package/dist/compiler-react/analyze.js +199 -0
  83. package/dist/compiler-react/behavior.js +75 -0
  84. package/dist/compiler-react/detect.js +558 -0
  85. package/dist/compiler-react/emit.js +188 -0
  86. package/dist/compiler-react/index.js +2 -0
  87. package/dist/compiler-react/props.js +157 -0
  88. package/dist/compiler-react/styling.js +138 -0
  89. package/dist/compiler-react/usage.js +116 -0
  90. package/dist/compiler-react/variants.js +111 -0
  91. package/dist/compiler-storybook/adapter.js +253 -0
  92. package/dist/compiler-storybook/csf.js +521 -0
  93. package/dist/compiler-storybook/emit.js +202 -0
  94. package/dist/compiler-storybook/index-json.js +41 -0
  95. package/dist/compiler-storybook/index.js +5 -0
  96. package/dist/compiler-storybook/mdx.js +120 -0
  97. package/dist/compiler-tokens/adapter.js +158 -0
  98. package/dist/compiler-tokens/css.js +59 -0
  99. package/dist/compiler-tokens/index.js +5 -0
  100. package/dist/compiler-tokens/json-lines.js +106 -0
  101. package/dist/compiler-tokens/json-tokens.js +52 -0
  102. package/dist/compiler-vue/adapter.js +107 -0
  103. package/dist/compiler-vue/analyze.js +344 -0
  104. package/dist/compiler-vue/declared.js +343 -0
  105. package/dist/compiler-vue/emit.js +129 -0
  106. package/dist/compiler-vue/index.js +5 -0
  107. package/dist/compiler-vue/script.js +472 -0
  108. package/dist/compiler-vue/sfc.js +44 -0
  109. package/dist/compiler-vue/template.js +73 -0
  110. package/dist/contract/archetype-checks.js +153 -0
  111. package/dist/contract/components.js +102 -0
  112. package/dist/contract/conflicts.js +39 -0
  113. package/dist/contract/contract.js +46 -0
  114. package/dist/contract/evidence.js +84 -0
  115. package/dist/contract/fact-path.js +39 -0
  116. package/dist/contract/facts.js +62 -0
  117. package/dist/contract/index.js +16 -0
  118. package/dist/contract/integrity.js +21 -0
  119. package/dist/contract/json-schema.js +11 -0
  120. package/dist/contract/knowledge.js +95 -0
  121. package/dist/contract/pattern-checks.js +254 -0
  122. package/dist/contract/patterns.js +225 -0
  123. package/dist/contract/primitives.js +81 -0
  124. package/dist/contract/sources.js +30 -0
  125. package/dist/contract/tokens.js +41 -0
  126. package/dist/contract/validate.js +253 -0
  127. package/dist/contract-query/archetype.js +188 -0
  128. package/dist/contract-query/index.js +6 -0
  129. package/dist/contract-query/patterns.js +298 -0
  130. package/dist/contract-query/search.js +132 -0
  131. package/dist/contract-query/system.js +148 -0
  132. package/dist/contract-query/views.js +288 -0
  133. package/dist/governance/decisions.js +229 -0
  134. package/dist/governance/index.js +5 -0
  135. package/dist/governance/patterns-file.js +156 -0
  136. package/dist/governance/patterns.js +510 -0
  137. package/dist/governance/policies.js +148 -0
  138. package/dist/mcp/index.js +7 -0
  139. package/dist/mcp/loader.js +70 -0
  140. package/dist/mcp/protocol.js +27 -0
  141. package/dist/mcp/resources.js +138 -0
  142. package/dist/mcp/server.js +177 -0
  143. package/dist/mcp/stdio.js +28 -0
  144. package/dist/mcp/tools.js +267 -0
  145. package/dist/reconciliation/code.js +62 -0
  146. package/dist/reconciliation/components.js +401 -0
  147. package/dist/reconciliation/conflicts.js +126 -0
  148. package/dist/reconciliation/facts.js +41 -0
  149. package/dist/reconciliation/index.js +7 -0
  150. package/dist/reconciliation/reconcile.js +134 -0
  151. package/dist/reconciliation/resolve.js +158 -0
  152. package/dist/reconciliation/review.js +81 -0
  153. package/dist/reconciliation/storybook.js +370 -0
  154. package/dist/reconciliation/tokens.js +179 -0
  155. package/dist/reconciliation/util.js +55 -0
  156. package/dist/semantic-engine/additive.js +51 -0
  157. package/dist/semantic-engine/compounds.js +91 -0
  158. package/dist/semantic-engine/documents.js +157 -0
  159. package/dist/semantic-engine/enrich.js +42 -0
  160. package/dist/semantic-engine/index.js +7 -0
  161. package/dist/semantic-engine/infer.js +38 -0
  162. package/dist/semantic-engine/tokens.js +120 -0
  163. package/dist/shared/canonical.js +65 -0
  164. package/dist/shared/diagnostic.js +78 -0
  165. package/dist/shared/glob.js +98 -0
  166. package/dist/shared/index.js +4 -0
  167. package/dist/shared/json.js +2 -0
  168. package/dist/validation/card.js +50 -0
  169. package/dist/validation/discovery/arrangements.js +162 -0
  170. package/dist/validation/discovery/discover.js +70 -0
  171. package/dist/validation/discovery/index.js +8 -0
  172. package/dist/validation/discovery/model.js +127 -0
  173. package/dist/validation/discovery/promote.js +24 -0
  174. package/dist/validation/discovery/reviews.js +63 -0
  175. package/dist/validation/discovery/shapes.js +47 -0
  176. package/dist/validation/discovery/similar-files.js +146 -0
  177. package/dist/validation/discovery/util.js +47 -0
  178. package/dist/validation/index.js +11 -0
  179. package/dist/validation/interaction-facts.js +341 -0
  180. package/dist/validation/interaction-workflows.js +633 -0
  181. package/dist/validation/literals.js +251 -0
  182. package/dist/validation/pattern-rules.js +608 -0
  183. package/dist/validation/policy.js +241 -0
  184. package/dist/validation/report.js +163 -0
  185. package/dist/validation/rules.js +269 -0
  186. package/dist/validation/scan.js +295 -0
  187. package/dist/validation/text.js +34 -0
  188. package/dist/validation/validate-code.js +513 -0
  189. package/dist/validation/validate-usage.js +196 -0
  190. package/package.json +38 -4
@@ -0,0 +1,153 @@
1
+ /** The parts of a pattern, with a variation's role changes and additions applied. */
2
+ export function effectiveParts(p, variationId) {
3
+ const base = (p.composition?.parts ?? []).map((x) => ({
4
+ name: x.name,
5
+ ref: x.ref,
6
+ role: x.role,
7
+ region: x.region
8
+ }));
9
+ const v = variationId === undefined ? undefined : p.variations?.find((x) => x.name === variationId);
10
+ if (!v)
11
+ return base;
12
+ const roles = new Map((v.roles ?? []).map((r) => [r.part, r.role]));
13
+ return [
14
+ ...base.map((x) => ({ ...x, role: roles.get(x.name) ?? x.role })),
15
+ ...(v.parts ?? []).map((x) => ({ name: x.name, ref: x.ref, role: x.role, region: x.region }))
16
+ ];
17
+ }
18
+ const COMPOSING = new Set(["composes", "contains", "uses", "requires"]);
19
+ /** Patterns a pattern builds on: its non-prohibited parts that are patterns, and what it composes or contains. */
20
+ function uses(p, parts) {
21
+ const out = new Set();
22
+ for (const x of parts)
23
+ if (x.role !== "prohibited" && x.ref.startsWith("pattern:"))
24
+ out.add(x.ref);
25
+ for (const r of p.relationships ?? [])
26
+ if (COMPOSING.has(r.type) && r.target.startsWith("pattern:"))
27
+ out.add(r.target);
28
+ return [...out].sort();
29
+ }
30
+ /**
31
+ * Everything reachable from a pattern's effective parts, with the chain of patterns that leads to it. Patterns
32
+ * (and the components their parts name) are both included. Nested patterns contribute their base composition.
33
+ */
34
+ function reach(byId, root, parts) {
35
+ const patterns = new Map();
36
+ const refs = new Map();
37
+ const seen = new Set([root.id]);
38
+ const walk = (p, ps, chain) => {
39
+ for (const x of ps)
40
+ if (x.role !== "prohibited" && !refs.has(x.ref))
41
+ refs.set(x.ref, chain);
42
+ for (const next of uses(p, ps)) {
43
+ if (!refs.has(next))
44
+ refs.set(next, chain);
45
+ if (seen.has(next))
46
+ continue;
47
+ seen.add(next);
48
+ const n = byId.get(next);
49
+ if (!n)
50
+ continue;
51
+ patterns.set(next, [...chain, next]);
52
+ walk(n, effectiveParts(n), [...chain, next]);
53
+ }
54
+ };
55
+ walk(root, parts, [root.id]);
56
+ return { patterns, refs };
57
+ }
58
+ const label = (v) => (v === undefined ? "" : ` in variation "${v}"`);
59
+ /** A variation changes real parts, adds uniquely named ones, and places them in real regions. */
60
+ export function checkVariations(p, error) {
61
+ const base = new Set((p.composition?.parts ?? []).map((x) => x.name));
62
+ const regions = new Set((p.layout?.regions ?? []).map((r) => r.name));
63
+ const names = (p.variations ?? []).map((v) => v.name);
64
+ for (const name of new Set(names.filter((x, i) => names.indexOf(x) !== i)))
65
+ error("contract.pattern-duplicate-name", `${p.id} has more than one variation named "${name}"`, p.id);
66
+ for (const v of p.variations ?? []) {
67
+ const changed = new Set();
68
+ for (const r of v.roles ?? []) {
69
+ if (!base.has(r.part))
70
+ error("contract.pattern-variation-unknown-part", `${p.id} variation "${v.name}" changes part "${r.part}", which the composition does not have`, p.id);
71
+ if (changed.has(r.part))
72
+ error("contract.pattern-duplicate-name", `${p.id} variation "${v.name}" changes part "${r.part}" twice`, p.id);
73
+ changed.add(r.part);
74
+ }
75
+ const added = new Set();
76
+ for (const x of v.parts ?? []) {
77
+ if (base.has(x.name) || added.has(x.name))
78
+ error("contract.pattern-duplicate-name", `${p.id} variation "${v.name}" adds a part named "${x.name}", which already exists`, p.id);
79
+ added.add(x.name);
80
+ if (x.region !== undefined && !regions.has(x.region))
81
+ error("contract.pattern-region-unknown", `${p.id} variation "${v.name}" places part "${x.name}" in unknown region "${x.region}"`, p.id);
82
+ }
83
+ }
84
+ }
85
+ /**
86
+ * Follows what each pattern composes, through the patterns it uses, and reports what cannot hold together:
87
+ * two patterns declared prohibited together that one blueprint composes, a part a blueprint prohibits that
88
+ * something it composes brings back, a pattern that another supersedes, and a required region nothing fills.
89
+ * Each pattern is checked as written and once per variation.
90
+ */
91
+ export function checkArchetypes(contract, error, warn) {
92
+ const byId = new Map(contract.patterns.map((p) => [p.id, p]));
93
+ const supersededBy = new Map();
94
+ for (const p of contract.patterns)
95
+ for (const r of p.relationships ?? [])
96
+ if (r.type === "supersedes")
97
+ supersededBy.set(r.target, p.id);
98
+ const reported = new Set();
99
+ const once = (key, fn) => {
100
+ if (reported.has(key))
101
+ return;
102
+ reported.add(key);
103
+ fn();
104
+ };
105
+ for (const p of contract.patterns) {
106
+ const ids = [undefined, ...(p.variations ?? []).map((v) => v.name)];
107
+ for (const variation of ids) {
108
+ const parts = effectiveParts(p, variation);
109
+ const { patterns, refs } = reach(byId, p, parts);
110
+ const inside = new Set([p.id, ...patterns.keys()]);
111
+ for (const id of inside) {
112
+ const x = byId.get(id);
113
+ for (const rel of x?.relationships ?? []) {
114
+ if (rel.type !== "prohibited-with" || rel.target === id || !inside.has(rel.target))
115
+ continue;
116
+ const [a, b] = [id, rel.target].sort();
117
+ // Base first: a pair already reported for the blueprint as written is not repeated for its variations.
118
+ once(`${p.id}|${a}+${b}`, () => error("contract.pattern-prohibited-combination", `${p.id}${label(variation)} composes both ${a} and ${b}, which are prohibited together (${id} prohibited-with ${rel.target})`, p.id));
119
+ }
120
+ }
121
+ for (const part of parts) {
122
+ if (part.role !== "prohibited")
123
+ continue;
124
+ const chain = refs.get(part.ref);
125
+ // A part is a slot: another slot of the same pattern using the same component is not a conflict. Only what
126
+ // a composed pattern brings in is.
127
+ if (chain === undefined || chain.length < 2)
128
+ continue;
129
+ once(`${p.id}|prohibits|${part.ref}|${part.name}`, () => error("contract.pattern-prohibited-conflict", `${p.id}${label(variation)} prohibits ${part.ref} (part "${part.name}"), but ${chain.join(" -> ")} brings it in`, p.id));
130
+ }
131
+ if (variation === undefined)
132
+ for (const target of [...refs.keys()].filter((r) => r.startsWith("pattern:"))) {
133
+ const by = supersededBy.get(target);
134
+ if (by !== undefined && by !== p.id)
135
+ once(`${p.id}|superseded|${target}`, () => warn("contract.pattern-superseded-reference", `${p.id} builds on ${target}, which ${by} supersedes`, p.id));
136
+ }
137
+ }
138
+ if (p.inheritsConstraints === true) {
139
+ if (!p.appliesTo?.paths)
140
+ error("contract.pattern-inheritance-unscoped", `${p.id} inherits constraints but names no appliesTo.paths, so there is no way to know which files to hold to them`, p.id);
141
+ if (!p.composition)
142
+ warn("contract.pattern-inheritance-empty", `${p.id} inherits constraints but composes nothing, so there is nothing to inherit`, p.id);
143
+ }
144
+ if (p.layout && p.composition)
145
+ for (const r of p.layout.regions) {
146
+ if (!r.required)
147
+ continue;
148
+ if (!p.composition.parts.some((x) => x.role !== "prohibited" && x.region === r.name))
149
+ warn("contract.pattern-region-unfilled", `${p.id} requires region "${r.name}", but no composition part is placed in it`, p.id);
150
+ }
151
+ }
152
+ }
153
+ //# sourceMappingURL=archetype-checks.js.map
@@ -0,0 +1,102 @@
1
+ import { z } from "zod";
2
+ import { factsSchema } from "./facts.js";
3
+ import { componentIdSchema, entityIdSchema, extensionsSchema, frameworkSchema, jsonValueSchema, slugSchema, sourceIdSchema } from "./primitives.js";
4
+ export const deprecationSchema = z.strictObject({
5
+ reason: z.string().min(1).optional(),
6
+ replacedBy: entityIdSchema.optional()
7
+ });
8
+ /** Framework-neutral type description. `text` is the source's own spelling. */
9
+ export const typeRefSchema = z.strictObject({
10
+ text: z.string().min(1),
11
+ kind: z
12
+ .enum([
13
+ "string",
14
+ "number",
15
+ "boolean",
16
+ "enum",
17
+ "function",
18
+ "component",
19
+ "object",
20
+ "array",
21
+ "union",
22
+ "unknown"
23
+ ])
24
+ .optional()
25
+ });
26
+ export const propSchema = z.strictObject({
27
+ name: z.string().min(1),
28
+ type: typeRefSchema,
29
+ required: z.boolean(),
30
+ default: jsonValueSchema.optional(),
31
+ allowedValues: z.array(z.union([z.string(), z.number().finite(), z.boolean()])).optional(),
32
+ description: z.string().optional(),
33
+ deprecated: deprecationSchema.optional(),
34
+ extensions: extensionsSchema.optional()
35
+ });
36
+ export const eventSchema = z.strictObject({
37
+ name: z.string().min(1),
38
+ payload: typeRefSchema.optional(),
39
+ description: z.string().optional(),
40
+ deprecated: deprecationSchema.optional(),
41
+ extensions: extensionsSchema.optional()
42
+ });
43
+ export const slotSchema = z.strictObject({
44
+ name: z.string().min(1),
45
+ description: z.string().optional(),
46
+ required: z.boolean().optional(),
47
+ accepts: z.array(componentIdSchema).optional(),
48
+ extensions: extensionsSchema.optional()
49
+ });
50
+ export const variantSchema = z.strictObject({
51
+ name: z.string().min(1),
52
+ values: z.array(z.string().min(1)).min(1),
53
+ default: z.string().min(1).optional(),
54
+ description: z.string().optional()
55
+ });
56
+ export const stateSchema = z.strictObject({ name: z.string().min(1), description: z.string().optional() });
57
+ export const accessibilitySchema = z.strictObject({
58
+ role: z.string().min(1).optional(),
59
+ attributes: z.array(z.string().min(1)).optional(),
60
+ keyboard: z.array(z.string().min(1)).optional(),
61
+ requirements: z.array(z.string().min(1)).optional()
62
+ });
63
+ export const exampleSchema = z.strictObject({
64
+ id: slugSchema,
65
+ title: z.string().optional(),
66
+ language: z.string().min(1),
67
+ code: z.string().min(1),
68
+ sourceId: sourceIdSchema.optional()
69
+ });
70
+ export const relationshipSchema = z.strictObject({
71
+ type: z.enum(["contains", "requires-parent", "commonly-used-with", "extends"]),
72
+ target: componentIdSchema
73
+ });
74
+ /** One concrete implementation of a conceptual component, in one framework, from one source. */
75
+ export const implementationSchema = z.strictObject({
76
+ id: slugSchema,
77
+ framework: frameworkSchema,
78
+ sourceId: sourceIdSchema,
79
+ packageName: z.string().min(1).optional(),
80
+ exportName: z.string().min(1).optional(),
81
+ importPath: z.string().min(1).optional(),
82
+ extensions: extensionsSchema.optional()
83
+ });
84
+ export const componentSchema = z.strictObject({
85
+ id: componentIdSchema,
86
+ name: z.string().min(1),
87
+ description: z.string().optional(),
88
+ lifecycle: z.enum(["stable", "experimental", "deprecated"]).optional(),
89
+ deprecated: deprecationSchema.optional(),
90
+ implementations: z.array(implementationSchema),
91
+ props: z.array(propSchema),
92
+ events: z.array(eventSchema),
93
+ slots: z.array(slotSchema),
94
+ variants: z.array(variantSchema),
95
+ states: z.array(stateSchema),
96
+ accessibility: accessibilitySchema.optional(),
97
+ examples: z.array(exampleSchema),
98
+ composition: z.array(relationshipSchema),
99
+ facts: factsSchema,
100
+ extensions: extensionsSchema.optional()
101
+ });
102
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+ import { evidenceIdSchema } from "./evidence.js";
3
+ import { factStatusSchema } from "./facts.js";
4
+ import { conflictIdSchema, entityIdSchema, factPathSchema, isoTimestampSchema, jsonValueSchema, sourceIdSchema } from "./primitives.js";
5
+ export const claimSchema = z.strictObject({
6
+ sourceId: sourceIdSchema,
7
+ /** Absent means the source asserts the field does not exist or has no value, which is distinct from null. */
8
+ value: jsonValueSchema.optional(),
9
+ status: factStatusSchema,
10
+ evidenceIds: z.array(evidenceIdSchema).min(1)
11
+ });
12
+ export const conflictSchema = z.strictObject({
13
+ id: conflictIdSchema,
14
+ type: z.enum([
15
+ "value-mismatch",
16
+ "existence-mismatch",
17
+ "deprecation-mismatch",
18
+ "identity-ambiguity",
19
+ "token-value-mismatch",
20
+ "documentation-gap"
21
+ ]),
22
+ severity: z.enum(["error", "warning", "info"]),
23
+ subject: entityIdSchema,
24
+ path: factPathSchema.optional(),
25
+ claims: z.array(claimSchema).min(2),
26
+ suggestedResolution: z.string().min(1).optional(),
27
+ resolution: z.discriminatedUnion("state", [
28
+ z.strictObject({ state: z.literal("open") }),
29
+ z.strictObject({
30
+ state: z.enum(["resolved", "accepted", "dismissed"]),
31
+ /** The chosen source, when the resolution selects one claim. Losing claims are never deleted. */
32
+ chosenSourceId: sourceIdSchema.optional(),
33
+ decidedBy: z.string().min(1),
34
+ decidedAt: isoTimestampSchema,
35
+ note: z.string().min(1).optional()
36
+ })
37
+ ])
38
+ });
39
+ //# sourceMappingURL=conflicts.js.map
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ import { componentSchema } from "./components.js";
3
+ import { conflictSchema } from "./conflicts.js";
4
+ import { constraintSchema, guidelineSchema, patternSchema, policySchema } from "./knowledge.js";
5
+ import { frameworkSchema, isoTimestampSchema, sha256HexSchema, slugSchema } from "./primitives.js";
6
+ import { sourceSchema } from "./sources.js";
7
+ import { themeSchema, tokenSchema } from "./tokens.js";
8
+ /**
9
+ * 1.1.0 added pattern contracts. Every new field is optional, so a 1.0.0 document is also a valid 1.1.0 document:
10
+ * nothing is rewritten when one is read, and its content hash stays valid. Writers emit the current version.
11
+ */
12
+ export const SUPPORTED_CONTRACT_VERSIONS = ["1.0.0", "1.1.0"];
13
+ export const CONTRACT_VERSION = "1.1.0";
14
+ export const contractMetadataSchema = z.strictObject({
15
+ /** Stable identity of the design system across contract versions. */
16
+ contractId: slugSchema,
17
+ name: z.string().min(1),
18
+ description: z.string().optional(),
19
+ compilerVersion: z.string().min(1),
20
+ frameworks: z.array(frameworkSchema),
21
+ /** Excluded from the content hash. */
22
+ compiledAt: isoTimestampSchema
23
+ });
24
+ export const integritySchema = z.strictObject({
25
+ algorithm: z.literal("sha256"),
26
+ contentHash: sha256HexSchema
27
+ });
28
+ /**
29
+ * Canonical design-system contract. Collections are sorted by id; per-source versions live in
30
+ * `sources[].version`. Evidence is stored in a separate evidence file and referenced by id.
31
+ */
32
+ export const contractSchema = z.strictObject({
33
+ contractVersion: z.enum(SUPPORTED_CONTRACT_VERSIONS),
34
+ metadata: contractMetadataSchema,
35
+ sources: z.array(sourceSchema),
36
+ themes: z.array(themeSchema),
37
+ components: z.array(componentSchema),
38
+ tokens: z.array(tokenSchema),
39
+ patterns: z.array(patternSchema),
40
+ guidelines: z.array(guidelineSchema),
41
+ constraints: z.array(constraintSchema),
42
+ policies: z.array(policySchema),
43
+ conflicts: z.array(conflictSchema),
44
+ integrity: integritySchema
45
+ });
46
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1,84 @@
1
+ import { hashJson } from "../shared/index.js";
2
+ import { z } from "zod";
3
+ import { confidenceSchema, isoTimestampSchema, relativePathSchema, sha256HexSchema, sourceIdSchema } from "./primitives.js";
4
+ export const EVIDENCE_VERSION = "1.0.0";
5
+ export const evidenceIdSchema = z.string().regex(/^ev_[0-9a-f]{24}$/);
6
+ export const evidenceLocationSchema = z.discriminatedUnion("type", [
7
+ z.strictObject({
8
+ type: z.literal("file"),
9
+ path: relativePathSchema,
10
+ line: z.number().int().positive().optional(),
11
+ column: z.number().int().positive().optional(),
12
+ endLine: z.number().int().positive().optional(),
13
+ endColumn: z.number().int().positive().optional()
14
+ }),
15
+ z.strictObject({
16
+ type: z.literal("document"),
17
+ documentId: z.string().min(1),
18
+ title: z.string().min(1).optional(),
19
+ section: z.string().min(1).optional(),
20
+ url: z.url().optional()
21
+ }),
22
+ z.strictObject({ type: z.literal("url"), url: z.url(), pointer: z.string().optional() }),
23
+ z.strictObject({
24
+ type: z.literal("design-node"),
25
+ fileKey: z.string().min(1),
26
+ nodeId: z.string().min(1).optional(),
27
+ variableKey: z.string().min(1).optional()
28
+ })
29
+ ]);
30
+ /** How a fact was obtained. `llm-assisted` evidence is never allowed in adapter IR. */
31
+ export const EXTRACTION_METHODS = [
32
+ "ast",
33
+ "compiler-api",
34
+ "metadata-parse",
35
+ "structured-parse",
36
+ "document-parse",
37
+ "llm-assisted",
38
+ "manual"
39
+ ];
40
+ export const extractionMethodSchema = z.enum(EXTRACTION_METHODS);
41
+ export const verificationStatusSchema = z.enum(["unverified", "verified", "contradicted"]);
42
+ export const evidenceSchema = z.strictObject({
43
+ id: evidenceIdSchema,
44
+ sourceId: sourceIdSchema,
45
+ /** Source-native reference, for example `src/Button.tsx#Button` or a zeroheight page slug. */
46
+ sourceRef: z.string().min(1),
47
+ location: evidenceLocationSchema,
48
+ method: extractionMethodSchema,
49
+ extractor: z.strictObject({ name: z.string().min(1), version: z.string().min(1) }),
50
+ /** Bounded excerpt of the original source text. */
51
+ original: z.string().max(2000).optional(),
52
+ confidence: confidenceSchema.optional(),
53
+ verificationStatus: verificationStatusSchema,
54
+ capturedAt: isoTimestampSchema
55
+ });
56
+ export const evidenceFileSchema = z.strictObject({
57
+ evidenceVersion: z.literal(EVIDENCE_VERSION),
58
+ /** Content hash of the contract these evidence entries belong to. */
59
+ contractContentHash: sha256HexSchema,
60
+ evidence: z.array(evidenceSchema)
61
+ });
62
+ /**
63
+ * Evidence ids are content-addressed over the immutable parts of an observation. Confidence,
64
+ * verification status and capture time are mutable and deliberately excluded.
65
+ */
66
+ export function computeEvidenceId(evidence) {
67
+ const digest = hashJson({
68
+ sourceId: evidence.sourceId,
69
+ sourceRef: evidence.sourceRef,
70
+ location: evidence.location,
71
+ method: evidence.method,
72
+ extractor: evidence.extractor,
73
+ original: evidence.original ?? null
74
+ });
75
+ return `ev_${digest.slice(0, 24)}`;
76
+ }
77
+ export function createEvidenceFile(contractContentHash, evidence) {
78
+ return {
79
+ evidenceVersion: EVIDENCE_VERSION,
80
+ contractContentHash,
81
+ evidence: [...evidence].sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))
82
+ };
83
+ }
84
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Resolves a dotted fact path inside an entity. A segment addresses an object member, or, when the
3
+ * current node is an array, the item whose `name` (or else `id`) equals the segment, or else the
4
+ * item at that numeric index.
5
+ */
6
+ export function resolveFactPath(entity, path) {
7
+ let node = entity;
8
+ for (const segment of path.split(".")) {
9
+ if (Array.isArray(node)) {
10
+ const item = node.find((candidate) => keyOf(candidate) === segment) ?? byIndex(node, segment);
11
+ if (item === undefined)
12
+ return { found: false };
13
+ node = item;
14
+ }
15
+ else if (isRecord(node) && Object.hasOwn(node, segment)) {
16
+ node = node[segment];
17
+ }
18
+ else {
19
+ return { found: false };
20
+ }
21
+ }
22
+ return node === undefined ? { found: false } : { found: true, value: node };
23
+ }
24
+ function keyOf(item) {
25
+ if (!isRecord(item))
26
+ return undefined;
27
+ if (typeof item.name === "string")
28
+ return item.name;
29
+ if (typeof item.id === "string")
30
+ return item.id;
31
+ return undefined;
32
+ }
33
+ function byIndex(items, segment) {
34
+ return /^\d+$/.test(segment) ? items[Number(segment)] : undefined;
35
+ }
36
+ function isRecord(value) {
37
+ return typeof value === "object" && value !== null && !Array.isArray(value);
38
+ }
39
+ //# sourceMappingURL=fact-path.js.map
@@ -0,0 +1,62 @@
1
+ import { hashJson } from "../shared/index.js";
2
+ import { z } from "zod";
3
+ import { evidenceIdSchema } from "./evidence.js";
4
+ import { confidenceSchema, isoTimestampSchema, sha256HexSchema } from "./primitives.js";
5
+ /**
6
+ * Epistemic status of a fact. Never collapsed into a confidence number:
7
+ * - discovered: parsed from an implementation artifact.
8
+ * - documented: stated by a person in documentation or a design tool.
9
+ * - inferred: derived by a named rule or model from other evidence.
10
+ * - approved: accepted by an authorized owner. Layers over `approval.priorStatus`, which is retained.
11
+ */
12
+ export const factStatusSchema = z.enum(["discovered", "documented", "inferred", "approved"]);
13
+ export const priorStatusSchema = z.enum(["discovered", "documented", "inferred"]);
14
+ export const approvalSchema = z.strictObject({
15
+ approvedBy: z.string().min(1),
16
+ approvedAt: isoTimestampSchema,
17
+ role: z.string().min(1).optional(),
18
+ reference: z.string().min(1).optional(),
19
+ /** Hash of (entity id, path, value) at approval time. A mismatch means the approval is stale. */
20
+ fingerprint: sha256HexSchema,
21
+ priorStatus: priorStatusSchema
22
+ });
23
+ export const derivationSchema = z.strictObject({
24
+ rule: z.string().min(1),
25
+ reasoning: z.string().min(1),
26
+ inputs: z.array(z.string().min(1)),
27
+ model: z.strictObject({ id: z.string().min(1), promptHash: sha256HexSchema }).optional()
28
+ });
29
+ export const factRecordSchema = z
30
+ .strictObject({
31
+ status: factStatusSchema,
32
+ evidenceIds: z.array(evidenceIdSchema),
33
+ confidence: confidenceSchema.optional(),
34
+ derivation: derivationSchema.optional(),
35
+ approval: approvalSchema.optional()
36
+ })
37
+ .superRefine((fact, ctx) => {
38
+ const issue = (message, path) => ctx.addIssue({ code: "custom", message, path });
39
+ if (fact.evidenceIds.length === 0)
40
+ issue("every fact needs at least one evidence id", ["evidenceIds"]);
41
+ if (fact.status === "approved") {
42
+ if (!fact.approval)
43
+ issue("approved facts require approval metadata", ["approval"]);
44
+ }
45
+ else if (fact.approval) {
46
+ issue("approval metadata is only valid when status is 'approved'", ["approval"]);
47
+ }
48
+ if (fact.status === "inferred") {
49
+ if (!fact.derivation)
50
+ issue("inferred facts require a derivation", ["derivation"]);
51
+ if (fact.confidence === undefined)
52
+ issue("inferred facts require a confidence", ["confidence"]);
53
+ }
54
+ else if (fact.derivation && fact.status !== "approved") {
55
+ issue("derivation is only valid on inferred or approved facts", ["derivation"]);
56
+ }
57
+ });
58
+ export const factsSchema = z.record(z.string(), factRecordSchema);
59
+ export function computeFactFingerprint(input) {
60
+ return hashJson(input);
61
+ }
62
+ //# sourceMappingURL=facts.js.map
@@ -0,0 +1,16 @@
1
+ export { effectiveParts } from "./archetype-checks.js";
2
+ export { componentSchema } from "./components.js";
3
+ export { conflictSchema } from "./conflicts.js";
4
+ export { CONTRACT_VERSION, contractSchema, SUPPORTED_CONTRACT_VERSIONS } from "./contract.js";
5
+ export { computeEvidenceId, createEvidenceFile, EVIDENCE_VERSION, EXTRACTION_METHODS, evidenceFileSchema, evidenceIdSchema, evidenceLocationSchema, evidenceSchema, extractionMethodSchema } from "./evidence.js";
6
+ export { resolveFactPath } from "./fact-path.js";
7
+ export { approvalSchema, computeFactFingerprint, factRecordSchema, factStatusSchema } from "./facts.js";
8
+ export { computeContentHash, finalizeContract, serializeContract, serializeEvidenceFile } from "./integrity.js";
9
+ export { contractJsonSchemas } from "./json-schema.js";
10
+ export { constraintSchema, guidelineSchema, patternSchema, policySchema } from "./knowledge.js";
11
+ export { ACYCLIC_RELATIONSHIPS, behaviorSchema, compositionPartSchema, constraintDetailsSchemas, EVIDENCE_LEVELS, elementRefSchema, evidenceLevelSchema, INTERACTION_STATES, interactionWorkflowSchema, isPatternConstraintKind, layoutRegionSchema, PATTERN_CATEGORIES, PATTERN_CATEGORIES_1_1, PATTERN_CONSTRAINT_KINDS, PATTERN_ONLY_RELATIONSHIPS, PATTERN_RELATIONSHIP_TYPES, partNameSchema, patternAccessibilitySchema, patternRelationshipSchema, patternVariationSchema, regionRefSchema, verifiableBySchema } from "./patterns.js";
12
+ export { componentIdSchema, conflictIdSchema, ENTITY_KINDS, entityIdSchema, entityIdSchemaFor, FRAMEWORKS, factPathSchema, frameworkSchema, jsonValueSchema, relativePathSchema, SOURCE_TYPES, sourceIdSchema, sourceTypeSchema, themeIdSchema, tokenIdSchema } from "./primitives.js";
13
+ export { sourceSchema, sourceVersionSchema } from "./sources.js";
14
+ export { TOKEN_CATEGORIES, themeSchema, tokenSchema } from "./tokens.js";
15
+ export { parseContract, verifyContract } from "./validate.js";
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,21 @@
1
+ import { canonicalStringify, hashJson } from "../shared/index.js";
2
+ /**
3
+ * The content hash covers everything except the integrity block and volatile timestamps
4
+ * (`metadata.compiledAt`, `sources[].lastSyncedAt`), so recompiling unchanged inputs yields the same hash.
5
+ */
6
+ export function computeContentHash(contract) {
7
+ const { integrity: _integrity, ...body } = contract;
8
+ const { compiledAt: _compiledAt, ...metadata } = body.metadata;
9
+ const sources = body.sources.map(({ lastSyncedAt: _lastSyncedAt, ...source }) => source);
10
+ return hashJson({ ...body, metadata, sources });
11
+ }
12
+ export function finalizeContract(draft) {
13
+ return { ...draft, integrity: { algorithm: "sha256", contentHash: computeContentHash(draft) } };
14
+ }
15
+ export function serializeContract(contract) {
16
+ return `${canonicalStringify(contract, 2)}\n`;
17
+ }
18
+ export function serializeEvidenceFile(file) {
19
+ return `${canonicalStringify(file, 2)}\n`;
20
+ }
21
+ //# sourceMappingURL=integrity.js.map
@@ -0,0 +1,11 @@
1
+ import { z } from "zod";
2
+ import { contractSchema } from "./contract.js";
3
+ import { evidenceFileSchema } from "./evidence.js";
4
+ /** Serialized-contract JSON Schemas, derived from the Zod definitions (the single source of truth). */
5
+ export function contractJsonSchemas() {
6
+ return {
7
+ "contract-v1.schema.json": { title: "Invariant contract v1", ...z.toJSONSchema(contractSchema) },
8
+ "evidence-v1.schema.json": { title: "Invariant evidence file v1", ...z.toJSONSchema(evidenceFileSchema) }
9
+ };
10
+ }
11
+ //# sourceMappingURL=json-schema.js.map