@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,196 @@
1
+ import { normalize } from "../contract-query/index.js";
2
+ import { nearest, quoteList } from "./text.js";
3
+ export const isDynamic = (v) => typeof v === "object" &&
4
+ v !== null &&
5
+ !Array.isArray(v) &&
6
+ Object.keys(v).length === 1 &&
7
+ typeof v.expression === "string";
8
+ /**
9
+ * Attributes frameworks pass through to the rendered element. A component rarely declares them, and whether it
10
+ * forwards them is not in the contract, so an undeclared one is not evidence of a mistake.
11
+ */
12
+ const HTML_ATTRIBUTES = new Set("accept alt autocomplete autofocus checked cols colspan disabled download draggable for form height href hreflang htmlfor inputmode lang list loading max maxlength method min minlength multiple name novalidate pattern placeholder readonly rel required rows rowspan selected size spellcheck src srcset step target type value width wrap dir content crossorigin enterkeyhint open".split(" "));
13
+ const PASSTHROUGH = /^(data-|aria-)|^(key|ref|class|className|style|id|slot|role|tabindex|title|hidden)$/i;
14
+ const isPassthrough = (name) => PASSTHROUGH.test(name) || HTML_ATTRIBUTES.has(name.toLowerCase());
15
+ function sameValue(allowed, v) {
16
+ if (allowed === v)
17
+ return true;
18
+ return typeof v === "string" && typeof allowed !== "string" && String(allowed) === v;
19
+ }
20
+ export function validateUsage(ds, input) {
21
+ const findings = [];
22
+ const found = ds.findComponent(input.component);
23
+ if (!found.match) {
24
+ const names = found.candidates.map((c) => c.name);
25
+ const close = names.length > 0
26
+ ? names
27
+ : nearest(input.component, ds.contract.components.map((c) => c.name));
28
+ findings.push({
29
+ code: found.candidates.length > 1 && names.some((n) => normalize(n) === normalize(input.component))
30
+ ? "component-ambiguous"
31
+ : "component-unknown",
32
+ severity: "error",
33
+ message: `"${input.component}" is not a component in the contract${close.length > 0 ? `. Candidates: ${close.join(", ")}` : ""}`,
34
+ basis: "discovered",
35
+ ...(close.length > 0
36
+ ? { suggestion: `Did you mean ${close.slice(0, 3).join(" or ")}?` }
37
+ : {
38
+ suggestion: "Find a component with search_design_system or `invariant components list`, or add the component to the design system."
39
+ })
40
+ });
41
+ return { findings, unverifiedValues: 0 };
42
+ }
43
+ const c = found.match;
44
+ const framework = input.framework;
45
+ if (framework && !c.implementations.some((i) => i.framework === framework))
46
+ findings.push({
47
+ code: "framework-not-implemented",
48
+ severity: "error",
49
+ subject: c.id,
50
+ message: `${c.name} has no ${framework} implementation (it has: ${c.implementations.map((i) => i.framework).join(", ")})`,
51
+ basis: "discovered",
52
+ suggestion: `Use the ${c.implementations.map((i) => i.framework).join(" or ")} implementation, or a ${framework} component with the same role.`
53
+ });
54
+ if (c.lifecycle === "deprecated") {
55
+ const replacement = c.deprecated?.replacedBy ? ds.component(c.deprecated.replacedBy)?.name : undefined;
56
+ findings.push({
57
+ code: "component-deprecated",
58
+ severity: "warning",
59
+ subject: c.id,
60
+ message: `${c.name} is deprecated${c.deprecated?.reason ? `: ${c.deprecated.reason}` : ""}`,
61
+ basis: ds.factView(c.facts, "lifecycle")?.status === "documented" ? "documented" : "discovered",
62
+ ...(ds.factView(c.facts, "lifecycle")?.source
63
+ ? { source: ds.factView(c.facts, "lifecycle")?.source }
64
+ : {}),
65
+ suggestion: replacement
66
+ ? `Use ${replacement}.`
67
+ : "Migrate to the component that replaces it; check the component's documentation."
68
+ });
69
+ }
70
+ const complete = ds.propsComplete(c, framework);
71
+ const props = input.props ?? {};
72
+ let unverified = 0;
73
+ const basisOf = (path) => {
74
+ const s = ds.factView(c.facts, path)?.status;
75
+ return s === "documented" || s === "inferred" || s === "approved" ? s : "discovered";
76
+ };
77
+ const where = (path) => {
78
+ const s = ds.factView(c.facts, path)?.source;
79
+ return s ? { source: s } : {};
80
+ };
81
+ const eventNames = new Set(c.events.map((e) => normalize(e.name)));
82
+ const slotNames = new Set(c.slots.map((s) => normalize(s.name)));
83
+ for (const [name, value] of Object.entries(props)) {
84
+ const prop = c.props.find((p) => p.name === name);
85
+ if (!prop) {
86
+ if (isPassthrough(name) ||
87
+ eventNames.has(normalize(name.replace(/^on(?=[A-Z])/, ""))) ||
88
+ slotNames.has(normalize(name)))
89
+ continue;
90
+ const close = nearest(name, c.props.map((p) => p.name));
91
+ findings.push(complete
92
+ ? {
93
+ code: "unknown-prop",
94
+ severity: "warning",
95
+ subject: c.id,
96
+ message: `${c.name} does not declare a prop "${name}"`,
97
+ path: `props.${name}`,
98
+ basis: "discovered",
99
+ suggestion: close.length > 0
100
+ ? `Did you mean ${close.map((x) => `"${x}"`).join(" or ")}?`
101
+ : `Remove "${name}", or check the props ${c.name} declares (get_component).`
102
+ }
103
+ : {
104
+ code: "unverifiable-prop",
105
+ severity: "info",
106
+ subject: c.id,
107
+ message: `${c.name}'s prop list is incomplete, so "${name}" could not be verified`,
108
+ path: `props.${name}`,
109
+ basis: "discovered"
110
+ });
111
+ continue;
112
+ }
113
+ const base = `props.${name}`;
114
+ if (prop.deprecated)
115
+ findings.push({
116
+ code: "prop-deprecated",
117
+ severity: "warning",
118
+ subject: c.id,
119
+ message: `${c.name}.${name} is deprecated${prop.deprecated.reason ? `: ${prop.deprecated.reason}` : ""}`,
120
+ path: base,
121
+ basis: basisOf(`${base}.deprecated`),
122
+ ...where(`${base}.deprecated`),
123
+ suggestion: prop.deprecated.reason
124
+ ? `Follow the deprecation note: ${prop.deprecated.reason}`
125
+ : `Stop using "${name}"; see ${c.name}'s documentation for its replacement.`
126
+ });
127
+ if (isDynamic(value)) {
128
+ unverified++;
129
+ continue;
130
+ }
131
+ if (prop.allowedValues &&
132
+ (typeof value === "string" || typeof value === "number" || typeof value === "boolean")) {
133
+ if (!prop.allowedValues.some((a) => sameValue(a, value))) {
134
+ const close = typeof value === "string" ? nearest(value, prop.allowedValues.map(String)) : [];
135
+ findings.push({
136
+ code: "prop-value-not-allowed",
137
+ severity: "error",
138
+ subject: c.id,
139
+ message: `${c.name}.${name} is ${JSON.stringify(value)}, which is not one of ${quoteList(prop.allowedValues)}`,
140
+ path: `${base}.allowedValues`,
141
+ basis: basisOf(`${base}.allowedValues`),
142
+ ...where(`${base}.allowedValues`),
143
+ suggestion: `Use one of ${quoteList(prop.allowedValues)}${close.length > 0 ? ` (closest: ${JSON.stringify(close[0])})` : ""}.`
144
+ });
145
+ }
146
+ }
147
+ else {
148
+ const kind = prop.type.kind;
149
+ const bad = (kind === "boolean" && typeof value !== "boolean") ||
150
+ (kind === "number" && typeof value !== "number") ||
151
+ (kind === "string" && typeof value !== "string");
152
+ if (bad)
153
+ findings.push({
154
+ code: "prop-type-mismatch",
155
+ severity: "warning",
156
+ subject: c.id,
157
+ message: `${c.name}.${name} expects ${kind} (${prop.type.text}) but got ${JSON.stringify(value)}`,
158
+ path: `${base}.type`,
159
+ basis: basisOf(`${base}.type.text`),
160
+ ...where(`${base}.type.text`),
161
+ suggestion: `Pass a ${kind} value${kind === "boolean" ? ` (for example ${name}={true})` : ""}.`
162
+ });
163
+ }
164
+ }
165
+ if (!input.hasSpread)
166
+ for (const p of c.props) {
167
+ if (!p.required || p.name in props)
168
+ continue;
169
+ if (p.name === "children") {
170
+ if (input.hasChildren === false)
171
+ findings.push({
172
+ code: "required-prop-missing",
173
+ severity: "error",
174
+ subject: c.id,
175
+ message: `${c.name} requires children`,
176
+ path: "props.children",
177
+ basis: basisOf("props.children.required"),
178
+ ...where("props.children.required"),
179
+ suggestion: `Put content inside ${c.name}.`
180
+ });
181
+ continue;
182
+ }
183
+ findings.push({
184
+ code: "required-prop-missing",
185
+ severity: "error",
186
+ subject: c.id,
187
+ message: `${c.name} requires the prop "${p.name}"`,
188
+ path: `props.${p.name}`,
189
+ basis: basisOf(`props.${p.name}.required`),
190
+ ...where(`props.${p.name}.required`),
191
+ suggestion: `Add ${p.name} (${p.type.text}${p.allowedValues ? `: ${quoteList(p.allowedValues)}` : ""}).`
192
+ });
193
+ }
194
+ return { component: c.id, findings, unverifiedValues: unverified };
195
+ }
196
+ //# sourceMappingURL=validate-usage.js.map
package/package.json CHANGED
@@ -1,6 +1,40 @@
1
1
  {
2
2
  "name": "@invariant-ui/cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "Compile your design system, UX patterns and page layouts into a contract AI agents can read, and check code against it.",
5
+ "keywords": [
6
+ "design-system",
7
+ "ai-agents",
8
+ "mcp",
9
+ "design-tokens",
10
+ "storybook",
11
+ "linting",
12
+ "ux-patterns"
13
+ ],
14
+ "license": "SEE LICENSE IN LICENSE",
15
+ "homepage": "https://invariant-ui.com/",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/invariant-ui/invariant.git"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/invariant-ui/invariant/issues"
22
+ },
23
+ "type": "module",
24
+ "bin": {
25
+ "invariant": "dist/cli/main.js"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "README.md",
30
+ "LICENSE"
31
+ ],
32
+ "engines": {
33
+ "node": ">=20"
34
+ },
35
+ "dependencies": {
36
+ "@vue/compiler-sfc": "3.5.44",
37
+ "typescript": "5.9.3",
38
+ "zod": "4.6.7"
39
+ }
40
+ }