@ggui-ai/ui-gen 0.14.0 → 0.16.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 (102) hide show
  1. package/dist/adapters/generation-dispatch.d.ts +21 -4
  2. package/dist/adapters/generation-dispatch.js +915 -351
  3. package/dist/adapters/generation-dispatch.js.map +1 -1
  4. package/dist/adapters/index.js +28 -23
  5. package/dist/adapters/index.js.map +1 -1
  6. package/dist/advanced/index.d.ts +17 -12
  7. package/dist/advanced/index.js +968 -375
  8. package/dist/advanced/index.js.map +1 -1
  9. package/dist/boilerplate.d.ts +16 -1
  10. package/dist/boilerplate.js +579 -245
  11. package/dist/boilerplate.js.map +1 -1
  12. package/dist/check/index.d.ts +17 -3
  13. package/dist/check/index.js +34 -26
  14. package/dist/check/index.js.map +1 -1
  15. package/dist/{create-ui-generator-D6TKuv9V.d.ts → create-ui-generator-CCIeQaEe.d.ts} +77 -10
  16. package/dist/design-mode-BHEE7flj.d.ts +67 -0
  17. package/dist/{dispatch-BuZfTh9r.d.ts → dispatch-BA5dJcg-.d.ts} +4 -1
  18. package/dist/evaluation/axis-checks/index.d.ts +4 -3
  19. package/dist/evaluation/axis-checks/index.js +3 -1
  20. package/dist/evaluation/axis-checks/index.js.map +1 -1
  21. package/dist/evaluation/axis-checks/registry.d.ts +2 -1
  22. package/dist/evaluation/axis-checks/registry.js +1 -0
  23. package/dist/evaluation/axis-checks/registry.js.map +1 -1
  24. package/dist/evaluation/index.d.ts +143 -3
  25. package/dist/evaluation/index.js +3866 -92
  26. package/dist/evaluation/index.js.map +1 -1
  27. package/dist/{generate-BTfvELgl.d.ts → generate-8L_bc2iP.d.ts} +10 -1
  28. package/dist/harness/check/runtime-render/index.d.ts +2 -1
  29. package/dist/harness/index.d.ts +2 -1
  30. package/dist/harness/index.js +589 -248
  31. package/dist/harness/index.js.map +1 -1
  32. package/dist/harness/llm-trace-sink.d.ts +3 -3
  33. package/dist/harness/llm-trace-sink.js.map +1 -1
  34. package/dist/harness/prompts.d.ts +2 -1
  35. package/dist/harness/prompts.js +3 -0
  36. package/dist/harness/prompts.js.map +1 -1
  37. package/dist/harness/result-types.d.ts +17 -5
  38. package/dist/harness/result-types.js.map +1 -1
  39. package/dist/harness/runtime.d.ts +19 -3
  40. package/dist/harness/runtime.js +602 -261
  41. package/dist/harness/runtime.js.map +1 -1
  42. package/dist/harness/types-public.d.ts +28 -1
  43. package/dist/harness/types-public.js +589 -248
  44. package/dist/harness/types-public.js.map +1 -1
  45. package/dist/harness/validator-trace-sink.d.ts +2 -1
  46. package/dist/index.d.ts +8 -4
  47. package/dist/index.js +975 -373
  48. package/dist/index.js.map +1 -1
  49. package/dist/patch.d.ts +2 -1
  50. package/dist/{prompts-BVhtH3M1.d.ts → prompts-k6m6reqe.d.ts} +11 -1
  51. package/dist/providers/index.d.ts +2 -2
  52. package/dist/providers/index.js.map +1 -1
  53. package/dist/tools/get-primitives-ts.d.ts +1 -1
  54. package/dist/tools/get-primitives-ts.js +1 -1
  55. package/dist/tools/get-primitives-ts.js.map +1 -1
  56. package/dist/{types-public-CkNWEov9.d.ts → types-public-D24JLJgl.d.ts} +49 -5
  57. package/dist/validation/index.d.ts +1 -1
  58. package/dist/validation/index.js +4 -4
  59. package/dist/validation/index.js.map +1 -1
  60. package/dist/workflows.d.ts +2 -1
  61. package/package.json +12 -12
  62. package/src/adapters/generation-dispatch.ts +57 -4
  63. package/src/adapters/provider-router.ts +7 -6
  64. package/src/adapters/tools.ts +5 -5
  65. package/src/advanced/generator.ts +11 -10
  66. package/src/advanced/index.ts +5 -4
  67. package/src/boilerplate/free-design-prompt.ts +329 -0
  68. package/src/boilerplate/generate.ts +10 -1
  69. package/src/boilerplate/hard-sections.ts +242 -0
  70. package/src/boilerplate/render.ts +32 -8
  71. package/src/boilerplate/system-prompt.ts +81 -229
  72. package/src/boilerplate/templates/base-free.tsx.tmpl +24 -0
  73. package/src/check/run-tier0.ts +80 -20
  74. package/src/check/type-checker.ts +12 -2
  75. package/src/coding-agent/tools.ts +8 -2
  76. package/src/contract-context.ts +28 -0
  77. package/src/create-harness.ts +11 -0
  78. package/src/create-ui-generator.ts +71 -25
  79. package/src/design-mode.ts +182 -0
  80. package/src/design-system-docs.ts +17 -13
  81. package/src/evaluation/axis-checks/dispatch.ts +4 -0
  82. package/src/evaluation/axis-checks/extras.ts +5 -0
  83. package/src/evaluation/cost-tracker.ts +2 -3
  84. package/src/evaluation/index.ts +46 -2
  85. package/src/evaluation/llm-evaluator.ts +77 -21
  86. package/src/evaluation/types-public.ts +103 -8
  87. package/src/evaluation/visual-evaluator.ts +301 -29
  88. package/src/harness/coding/dupe-break.ts +0 -0
  89. package/src/harness/coding/init-session.ts +1 -0
  90. package/src/harness/coding/run-coding-turn.ts +3 -0
  91. package/src/harness/coding/run-eval-round.ts +15 -2
  92. package/src/harness/llm-trace-sink.ts +3 -3
  93. package/src/harness/result-types.ts +15 -3
  94. package/src/harness/runtime.ts +18 -0
  95. package/src/harness/types-public.ts +27 -0
  96. package/src/index.ts +26 -0
  97. package/src/internal/extract-call-signatures.ts +2 -2
  98. package/src/providers/bedrock.ts +4 -4
  99. package/src/run-check.ts +1 -0
  100. package/src/tools/get-primitives-ts.ts +1 -1
  101. package/src/validation/allowed-imports.ts +8 -2
  102. package/src/validation/primitives.ts +1 -1
@@ -1,5 +1,6 @@
1
1
  import { DataContract, JsonObject, PropsSpec, ActionSpec, StreamSpec } from '@ggui-ai/protocol';
2
- import { b as EvalResult, E as EvalIssue } from '../types-public-CkNWEov9.js';
2
+ import { D as DesignMode } from '../design-mode-BHEE7flj.js';
3
+ import { b as EvalResult, E as EvalIssue } from '../types-public-D24JLJgl.js';
3
4
  export { j as jsonSchemaTypeToTs } from '../json-schema-ts-CbB78b3n.js';
4
5
  import '../axes-CzLEMDeB.js';
5
6
  import '../types-BOvHNG7K.js';
@@ -223,10 +224,23 @@ declare function runTier0Checks(sourceCode: string, contract?: DataContract, bui
223
224
  * resolves against the real declaration (strict option/return
224
225
  * narrowing). Standard-library-only callers omit it.
225
226
  */
226
- gadgetTypes?: Readonly<Record<string, string>>): Promise<EvalIssue[]>;
227
+ gadgetTypes?: Readonly<Record<string, string>>,
228
+ /**
229
+ * Which triad produced the source. `constrained` (default) runs every
230
+ * leg exactly as before. `free` gates OFF the design-VOCABULARY legs —
231
+ * `raw-spacing`, `raw-pixels`, `numeric-spacing-prop`, the
232
+ * `stack-row-*` prop checks and `clickable-wrapper` — because raw
233
+ * elements, inline CSS and literal spacing are first-class there. It
234
+ * KEEPS every contract leg: `hex-color`, `hardcoded-color-fn`,
235
+ * `named-color`, `token-fallback`, `off-manifest-token`,
236
+ * `asset-color-pair` (color stays on the closed token manifest),
237
+ * imports, security, Props / default-export, wire_* and gadget checks,
238
+ * and the double-wired-action detector (retargeted at raw elements).
239
+ */
240
+ designMode?: DesignMode): Promise<EvalIssue[]>;
227
241
  /**
228
242
  * Run tier 0 checks and return a full EvalResult with pass list.
229
243
  */
230
- declare function runTier0(sourceCode: string, contract?: DataContract): Promise<EvalResult>;
244
+ declare function runTier0(sourceCode: string, contract?: DataContract, designMode?: DesignMode): Promise<EvalResult>;
231
245
 
232
246
  export { type ContractIssue, type ReactLintDiagnostic, type TypeCheckDiagnostic, type TypeCheckResult, type WireCallSite, type WireImportReport, type WireImportSite, type WireKind, type WirePreservationReport, checkWireImports, checkWirePreservation, collectExpectedWires, extractPropsInterface, extractWireCallSites, extractWireImports, inferPropsSpecFromSampleData, lintReactHooks, propsSpecToTypeScript, runTier0, runTier0Checks, typecheck, validateActionSpecConformance, validateAllContracts, validatePropsAgainstSchema, validateStreamSpecConformance };
@@ -2,6 +2,7 @@ import ts4 from 'typescript';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
4
  import { createRequire } from 'module';
5
+ import { FORBIDDEN_IMPORT_SPECIFIERS } from '@ggui-ai/design/rendering';
5
6
  import { Linter } from 'eslint';
6
7
  import { listContractGadgets, HOOK_NAME_RE } from '@ggui-ai/protocol';
7
8
  import { consumedTokenManifest } from '@ggui-ai/design/themes';
@@ -395,8 +396,6 @@ function inferJsonSchema(value) {
395
396
  }
396
397
  return { type: "string" };
397
398
  }
398
-
399
- // src/validation/allowed-imports.ts
400
399
  var ALLOWED_IMPORT_BASES = [
401
400
  "react",
402
401
  "react-dom",
@@ -405,13 +404,14 @@ var ALLOWED_IMPORT_BASES = [
405
404
  "@ggui-ai/gadgets"
406
405
  ];
407
406
  function isAllowedImport(specifier, gadgetPackages) {
407
+ if (FORBIDDEN_IMPORT_SPECIFIERS.includes(specifier)) return false;
408
408
  for (const base of ALLOWED_IMPORT_BASES) {
409
409
  if (specifier === base || specifier.startsWith(`${base}/`)) return true;
410
410
  }
411
411
  return gadgetPackages?.has(specifier) ?? false;
412
412
  }
413
413
  function describeAllowedImports() {
414
- return "react, @ggui-ai/design, @ggui-ai/wire, @ggui-ai/gadgets, or a gadget package declared on the contract";
414
+ return "react, @ggui-ai/design, @ggui-ai/wire, @ggui-ai/gadgets, or a gadget package declared on the contract \u2014 never @ggui-ai/wire/internal (the writer side of the wire; components read useRender().isConnected)";
415
415
  }
416
416
 
417
417
  // src/check/type-checker.ts
@@ -565,7 +565,8 @@ async function loadVfs() {
565
565
  function resolveRelativeInVfs(vfs, containingFile, importPath) {
566
566
  const normalized = containingFile.startsWith("/") ? containingFile.slice(1) : containingFile;
567
567
  const dir = path.posix.dirname(normalized);
568
- const resolved2 = path.posix.normalize(`${dir}/${importPath}`);
568
+ const specifier = importPath.replace(/\.(?:m|c)?js$/, "");
569
+ const resolved2 = path.posix.normalize(`${dir}/${specifier}`);
569
570
  const withDts = `${resolved2}.d.ts`;
570
571
  if (vfs.has(withDts)) return withDts;
571
572
  const withIndexDts = `${resolved2}/index.d.ts`;
@@ -876,6 +877,9 @@ function generateReactFix(ruleId, message) {
876
877
  return "Fix the React violation.";
877
878
  }
878
879
 
880
+ // src/design-mode.ts
881
+ var DEFAULT_DESIGN_MODE = "constrained";
882
+
879
883
  // src/evaluation/types-public.ts
880
884
  function priorityForIssue(category) {
881
885
  if (category === "interactivity" || category === "accessibility" || category === "layout" || category === "loading" || category === "visual") {
@@ -903,10 +907,11 @@ function stripComments(code) {
903
907
  }
904
908
  return out;
905
909
  }
906
- function detectCertainDoubleWiredActions(sourceCode, actionBindings) {
910
+ function detectCertainDoubleWiredActions(sourceCode, actionBindings, designMode = DEFAULT_DESIGN_MODE) {
907
911
  const issues = [];
908
912
  if (actionBindings.length === 0) return issues;
909
913
  const bindings = new Set(actionBindings);
914
+ const anyElementIsInteractive = designMode === "free";
910
915
  const TRAIT_HOST_TAGS = /* @__PURE__ */ new Set(["Card", "Box", "Stack", "Row"]);
911
916
  const TRAITS_THAT_FIRE = /* @__PURE__ */ new Set(["Clickable", "Pressable"]);
912
917
  const INTERACTIVE_DESCENDANTS = /* @__PURE__ */ new Set([
@@ -942,7 +947,9 @@ function detectCertainDoubleWiredActions(sourceCode, actionBindings) {
942
947
  }
943
948
  function isTraitHostWithFiringAs(node) {
944
949
  const tag = tagNameText(node);
945
- if (tag === void 0 || !TRAIT_HOST_TAGS.has(tag)) return false;
950
+ if (tag === void 0) return false;
951
+ if (anyElementIsInteractive) return true;
952
+ if (!TRAIT_HOST_TAGS.has(tag)) return false;
946
953
  const asExpr = attrExpression(node, "as");
947
954
  return asExpr !== void 0 && ts4.isIdentifier(asExpr) && TRAITS_THAT_FIRE.has(asExpr.text);
948
955
  }
@@ -971,7 +978,7 @@ function detectCertainDoubleWiredActions(sourceCode, actionBindings) {
971
978
  const opening = ts4.isJsxElement(node) ? node.openingElement : ts4.isJsxSelfClosingElement(node) ? node : void 0;
972
979
  if (opening !== void 0) {
973
980
  const tag = tagNameText(opening);
974
- if (tag !== void 0 && INTERACTIVE_DESCENDANTS.has(tag)) {
981
+ if (tag !== void 0 && (anyElementIsInteractive || INTERACTIVE_DESCENDANTS.has(tag))) {
975
982
  for (const attrName of HANDLER_ATTRS) {
976
983
  const callee = extractCalleeName(attrExpression(opening, attrName));
977
984
  if (callee === expectedBinding) {
@@ -997,14 +1004,15 @@ function detectCertainDoubleWiredActions(sourceCode, actionBindings) {
997
1004
  if (match !== void 0) {
998
1005
  const outerTag = tagNameText(node.openingElement);
999
1006
  const outerLine = sf.getLineAndCharacterOfPosition(node.openingElement.getStart()).line + 1;
1007
+ const outerLabel = anyElementIsInteractive ? `<${outerTag}>` : `<${outerTag} as={...}>`;
1000
1008
  issues.push({
1001
1009
  tier: 0,
1002
1010
  result: "fail",
1003
1011
  category: "interactivity",
1004
1012
  subcategory: "double-wired-action:certain",
1005
1013
  severity: "critical",
1006
- description: `Nested-interactive double-wire: outer <${outerTag} as={...}> at line ${outerLine} and inner <${match.tag}> at line ${match.line} both dispatch the same useAction binding '${outerCallee}'. One user click on the inner control fires its handler AND bubbles to the outer handler \u2014 '${outerCallee}' dispatches TWICE, the action runs back-to-back, and a toggle-style action silently reverts the user's change.`,
1007
- fix: `Pick ONE surface for the gesture: either drop \`as={...}\` + onClick on the outer <${outerTag}> and let the inner <${match.tag}> own the gesture, OR remove the inner <${match.tag}> and let the outer <${outerTag} as={...}> own it. Don't wire both to the same useAction binding.`,
1014
+ description: `Nested-interactive double-wire: outer ${outerLabel} at line ${outerLine} and inner <${match.tag}> at line ${match.line} both dispatch the same useAction binding '${outerCallee}'. One user click on the inner control fires its handler AND bubbles to the outer handler \u2014 '${outerCallee}' dispatches TWICE, the action runs back-to-back, and a toggle-style action silently reverts the user's change.`,
1015
+ fix: anyElementIsInteractive ? `Pick ONE gesture surface for '${outerCallee}': either remove the onClick from the outer <${outerTag}> and let the inner <${match.tag}> own the gesture, OR drop the inner <${match.tag}>'s handler and let the outer <${outerTag}> own it. Never wire both to the same useAction binding \u2014 stopPropagation is not a fix.` : `Pick ONE surface for the gesture: either drop \`as={...}\` + onClick on the outer <${outerTag}> and let the inner <${match.tag}> own the gesture, OR remove the inner <${match.tag}> and let the outer <${outerTag} as={...}> own it. Don't wire both to the same useAction binding.`,
1008
1016
  line: outerLine
1009
1017
  });
1010
1018
  }
@@ -1041,9 +1049,10 @@ function isGadgetExportImported(source, pkg, exportName) {
1041
1049
  }
1042
1050
  return false;
1043
1051
  }
1044
- async function runTier0Checks(sourceCode, contract, buildErrors, gadgetTypes) {
1052
+ async function runTier0Checks(sourceCode, contract, buildErrors, gadgetTypes, designMode = DEFAULT_DESIGN_MODE) {
1045
1053
  const issues = [];
1046
1054
  const lines = sourceCode.split("\n");
1055
+ const enforceDesignVocabulary = designMode === "constrained";
1047
1056
  if (buildErrors && buildErrors.length > 0) {
1048
1057
  const errorDetail = buildErrors.map((e) => {
1049
1058
  const match = e.match(/<stdin>:(\d+):\d+: ERROR: (.+)/);
@@ -1172,7 +1181,7 @@ ${errorDetail}`,
1172
1181
  subcategory: "hardcoded-color-fn",
1173
1182
  severity: "critical",
1174
1183
  description: `Hardcoded ${colorFnMatch[1]}() breaks theme switching \u2014 use design tokens.`,
1175
- fix: "Replace with a primitive variant OR a semantic token: var(--ggui-color-surface), var(--ggui-color-onSurface), var(--ggui-color-outline), etc.",
1184
+ fix: "Replace with a primitive variant OR a layering role: var(--ggui-color-container), var(--ggui-color-onContainer), var(--ggui-color-outline), etc.",
1176
1185
  line: lineNum
1177
1186
  });
1178
1187
  }
@@ -1189,13 +1198,13 @@ ${errorDetail}`,
1189
1198
  subcategory: "off-manifest-token",
1190
1199
  severity: "critical",
1191
1200
  description: `Token "${name}" is not in the design system's token manifest \u2014 no theme defines it, so it renders unset.`,
1192
- fix: `Choose a token that exists: the closed vocabulary is the manifest the design-system docs list (colors: var(--ggui-color-primary-500), var(--ggui-color-onSurface), \u2026; spacing: var(--ggui-spacing-4); type: var(--ggui-font-size-sm)). Never invent a name and never add a literal fallback.`,
1201
+ fix: `Choose a token that exists: the closed vocabulary is the manifest the design-system docs list (colors: var(--ggui-color-primary-500), var(--ggui-color-onContainer), \u2026; spacing: var(--ggui-spacing-4); type: var(--ggui-font-size-sm)). Never invent a name and never add a literal fallback.`,
1193
1202
  line: lineNum
1194
1203
  });
1195
1204
  }
1196
- const rawSpacingMatch = line.match(
1205
+ const rawSpacingMatch = enforceDesignVocabulary ? line.match(
1197
1206
  /\b(gap|padding|paddingX|paddingY|margin|radius)\s*=\s*["'][\d.]+(?:px|rem|em)["']/
1198
- );
1207
+ ) : null;
1199
1208
  if (rawSpacingMatch) {
1200
1209
  issues.push({
1201
1210
  tier: 0,
@@ -1289,12 +1298,12 @@ ${errorDetail}`,
1289
1298
  subcategory: "named-color",
1290
1299
  severity: "critical",
1291
1300
  description: `Hardcoded CSS named color "${named}" breaks theme switching \u2014 use design tokens.`,
1292
- fix: `Replace with a typed slot (Text tone="muted" / Box surface="accent" / Badge variant="success") OR a semantic token: var(--ggui-color-onSurfaceVariant), var(--ggui-color-primary-500), etc. The keyword "${named}" maps to a fixed RGB; the operator's theme has no effect on it.`,
1301
+ fix: `Replace with a typed slot (Text tone="muted" / Box surface="accent" / Badge variant="success") OR a semantic token: var(--ggui-color-onSunken), var(--ggui-color-primary-500), etc. The keyword "${named}" maps to a fixed RGB; the operator's theme has no effect on it.`,
1293
1302
  line: lineNum
1294
1303
  });
1295
1304
  }
1296
1305
  }
1297
- const pxMatch = line.match(/(?:padding|margin|gap|borderRadius)\s*:\s*['"]?\d+px/);
1306
+ const pxMatch = enforceDesignVocabulary ? line.match(/(?:padding|margin|gap|borderRadius)\s*:\s*['"]?\d+px/) : null;
1298
1307
  if (pxMatch && !line.includes("var(--ggui-")) {
1299
1308
  issues.push({
1300
1309
  tier: 0,
@@ -1302,11 +1311,11 @@ ${errorDetail}`,
1302
1311
  category: "tokens",
1303
1312
  subcategory: "raw-pixels",
1304
1313
  description: "Raw pixel value in spacing \u2014 must use design tokens",
1305
- fix: "Replace with var(--ggui-spacing-*, fallback)",
1314
+ fix: 'Replace with a bare var(--ggui-spacing-*) token \u2014 no literal fallback (the runtime injects every token) \u2014 or the scale name on the primitive prop (gap="md", padding="lg")',
1306
1315
  line: lineNum
1307
1316
  });
1308
1317
  }
1309
- const numericSpacingMatch = line.match(/\b(padding|paddingX|paddingY|gap|margin)\s*=\s*\{?\s*(\d+)\s*\}?/);
1318
+ const numericSpacingMatch = enforceDesignVocabulary ? line.match(/\b(padding|paddingX|paddingY|gap|margin)\s*=\s*\{?\s*(\d+)\s*\}?/) : null;
1310
1319
  if (numericSpacingMatch && !line.includes("var(--ggui-")) {
1311
1320
  issues.push({
1312
1321
  tier: 0,
@@ -1320,7 +1329,7 @@ ${errorDetail}`,
1320
1329
  }
1321
1330
  }
1322
1331
  const clickablePattern = /<(?:Card|Box|Stack|Row)\s[^>]*onClick/;
1323
- for (let i = 0; i < lines.length; i++) {
1332
+ for (let i = 0; enforceDesignVocabulary && i < lines.length; i++) {
1324
1333
  if (clickablePattern.test(lines[i]) && !lines[i].includes("as={Clickable}") && !lines[i].includes("as={Pressable}")) {
1325
1334
  issues.push({
1326
1335
  tier: 0,
@@ -1333,9 +1342,8 @@ ${errorDetail}`,
1333
1342
  });
1334
1343
  }
1335
1344
  }
1336
- const actionBindings = [
1337
- ...sourceCode.matchAll(/(?:const|let)\s+(\w+)\s*=\s*useAction\s*\(/g)
1338
- ].map((m) => m[1]).filter((name) => typeof name === "string");
1345
+ const bindingRe = designMode === "free" ? /(?:const|let)\s+(\w+)\s*=\s*useAction\s*(?:<[^>]*>)?\s*\(/g : /(?:const|let)\s+(\w+)\s*=\s*useAction\s*\(/g;
1346
+ const actionBindings = [...sourceCode.matchAll(bindingRe)].map((m) => m[1]).filter((name) => typeof name === "string");
1339
1347
  for (const binding of actionBindings) {
1340
1348
  const callSites = (sourceCode.match(new RegExp(`\\b${binding}\\s*\\(`, "g")) ?? []).length;
1341
1349
  if (callSites >= 2) {
@@ -1351,7 +1359,7 @@ ${errorDetail}`,
1351
1359
  }
1352
1360
  if (actionBindings.length > 0) {
1353
1361
  issues.push(
1354
- ...detectCertainDoubleWiredActions(sourceCode, actionBindings)
1362
+ ...detectCertainDoubleWiredActions(sourceCode, actionBindings, designMode)
1355
1363
  );
1356
1364
  }
1357
1365
  if (/\buseRender\s*\(/.test(sourceCode)) {
@@ -1396,7 +1404,7 @@ ${errorDetail}`,
1396
1404
  const ALIGN_VALUES = /* @__PURE__ */ new Set(["start", "center", "end", "stretch"]);
1397
1405
  const JUSTIFY_VALUES = /* @__PURE__ */ new Set(["start", "center", "end", "between", "around", "evenly"]);
1398
1406
  const tagRegex = /<(Stack|Row)\b([^>]*)>/gs;
1399
- for (const tag of sourceCode.matchAll(tagRegex)) {
1407
+ for (const tag of enforceDesignVocabulary ? sourceCode.matchAll(tagRegex) : []) {
1400
1408
  const tagName = tag[1];
1401
1409
  const attrs = tag[2];
1402
1410
  const tagLine = sourceCode.slice(0, tag.index).split("\n").length;
@@ -1682,8 +1690,8 @@ Import \`${exportName}\` ONLY from '${use.package}' \u2014 that is the package i
1682
1690
  }
1683
1691
  return issues;
1684
1692
  }
1685
- async function runTier0(sourceCode, contract) {
1686
- const issues = await runTier0Checks(sourceCode, contract);
1693
+ async function runTier0(sourceCode, contract, designMode = DEFAULT_DESIGN_MODE) {
1694
+ const issues = await runTier0Checks(sourceCode, contract, void 0, void 0, designMode);
1687
1695
  const pass = [];
1688
1696
  const failedCategories = new Set(issues.map((i) => i.category));
1689
1697
  const tier0Categories = ["compile", "security", "contract", "types", "imports", "tokens"];