@ggui-ai/ui-gen 0.26.0 → 0.28.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.
- package/dist/{adapter-BJwn74rx.d.ts → adapter-h4_V69LI.d.ts} +1 -1
- package/dist/adapters/base.d.ts +6 -1
- package/dist/adapters/base.js.map +1 -1
- package/dist/adapters/generation-dispatch.d.ts +2 -2
- package/dist/adapters/generation-dispatch.js +233 -17
- package/dist/adapters/generation-dispatch.js.map +1 -1
- package/dist/adapters/index.js +36 -14
- package/dist/adapters/index.js.map +1 -1
- package/dist/advanced/index.d.ts +4 -4
- package/dist/advanced/index.js +268 -28
- package/dist/advanced/index.js.map +1 -1
- package/dist/boilerplate.js +4 -6
- package/dist/boilerplate.js.map +1 -1
- package/dist/check/index.d.ts +1 -7
- package/dist/check/index.js +50 -4
- package/dist/check/index.js.map +1 -1
- package/dist/{create-ui-generator-N4gRXpcL.d.ts → create-ui-generator-BrZHF0cf.d.ts} +2 -2
- package/dist/{dispatch-BUoXRj_r.d.ts → dispatch-B07TI30d.d.ts} +1 -1
- package/dist/evaluation/axis-checks/index.d.ts +3 -3
- package/dist/evaluation/axis-checks/index.js +97 -1
- package/dist/evaluation/axis-checks/index.js.map +1 -1
- package/dist/evaluation/axis-checks/registry.d.ts +1 -1
- package/dist/evaluation/axis-checks/registry.js +97 -1
- package/dist/evaluation/axis-checks/registry.js.map +1 -1
- package/dist/evaluation/index.d.ts +22 -12
- package/dist/evaluation/index.js +138 -14
- package/dist/evaluation/index.js.map +1 -1
- package/dist/evaluation/types.d.ts +1 -1
- package/dist/harness/check/runtime-render/index.d.ts +3 -3
- package/dist/harness/index.d.ts +1 -1
- package/dist/harness/index.js +6 -6
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/prompts.js +1 -4
- package/dist/harness/prompts.js.map +1 -1
- package/dist/harness/result-types.d.ts +14 -3
- package/dist/harness/result-types.js.map +1 -1
- package/dist/harness/runtime.d.ts +1 -1
- package/dist/harness/runtime.js +6 -7
- package/dist/harness/runtime.js.map +1 -1
- package/dist/harness/types-public.d.ts +1 -1
- package/dist/harness/types-public.js +4 -6
- package/dist/harness/types-public.js.map +1 -1
- package/dist/harness/validator-trace-sink.d.ts +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +268 -28
- package/dist/index.js.map +1 -1
- package/dist/patch.d.ts +1 -1
- package/dist/{types-public-B7wn4ce5.d.ts → types-public-h8IMnYuh.d.ts} +4 -0
- package/dist/{visual-evaluator-C9L-o6ap.d.ts → visual-evaluator-C2strxqD.d.ts} +1 -1
- package/dist/workflows.d.ts +1 -1
- package/package.json +13 -13
- package/src/adapters/base.ts +6 -1
- package/src/adapters/claude/message-parser.ts +5 -6
- package/src/adapters/claude/sdk-tool-pins.ts +44 -0
- package/src/adapters/claude/sdk.ts +3 -3
- package/src/adapters/claude/source-capture.ts +20 -0
- package/src/adapters/provider-router.ts +1 -0
- package/src/boilerplate/system-prompt.ts +3 -2
- package/src/check/run-tier0.ts +61 -0
- package/src/create-ui-generator.ts +4 -2
- package/src/design-system-docs.ts +2 -1
- package/src/evaluation/axis-checks/checks/state-merge.ts +1 -1
- package/src/evaluation/axis-checks/helpers.ts +125 -0
- package/src/evaluation/criteria/resolve.ts +19 -1
- package/src/evaluation/evaluator.ts +2 -2
- package/src/evaluation/llm-evaluator.ts +2 -2
- package/src/evaluation/loop.ts +25 -4
- package/src/evaluation/message-parsing.ts +11 -12
- package/src/evaluation/types-public.ts +4 -0
- package/src/evaluation/visual-evaluator.ts +1 -1
- package/src/harness/coding/assemble-result.ts +1 -0
- package/src/harness/coding/dupe-break.ts +70 -0
- package/src/harness/coding/generate-task-runner.ts +5 -1
- package/src/harness/coding/run-coding-turn.ts +56 -1
- package/src/harness/result-types.ts +12 -0
- package/src/index.ts +1 -1
- package/src/taught-tokens.ts +5 -6
|
@@ -2,8 +2,8 @@ import { JsonObject, DataContract } from '@ggui-ai/protocol';
|
|
|
2
2
|
export { ActionSpec, DataContract, JsonSchema, PropsSpec, StreamSpec } from '@ggui-ai/protocol';
|
|
3
3
|
import { AdapterResult } from '../adapters/types.js';
|
|
4
4
|
import { R as RenderingContext } from '../prompts-BhNUuRoZ.js';
|
|
5
|
-
import { e as EvalResult } from '../types-public-
|
|
6
|
-
import { V as VisualLegTokens } from '../visual-evaluator-
|
|
5
|
+
import { e as EvalResult } from '../types-public-h8IMnYuh.js';
|
|
6
|
+
import { V as VisualLegTokens } from '../visual-evaluator-C2strxqD.js';
|
|
7
7
|
import { D as DesignMode, C as CanvasClass } from '../design-mode-DGWN_Gkm.js';
|
|
8
8
|
import 'zod';
|
|
9
9
|
import '../llm.js';
|
|
@@ -50,6 +50,15 @@ interface SameExchangeBreak {
|
|
|
50
50
|
readonly tool: string;
|
|
51
51
|
readonly repeats: number;
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* ggui#1791 — the same-failure guard ended the run: one failing check
|
|
55
|
+
* (`signature`, its first 160 characters) was reported by this many failed
|
|
56
|
+
* writes since the last passing one, whatever the patch.
|
|
57
|
+
*/
|
|
58
|
+
interface SameFailureBreak {
|
|
59
|
+
readonly signature: string;
|
|
60
|
+
readonly repeats: number;
|
|
61
|
+
}
|
|
53
62
|
interface GenerationResult extends AdapterResult {
|
|
54
63
|
/** Number of generation passes the harness performed */
|
|
55
64
|
passesUsed: number;
|
|
@@ -65,6 +74,8 @@ interface GenerationResult extends AdapterResult {
|
|
|
65
74
|
inLoopVisualTokens?: VisualLegTokens;
|
|
66
75
|
/** Set only when the same-exchange guard ended the run (ggui#404); no key otherwise. */
|
|
67
76
|
sameExchangeBreak?: SameExchangeBreak;
|
|
77
|
+
/** ggui#1791 — set only when the same-failure guard ended the run. */
|
|
78
|
+
sameFailureBreak?: SameFailureBreak;
|
|
68
79
|
/** Whether background improvement should be spawned (auto-improve mode) */
|
|
69
80
|
needsBackgroundImprovement?: boolean;
|
|
70
81
|
/** Whether at least one commit passed the self-check (compile + type check + lint) */
|
|
@@ -156,4 +167,4 @@ interface EvaluationConfig {
|
|
|
156
167
|
*/
|
|
157
168
|
declare function resolveModelForRole(role: ModelRole, models: ModelRoles | undefined, fallback: string): string;
|
|
158
169
|
|
|
159
|
-
export { type EvaluationConfig, type GenerationContext, type GenerationResult, type ModelRole, type ModelRoles, RenderingContext, type SameExchangeBreak, resolveModelForRole };
|
|
170
|
+
export { type EvaluationConfig, type GenerationContext, type GenerationResult, type ModelRole, type ModelRoles, RenderingContext, type SameExchangeBreak, type SameFailureBreak, resolveModelForRole };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/harness/result-types.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../../src/harness/result-types.ts"],"names":[],"mappings":";AAuMA,SAAS,iBAAiB,OAAA,EAAyB;AACjD,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA;AACtC,EAAA,OAAO,cAAc,CAAA,GAAI,OAAA,CAAQ,KAAA,CAAM,UAAA,GAAa,CAAC,CAAA,GAAI,OAAA;AAC3D;AAOO,SAAS,mBAAA,CACd,IAAA,EACA,MAAA,EACA,QAAA,EACQ;AACR,EAAA,IAAI,CAAC,QAAQ,OAAO,QAAA;AACpB,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,IAAI,CAAA,IAAK,OAAO,OAAA,IAAW,QAAA;AACnD,EAAA,OAAO,iBAAiB,QAAQ,CAAA;AAClC","file":"result-types.js","sourcesContent":["// packages/ui-gen/src/harness/result-types.ts\n//\n// Result shapes returned by the harness runtime.\n//\n// Two output types travel the dispatch surface:\n// - AdapterResult — raw adapter output (provider-direct path)\n// - GenerationResult — full harness output (run-loop, eval, breakdown)\n//\n// ModelRoles + resolveModelForRole live here too (the harness decides\n// which model to use per internal task).\n\nimport type { DataContract, JsonObject } from \"@ggui-ai/protocol\";\nimport type { AdapterResult } from \"../adapters/types.js\";\nimport type { RenderingContext } from \"../contract-context.js\";\nimport type { EvalResult } from \"../evaluation/types-public.js\";\nimport type { VisualLegTokens } from \"../evaluation/visual-evaluator.js\";\nimport type { CanvasClass, DesignMode } from \"../design-mode.js\";\n\n// =============================================================================\n// Model Roles\n// =============================================================================\n\n/**\n * Model role — each internal task in the harness can use a different model.\n *\n * - thinking: planning, design decisions, architecture (use frontier/thinking model)\n * - coding: writing TSX, implementing the design (use fast model)\n * - evaluation: scoring quality, finding issues (use balanced model)\n * - default: fallback for any role not explicitly set\n */\nexport type ModelRole = \"thinking\" | \"coding\" | \"evaluation\" | \"default\";\n\n/**\n * Maps model roles to model IDs.\n * Any role not specified falls back to 'default', then to params.model.\n *\n * @example\n * // Opus plans, Haiku codes, Sonnet evaluates\n * { thinking: 'claude-opus-4-6', coding: 'claude-haiku-4-5', default: 'claude-sonnet-4-6' }\n *\n * // All Haiku (cheapest)\n * { default: 'claude-haiku-4-5' }\n *\n * // All Opus (highest quality)\n * { default: 'claude-opus-4-6' }\n */\nexport type ModelRoles = Partial<Record<ModelRole, string>>;\n\n// =============================================================================\n// Generation Result\n// =============================================================================\n\n/**\n * The same-exchange guard (ggui#404) ended this generation: the coding model\n * made one identical tool exchange (same tool, same input, same result)\n * `repeats` times, so the loop stopped instead of burning its remaining turns.\n * Present ONLY when that guard ended the run — whether anything shipped is\n * the compiled code's to say (the loop falls back to an earlier build).\n */\nexport interface SameExchangeBreak {\n readonly tool: string;\n readonly repeats: number;\n}\n\n/**\n * ggui#1791 — the same-failure guard ended the run: one failing check\n * (`signature`, its first 160 characters) was reported by this many failed\n * writes since the last passing one, whatever the patch.\n */\nexport interface SameFailureBreak {\n readonly signature: string;\n readonly repeats: number;\n}\n\nexport interface GenerationResult extends AdapterResult {\n /** Number of generation passes the harness performed */\n passesUsed: number;\n /** Three-tier evaluation result (tier 0 + LLM tier 1+2 + visual) */\n evalResult?: EvalResult;\n /**\n * ggui#1522 — what the IN-LOOP visual judge spent during this generation (its scoring calls, and its report-only\n * criteria calls apart), priced at the visual agent's model. NOT inside `tokens`, which covers the coding turns\n * and the text evaluator. And NOT the same calls as a post-generation judge's own visual pass (a benchmark\n * report's `meta.costs.visualUsd`): a cost rule that adds both is correct, one read as the other double-counts.\n * Absent when no in-loop visual leg ran or it reported no tokens.\n */\n inLoopVisualTokens?: VisualLegTokens;\n /** Set only when the same-exchange guard ended the run (ggui#404); no key otherwise. */\n sameExchangeBreak?: SameExchangeBreak;\n /** ggui#1791 — set only when the same-failure guard ended the run. */\n sameFailureBreak?: SameFailureBreak;\n /** Whether background improvement should be spawned (auto-improve mode) */\n needsBackgroundImprovement?: boolean;\n /** Whether at least one commit passed the self-check (compile + type check + lint) */\n selfCheckPassed?: boolean;\n /** Which model was used for each role (for benchmark reporting) */\n modelRolesUsed?: Record<string, string>;\n /**\n * The triad this generation ran under — recorded ONLY when the caller\n * set `designMode` on the dispatch (a bench arm switch, an operator\n * option). Absent = the constrained default path, byte-identical to\n * the pre-`designMode` result.\n */\n designMode?: DesignMode;\n /**\n * The canvas class the `free` prompt stated — the explicit `canvas`\n * when the caller passed one, else the shell × screen derivation the\n * prompt itself used. Absent in constrained mode (that prompt states\n * no canvas) unless the caller passed one explicitly.\n */\n canvas?: CanvasClass;\n /** Phase-level timing breakdown (ms) */\n timing?: Record<string, number>;\n /** Per-turn/per-outcome breakdown for benchmark analysis.\n * Machine-parseable summary — phases counted by role, outcomes counted by rejection class. */\n breakdown?: {\n phases: { impl: number; patch: number; evalFix: number; scaffold?: number; fill?: number };\n outcomes: { pass: number; patchInvalid: number; selfCheckFail: number; diffFail: number };\n evalRounds: number;\n /** Coding-turn LLM wall-time (sum of per-turn llm=Xms). Stable semantics. */\n llmMs: number;\n /** Eval-round LLM wall-time (parallel LLM+visual). Added 2026-04-14. */\n evalLlmMs?: number;\n toolMs: number;\n /** Eval-round wall-clock (fix: was structurally 0 before 2026-04-14). */\n evalMs: number;\n /** Coding-only wall-time (inner loop minus eval). Added 2026-04-14. */\n codingMs?: number;\n /** Session setup+cleanup wall-time (outside inner loop). Added 2026-04-14. */\n setupMs?: number;\n };\n}\n\n// =============================================================================\n// Generation Context\n// =============================================================================\n\nexport interface GenerationContext {\n /** Progress callback */\n onProgress?: (event: unknown) => void;\n\n /** Called with initial result before evaluation loop (for early delivery) */\n onInitialResult?: (result: {\n componentCode: string;\n sourceCode?: string;\n }) => void | Promise<void>;\n\n /** Original user prompt (for evaluation context) */\n originalPrompt: string;\n\n /** Design context for evaluation */\n designContext?: string;\n\n /** Model roles — which model to use for each internal task */\n models?: ModelRoles;\n\n /** Rendering context — device and shell type affect layout strategy */\n rendering?: RenderingContext;\n\n /** Data contract — bind the component to its consumers */\n contract?: DataContract;\n\n /** Evaluation configuration */\n evaluation?: EvaluationConfig;\n}\n\n// Rendering context — canonical definition lives in\n// `../contract-context.ts` (one type, one prompt-builder family).\n// Re-exported here because this subpath is the harness's type hub.\nexport type { RenderingContext } from \"../contract-context.js\";\n\n// Data contract — re-exported from protocol (canonical types)\nexport type {\n ActionSpec,\n DataContract,\n JsonSchema,\n PropsSpec,\n StreamSpec,\n} from \"@ggui-ai/protocol\";\n\nexport interface EvaluationConfig {\n enabled: boolean;\n passThreshold: number;\n maxRounds?: number;\n model?: string;\n provider?: \"claude\" | \"openai\" | \"google\" | \"openrouter\";\n maxBudgetPerEval?: number;\n maxBudgetPerFix?: number;\n generatorOptions?: JsonObject;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/**\n * Strip provider prefix from LiteLLM-format model IDs.\n * 'anthropic/claude-sonnet-4-6' -> 'claude-sonnet-4-6'\n */\nfunction stripModelPrefix(modelId: string): string {\n const slashIndex = modelId.indexOf(\"/\");\n return slashIndex >= 0 ? modelId.slice(slashIndex + 1) : modelId;\n}\n\n/**\n * Resolve the model ID for a given role.\n * Priority: role-specific → default role → params.model\n * Strips provider prefix (e.g., 'anthropic/') so the result is a native API model ID.\n */\nexport function resolveModelForRole(\n role: ModelRole,\n models: ModelRoles | undefined,\n fallback: string\n): string {\n if (!models) return fallback;\n const resolved = models[role] ?? models.default ?? fallback;\n return stripModelPrefix(resolved);\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { G as GenerationProfileInput } from '../styling-profile-CxfvV48g.js';
|
|
2
|
-
import { Q as QualityConfig, b as AgentConfig } from '../types-public-
|
|
2
|
+
import { Q as QualityConfig, b as AgentConfig } from '../types-public-h8IMnYuh.js';
|
|
3
3
|
import { DataContract, JsonObject, GadgetDescriptor } from '@ggui-ai/protocol';
|
|
4
4
|
import { C as CriteriaBank } from '../bank-Ctdp3FUA.js';
|
|
5
5
|
import { C as CanvasClass, D as DesignMode } from '../design-mode-DGWN_Gkm.js';
|
package/dist/harness/runtime.js
CHANGED
|
@@ -45,6 +45,7 @@ These tokens adapt automatically to any theme (light, dark, branded). **ALWAYS u
|
|
|
45
45
|
| link | var(--ggui-color-link) | Accent TEXT \u2014 eyebrows, taglines, links, labels, inline arrows: the brand's readable ink, derived per mode to clear 4.5:1 on the container and the ground |
|
|
46
46
|
| outline | var(--ggui-color-outline) | Borders, dividers |
|
|
47
47
|
| outlineVariant | var(--ggui-color-outlineVariant) | Subtle borders |
|
|
48
|
+
| controlOutline | var(--ggui-color-controlOutline) | A control's edge \u2014 clears 3:1 on its surface; kit controls draw it themselves |
|
|
48
49
|
|
|
49
50
|
**Usage pattern:**
|
|
50
51
|
- Page/section background \u2192 \`var(--ggui-color-ground)\`
|
|
@@ -169,7 +170,7 @@ Use \`var(--ggui-spacing-N)\` for all padding, gap, and margin values. **Never u
|
|
|
169
170
|
### Color usage guide
|
|
170
171
|
- **Layering roles** (ground, container, elevated, sunken + their on* inks; outline): one kind of AREA each \u2014 use them for every background/text/border decision; they adapt to any theme
|
|
171
172
|
- **primary-50/100**: Section backgrounds, highlight strips, card headers
|
|
172
|
-
- **primary-200/300**:
|
|
173
|
+
- **primary-200/300**: Dividers and section rules \u2014 never a control's border: kit controls draw their own edge (\`controlOutline\` / \`controlAccentOutline\`), so set no inline border on them
|
|
173
174
|
- **primary-500/600**: Filled buttons, CTAs, badges, icon fills, active indicators \u2014 fills and borders, NOT a text color
|
|
174
175
|
- **link**: Accent TEXT \u2014 eyebrows, taglines, links, labels, inline arrows; the brand's readable ink per mode (a bare \`primary-300\u2026600\` as a text color fails tier-0: \`universal.accent_text_ink\`)
|
|
175
176
|
- **primary-700/800/900**: Headings and text on light primary backgrounds
|
|
@@ -1217,10 +1218,7 @@ function buildCodingCriteriaSummary(designMode = "constrained") {
|
|
|
1217
1218
|
}
|
|
1218
1219
|
return lines.join("\n");
|
|
1219
1220
|
}
|
|
1220
|
-
var NOT_YET_TAUGHT_TOKENS = /* @__PURE__ */ new Set([
|
|
1221
|
-
"--ggui-color-controlAccentOutline",
|
|
1222
|
-
"--ggui-color-controlOutline"
|
|
1223
|
-
]);
|
|
1221
|
+
var NOT_YET_TAUGHT_TOKENS = /* @__PURE__ */ new Set([]);
|
|
1224
1222
|
var taughtTokenManifest = consumedTokenManifest.filter(
|
|
1225
1223
|
(token) => !NOT_YET_TAUGHT_TOKENS.has(token)
|
|
1226
1224
|
);
|
|
@@ -2132,13 +2130,14 @@ MANDATORY:
|
|
|
2132
2130
|
2. NEVER use CSS gradients with custom colors. If you need a gradient: \`linear-gradient(to bottom, var(--ggui-color-primary-500), var(--ggui-color-primary-700))\`.
|
|
2133
2131
|
3. NEVER invent your own palette. The system provides primary, neutral, success, warning, error, and info \u2014 use ONLY these.
|
|
2134
2132
|
4. NEVER include literal fallback values in ANY token reference \u2014 colors, spacing, typography, radius, shadows alike. Write \`var(--ggui-spacing-4)\` bare, never \`var(--ggui-spacing-4, 16px)\`; \`var(--ggui-color-primary-600)\` bare, never \`var(--ggui-color-primary-600, #0284c7)\`. The runtime injects every token; a literal fallback paints the wrong value exactly when the operator's theme matters most.
|
|
2133
|
+
5. NEVER set an inline \`border\`, \`borderColor\`, \`borderWidth\` or \`borderStyle\` on a kit control \u2014 \`Button\`, \`Input\`, \`Select\`, \`TextArea\`, \`Checkbox\`, \`RadioGroup\`, \`Toggle\`, \`SearchField\`. The control draws its own boundary, and it clears 3:1 on its surface in every theme: an outline chip is \`<Button variant="outline">\` exactly as it comes (its edge is \`controlAccentOutline\`). Where you draw a control-like edge on your own element, use \`var(--ggui-color-controlOutline)\`. A ramp step such as \`primary-200\` as a control's border is nearly invisible (about 1.1:1).
|
|
2135
2134
|
|
|
2136
2135
|
Token categories:
|
|
2137
2136
|
- Brand fills: \`var(--ggui-color-primary-600)\`, \`var(--ggui-color-primary-50)\`
|
|
2138
2137
|
- Accent text: \`var(--ggui-color-link)\` \u2014 eyebrows, taglines, links, labels; readable per mode (never a bare \`primary-<stop>\` as a text color)
|
|
2139
2138
|
- Text: \`var(--ggui-color-onContainer)\`, \`var(--ggui-color-onSunken)\`
|
|
2140
2139
|
- Backgrounds: \`var(--ggui-color-container)\`, \`var(--ggui-color-sunken)\`
|
|
2141
|
-
- Borders: \`var(--ggui-color-outline)\`
|
|
2140
|
+
- Borders: \`var(--ggui-color-outline)\` \u2014 dividers and the edges of non-interactive boxes; a control's edge is the kit's (rule 5)
|
|
2142
2141
|
- Spacing: \`var(--ggui-spacing-4)\`, \`var(--ggui-spacing-6)\`
|
|
2143
2142
|
- Typography: \`var(--ggui-font-size-sm)\`, \`var(--ggui-font-weight-semibold)\`
|
|
2144
2143
|
- Shadows: \`var(--ggui-shape-shadow-sm)\`, \`var(--ggui-shape-shadow-md)\`, \`var(--ggui-shape-shadow-lg)\`
|
|
@@ -2153,7 +2152,7 @@ Use the FULL primary palette throughout the component \u2014 NOT only on submit
|
|
|
2153
2152
|
| Element | Token | Purpose |
|
|
2154
2153
|
|---------|-------|---------|
|
|
2155
2154
|
| Section headers, hero areas, highlight strips | \`primary-50\` / \`primary-100\` | Subtle branded backgrounds |
|
|
2156
|
-
|
|
|
2155
|
+
| Dividers, section rules, edges of non-interactive boxes | \`primary-200\` / \`primary-300\` | Branded structure \u2014 never a control's border (rule 5) |
|
|
2157
2156
|
| Accent TEXT \u2014 eyebrows, taglines, links, labels, inline arrows | \`link\` (\`var(--ggui-color-link)\`) or \`<Text tone="emphasized">\` | The brand's READABLE ink, derived per mode to clear 4.5:1 \u2014 a bare \`primary-300\u2026600\` as a text color fails tier-0 |
|
|
2158
2157
|
| Icon fills, badges, active indicators | \`primary-500\` / \`primary-600\` | Core accent fill |
|
|
2159
2158
|
| Buttons, CTAs, filled interactive elements | \`primary-600\` / \`primary-700\` | Primary actions |
|