@loworbitstudio/visor-theme-engine 0.15.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.
- package/dist/adapters/index.d.ts +1 -1
- package/dist/fowt.d.ts +46 -1
- package/dist/fowt.js +22 -1
- package/dist/index.d.ts +396 -10
- package/dist/index.js +471 -7
- package/dist/{types-zug1_eLX.d.ts → types-BstIS9rL.d.ts} +175 -1
- package/package.json +1 -1
- package/src/visor-theme.schema.json +155 -7
|
@@ -224,6 +224,171 @@ interface ThemeBrandResult {
|
|
|
224
224
|
warnings: string[];
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Brand-strategy types for the Visor theme engine (VI-505).
|
|
229
|
+
*
|
|
230
|
+
* The Brand Record as validated, serializable, theme-aware data — a top-level
|
|
231
|
+
* `brand-strategy` block in `.visor.yaml`, SIBLING to the asset-only `brand`
|
|
232
|
+
* block (`packages/theme-engine/src/brand/`). The two have different lifecycles
|
|
233
|
+
* and consumers: `brand` declares logo/wordmark/etc. assets; `brand-strategy`
|
|
234
|
+
* declares positioning, personality, pillars, voice, and tone.
|
|
235
|
+
*
|
|
236
|
+
* Shape follows F1 — Visor's authored Brand Record
|
|
237
|
+
* (`docs/brand/visor-brand-record.yaml`) — itself derived from the VI-498
|
|
238
|
+
* research sketch (§5a).
|
|
239
|
+
*
|
|
240
|
+
* This module is deliberately self-contained and engine-decoupled (D4): the
|
|
241
|
+
* types, the pure validators (coherence context is injected, never imported),
|
|
242
|
+
* and the serializer lift cleanly into a future `@loworbitstudio/visor-brand`
|
|
243
|
+
* package. Engine-specific wiring (the known-token set, the comprehensive
|
|
244
|
+
* `validate()` pass, the manifest serialization call-site) lives outside.
|
|
245
|
+
*/
|
|
246
|
+
/** Positioning — the onliness, category, and differentiation wedge. */
|
|
247
|
+
interface BrandPositioning {
|
|
248
|
+
/** The single sentence that passes Neumeier's "only" test. */
|
|
249
|
+
onliness: string;
|
|
250
|
+
/** The category the brand competes in (e.g. "design system"). */
|
|
251
|
+
category: string;
|
|
252
|
+
/** What sets the brand apart within that category. */
|
|
253
|
+
differentiation: string;
|
|
254
|
+
}
|
|
255
|
+
/** A personality trait sharpened by its antonym (brand-as-person). */
|
|
256
|
+
interface BrandPersonalityTrait {
|
|
257
|
+
/** The trait (e.g. "precise"). */
|
|
258
|
+
trait: string;
|
|
259
|
+
/** What the trait is NOT — the antonym that earns it its keep (e.g. "fussy"). */
|
|
260
|
+
not: string;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Brand archetype assignment (Pearson & Mark — twelve archetypes). Primary is
|
|
264
|
+
* required; secondary and tertiary are optional refinements.
|
|
265
|
+
*/
|
|
266
|
+
interface BrandArchetype {
|
|
267
|
+
primary: string;
|
|
268
|
+
secondary?: string;
|
|
269
|
+
tertiary?: string;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* What a pillar governs — the link that turns a slogan into a checkable claim.
|
|
273
|
+
* Targets span three namespaces: design tokens, registry components, and
|
|
274
|
+
* meta-surfaces (the manifest, the CLI, component metadata). The `openness`
|
|
275
|
+
* pillar governs the last of these, which is why `governs` accepts more than
|
|
276
|
+
* tokens/components (F1 schema note). At least one target list is expected.
|
|
277
|
+
*/
|
|
278
|
+
interface BrandGoverns {
|
|
279
|
+
/** Semantic token refs (with or without the leading `--`), or `"*"` for all. */
|
|
280
|
+
tokens?: string[];
|
|
281
|
+
/** Registry component names, or `"*"` for all. */
|
|
282
|
+
components?: string[];
|
|
283
|
+
/** Meta-surfaces (e.g. `manifest`, `cli`, `component-metadata`). */
|
|
284
|
+
surfaces?: string[];
|
|
285
|
+
}
|
|
286
|
+
/** A strategic pillar — an essence word made operational. */
|
|
287
|
+
interface BrandPillar {
|
|
288
|
+
/** Stable id (e.g. "coherence"). */
|
|
289
|
+
id: string;
|
|
290
|
+
/** The pillar's claim in one line. */
|
|
291
|
+
statement: string;
|
|
292
|
+
/** What the pillar governs (coherence-checked against the live system). */
|
|
293
|
+
governs: BrandGoverns;
|
|
294
|
+
}
|
|
295
|
+
/** A fixed voice trait with a worked example. */
|
|
296
|
+
interface BrandVoiceTrait {
|
|
297
|
+
/** Trait name (e.g. "plainspoken"). */
|
|
298
|
+
name: string;
|
|
299
|
+
/** What to do. */
|
|
300
|
+
do: string;
|
|
301
|
+
/** What not to do. */
|
|
302
|
+
dont: string;
|
|
303
|
+
/** A worked example sentence (F1 carries one on every trait). */
|
|
304
|
+
example?: string;
|
|
305
|
+
}
|
|
306
|
+
/** Voice — fixed across the brand; never flexes. */
|
|
307
|
+
interface BrandVoice {
|
|
308
|
+
traits: BrandVoiceTrait[];
|
|
309
|
+
}
|
|
310
|
+
/** A single tone entry, keyed (in `tone`) to a recognized UI state. */
|
|
311
|
+
interface BrandToneEntry {
|
|
312
|
+
/** The feeling the copy should evoke in this state. */
|
|
313
|
+
feeling: string;
|
|
314
|
+
/** A worked example message for this state. */
|
|
315
|
+
example: string;
|
|
316
|
+
}
|
|
317
|
+
/** A lexicon pairing — the word to use and the one to avoid. */
|
|
318
|
+
interface BrandLexiconEntry {
|
|
319
|
+
use: string;
|
|
320
|
+
avoid: string;
|
|
321
|
+
}
|
|
322
|
+
/** Visibility of a brand strategy. Client brands are `private`. */
|
|
323
|
+
type BrandVisibility = "public" | "private";
|
|
324
|
+
/**
|
|
325
|
+
* The `brand-strategy` block — strategy + verbal identity as data.
|
|
326
|
+
*
|
|
327
|
+
* `tone` is keyed by UI state (`error`, `success`, …); the keys are validated
|
|
328
|
+
* against the recognized UI states (coherence check D2). All ten fields are
|
|
329
|
+
* required in v1 — F1 authors the full record, and the downstream Workbench
|
|
330
|
+
* surfaces render each section.
|
|
331
|
+
*/
|
|
332
|
+
interface BrandStrategy {
|
|
333
|
+
positioning: BrandPositioning;
|
|
334
|
+
/** 2–3 internal-facing core words (Aaker essence). */
|
|
335
|
+
essence: string[];
|
|
336
|
+
personality: BrandPersonalityTrait[];
|
|
337
|
+
archetype: BrandArchetype;
|
|
338
|
+
pillars: BrandPillar[];
|
|
339
|
+
voice: BrandVoice;
|
|
340
|
+
/** Voice flexed per UI state. Keys ∈ recognized UI states. */
|
|
341
|
+
tone: Record<string, BrandToneEntry>;
|
|
342
|
+
lexicon: BrandLexiconEntry[];
|
|
343
|
+
/** Aaker core/extended — the immutable subset, as section names. */
|
|
344
|
+
core: string[];
|
|
345
|
+
visibility: BrandVisibility;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* The agent-facing projection of a brand strategy, embedded in
|
|
349
|
+
* `visor-manifest.json` under `brand_strategy` (D3). Structurally identical to
|
|
350
|
+
* the authored shape so an agent reads `voice.traits` / `tone.error` the way it
|
|
351
|
+
* reads a component's `when_to_use`. Only PUBLIC strategies are serialized.
|
|
352
|
+
*/
|
|
353
|
+
type SerializedBrandStrategy = BrandStrategy;
|
|
354
|
+
/** Recognized UI states a `tone` key may target (coherence check D2). */
|
|
355
|
+
declare const DEFAULT_BRAND_STRATEGY_TONE_STATES: readonly string[];
|
|
356
|
+
/** Recognized meta-surfaces a pillar may govern (coherence check D2). */
|
|
357
|
+
declare const DEFAULT_BRAND_STRATEGY_SURFACES: readonly string[];
|
|
358
|
+
/** Valid `visibility` values. */
|
|
359
|
+
declare const BRAND_VISIBILITIES: readonly BrandVisibility[];
|
|
360
|
+
/** Wildcard accepted in any `governs` target list — matches all of that namespace. */
|
|
361
|
+
declare const GOVERNS_WILDCARD = "*";
|
|
362
|
+
type BrandStrategyIssueSeverity = "error" | "warning";
|
|
363
|
+
/** A single validation finding. Mirrors the engine's `ValidationIssue` shape. */
|
|
364
|
+
interface BrandStrategyIssue {
|
|
365
|
+
severity: BrandStrategyIssueSeverity;
|
|
366
|
+
code: string;
|
|
367
|
+
message: string;
|
|
368
|
+
path?: string;
|
|
369
|
+
}
|
|
370
|
+
/** Structured validation result for a brand-strategy block. */
|
|
371
|
+
interface BrandStrategyValidationResult {
|
|
372
|
+
valid: boolean;
|
|
373
|
+
errors: BrandStrategyIssue[];
|
|
374
|
+
warnings: BrandStrategyIssue[];
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Coherence context — the real-world sets a strategy's links are checked
|
|
378
|
+
* against. Injected by the caller (the engine `validate()` pass, the manifest
|
|
379
|
+
* builder, or a test) so the validator stays pure and engine-decoupled (D4).
|
|
380
|
+
*/
|
|
381
|
+
interface BrandStrategyContext {
|
|
382
|
+
/** Known semantic token names WITHOUT the leading `--` (e.g. "primary", "surface-card"). When omitted, token coherence is skipped. */
|
|
383
|
+
tokens?: ReadonlySet<string>;
|
|
384
|
+
/** Known registry component names. When omitted, only `"*"` is accepted for components. */
|
|
385
|
+
components?: ReadonlySet<string>;
|
|
386
|
+
/** Recognized meta-surfaces. Defaults to {@link DEFAULT_BRAND_STRATEGY_SURFACES}. */
|
|
387
|
+
surfaces?: ReadonlySet<string>;
|
|
388
|
+
/** Recognized UI states for `tone` keys. Defaults to {@link DEFAULT_BRAND_STRATEGY_TONE_STATES}. */
|
|
389
|
+
states?: ReadonlySet<string>;
|
|
390
|
+
}
|
|
391
|
+
|
|
227
392
|
/**
|
|
228
393
|
* Types for the Visor Theme Engine
|
|
229
394
|
*
|
|
@@ -381,6 +546,15 @@ interface VisorThemeConfig {
|
|
|
381
546
|
* Omitted → the Visor default brand (stock themes are not logo-less).
|
|
382
547
|
*/
|
|
383
548
|
brand?: VisorBrand;
|
|
549
|
+
/**
|
|
550
|
+
* Brand-strategy block (VI-505) — positioning, personality, pillars, voice,
|
|
551
|
+
* and tone as validated, serializable data. SIBLING to `brand` (assets):
|
|
552
|
+
* different lifecycle and consumer. NOT expanded into derived CSS values;
|
|
553
|
+
* coherence-checked (pillars→tokens/components/surfaces; tone→UI states) and
|
|
554
|
+
* serialized to the agent manifest. Liftable into a future
|
|
555
|
+
* `@loworbitstudio/visor-brand` package (D4).
|
|
556
|
+
*/
|
|
557
|
+
"brand-strategy"?: BrandStrategy;
|
|
384
558
|
spacing?: {
|
|
385
559
|
base?: number;
|
|
386
560
|
};
|
|
@@ -605,4 +779,4 @@ interface ThemeData {
|
|
|
605
779
|
output: ThemeOutput;
|
|
606
780
|
}
|
|
607
781
|
|
|
608
|
-
export { type BrandSlot as B, type ColorRole as C, type FontResolveOptions as F, type GoogleFontEntry as G, type OKLCH as O, type ParsedColor as P, type ResolvedThemeConfig as R, type
|
|
782
|
+
export { type BrandPositioning as A, type BrandSlot as B, type ColorRole as C, type BrandStrategyIssueSeverity as D, type BrandToneEntry as E, type FontResolveOptions as F, type GoogleFontEntry as G, type BrandVariant as H, type BrandVisibility as I, type BrandVoice as J, type BrandVoiceTrait as K, type ColorFormat as L, DEFAULT_BRAND_STRATEGY_SURFACES as M, DEFAULT_BRAND_STRATEGY_TONE_STATES as N, type OKLCH as O, type ParsedColor as P, type FontSource as Q, type ResolvedThemeConfig as R, type SerializedBrandStrategy as S, type ThemeFontResult as T, GOVERNS_WILDCARD as U, type VisorTypography as V, type RGBA as W, type SemanticTokenValue as X, type FontResolution as a, type FontDisplayStrategy as b, type VisorBrand as c, type BrandSource as d, type BrandResolution as e, type ThemeBrandResult as f, type BrandStrategy as g, type BrandStrategyContext as h, type BrandStrategyIssue as i, type BrandStrategyValidationResult as j, type GeneratedPrimitives as k, type ThemeOutput as l, type ThemeData as m, type VisorThemeConfig as n, type FullShadeScale as o, type SelectiveShadeScale as p, type RGB as q, type SemanticTokens as r, type ShadeStep as s, BRAND_VARIANTS as t, BRAND_VISIBILITIES as u, type BrandArchetype as v, type BrandGoverns as w, type BrandLexiconEntry as x, type BrandPersonalityTrait as y, type BrandPillar as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loworbitstudio/visor-theme-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Theme engine for the Visor design system — shade generation, token mapping, font resolution, and import/export for .visor.yaml themes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"label": {
|
|
24
24
|
"type": "string",
|
|
25
|
-
"description": "Human-readable display name for the theme (e.g. '
|
|
25
|
+
"description": "Human-readable display name for the theme (e.g. 'My Brand Pro'). Overrides the name-derived label in the docs theme switcher. Optional."
|
|
26
26
|
},
|
|
27
27
|
"default-mode": {
|
|
28
28
|
"type": "string",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"properties": {
|
|
101
101
|
"family": {
|
|
102
102
|
"type": "string",
|
|
103
|
-
"description": "Google Fonts
|
|
103
|
+
"description": "Font family name — Google Fonts name, Visor Fonts name, or CSS font stack."
|
|
104
104
|
},
|
|
105
105
|
"weight": {
|
|
106
106
|
"type": "integer",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"source": {
|
|
112
112
|
"type": "string",
|
|
113
113
|
"enum": ["google-fonts", "visor-fonts", "local"],
|
|
114
|
-
"description": "Font source.
|
|
114
|
+
"description": "Font source. Default: \"google-fonts\". Use \"visor-fonts\" for CDN-hosted fonts, \"local\" for self-hosted fonts."
|
|
115
115
|
},
|
|
116
116
|
"org": {
|
|
117
117
|
"type": "string",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"properties": {
|
|
127
127
|
"family": {
|
|
128
128
|
"type": "string",
|
|
129
|
-
"description": "Google Fonts
|
|
129
|
+
"description": "Font family name — Google Fonts name, Visor Fonts name, or CSS font stack."
|
|
130
130
|
},
|
|
131
131
|
"weight": {
|
|
132
132
|
"type": "integer",
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"source": {
|
|
138
138
|
"type": "string",
|
|
139
139
|
"enum": ["google-fonts", "visor-fonts", "local"],
|
|
140
|
-
"description": "Font source.
|
|
140
|
+
"description": "Font source. Default: \"google-fonts\". Use \"visor-fonts\" for CDN-hosted fonts, \"local\" for self-hosted fonts."
|
|
141
141
|
},
|
|
142
142
|
"org": {
|
|
143
143
|
"type": "string",
|
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
"properties": {
|
|
152
152
|
"family": {
|
|
153
153
|
"type": "string",
|
|
154
|
-
"description": "Google Fonts
|
|
154
|
+
"description": "Font family name — Google Fonts name, Visor Fonts name, or CSS font stack."
|
|
155
155
|
},
|
|
156
156
|
"weight": {
|
|
157
157
|
"type": "integer",
|
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
"source": {
|
|
163
163
|
"type": "string",
|
|
164
164
|
"enum": ["google-fonts", "visor-fonts", "local"],
|
|
165
|
-
"description": "Font source.
|
|
165
|
+
"description": "Font source. Default: \"google-fonts\". Use \"visor-fonts\" for CDN-hosted fonts, \"local\" for self-hosted fonts."
|
|
166
166
|
},
|
|
167
167
|
"org": {
|
|
168
168
|
"type": "string",
|
|
@@ -293,6 +293,59 @@
|
|
|
293
293
|
]
|
|
294
294
|
}
|
|
295
295
|
},
|
|
296
|
+
"brand-strategy": {
|
|
297
|
+
"type": "object",
|
|
298
|
+
"description": "Brand-strategy block (VI-505) — positioning, personality, pillars, voice, and tone as validated, serializable data. Sibling to `brand` (assets): different lifecycle and consumer. NOT expanded into derived CSS values; coherence-checked (pillars govern real tokens/components/surfaces; tone keys map to real UI states) and serialized to the agent manifest under `brand_strategy`.",
|
|
299
|
+
"additionalProperties": false,
|
|
300
|
+
"required": ["positioning", "essence", "personality", "archetype", "pillars", "voice", "tone", "lexicon", "core", "visibility"],
|
|
301
|
+
"properties": {
|
|
302
|
+
"positioning": { "$ref": "#/$defs/brandPositioning" },
|
|
303
|
+
"essence": {
|
|
304
|
+
"type": "array",
|
|
305
|
+
"items": { "type": "string" },
|
|
306
|
+
"minItems": 1,
|
|
307
|
+
"description": "2–3 internal-facing core words (Aaker essence)."
|
|
308
|
+
},
|
|
309
|
+
"personality": {
|
|
310
|
+
"type": "array",
|
|
311
|
+
"items": { "$ref": "#/$defs/brandPersonalityTrait" },
|
|
312
|
+
"minItems": 1,
|
|
313
|
+
"description": "Brand-as-person traits, each sharpened by its antonym."
|
|
314
|
+
},
|
|
315
|
+
"archetype": { "$ref": "#/$defs/brandArchetype" },
|
|
316
|
+
"pillars": {
|
|
317
|
+
"type": "array",
|
|
318
|
+
"items": { "$ref": "#/$defs/brandPillar" },
|
|
319
|
+
"minItems": 1,
|
|
320
|
+
"description": "Strategic pillars — essence words made operational, each governing real tokens/components/surfaces."
|
|
321
|
+
},
|
|
322
|
+
"voice": { "$ref": "#/$defs/brandVoice" },
|
|
323
|
+
"tone": {
|
|
324
|
+
"type": "object",
|
|
325
|
+
"description": "Voice flexed per UI state. Keys must be recognized UI states.",
|
|
326
|
+
"minProperties": 1,
|
|
327
|
+
"propertyNames": { "enum": ["error", "success", "warning", "info", "empty", "loading", "validation-warning"] },
|
|
328
|
+
"additionalProperties": { "$ref": "#/$defs/brandToneEntry" }
|
|
329
|
+
},
|
|
330
|
+
"lexicon": {
|
|
331
|
+
"type": "array",
|
|
332
|
+
"items": { "$ref": "#/$defs/brandLexiconEntry" },
|
|
333
|
+
"minItems": 1,
|
|
334
|
+
"description": "Words to use and the ones to avoid."
|
|
335
|
+
},
|
|
336
|
+
"core": {
|
|
337
|
+
"type": "array",
|
|
338
|
+
"items": { "type": "string" },
|
|
339
|
+
"minItems": 1,
|
|
340
|
+
"description": "Aaker core/extended — the immutable subset, as section names."
|
|
341
|
+
},
|
|
342
|
+
"visibility": {
|
|
343
|
+
"type": "string",
|
|
344
|
+
"enum": ["public", "private"],
|
|
345
|
+
"description": "Client brands are private and are omitted from the public agent manifest."
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
},
|
|
296
349
|
"spacing": {
|
|
297
350
|
"type": "object",
|
|
298
351
|
"description": "Spacing configuration.",
|
|
@@ -460,6 +513,101 @@
|
|
|
460
513
|
"description": "Letter spacing in logical pixels (Flutter TextStyle.letterSpacing). Material defaults include negative values, e.g. -0.25 for displayLarge."
|
|
461
514
|
}
|
|
462
515
|
}
|
|
516
|
+
},
|
|
517
|
+
"brandPositioning": {
|
|
518
|
+
"type": "object",
|
|
519
|
+
"description": "Positioning — the onliness, category, and differentiation wedge.",
|
|
520
|
+
"additionalProperties": false,
|
|
521
|
+
"required": ["onliness", "category", "differentiation"],
|
|
522
|
+
"properties": {
|
|
523
|
+
"onliness": { "type": "string", "minLength": 1, "description": "The single sentence that passes Neumeier's \"only\" test." },
|
|
524
|
+
"category": { "type": "string", "minLength": 1, "description": "The category the brand competes in (e.g. \"design system\")." },
|
|
525
|
+
"differentiation": { "type": "string", "minLength": 1, "description": "What sets the brand apart within that category." }
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
"brandPersonalityTrait": {
|
|
529
|
+
"type": "object",
|
|
530
|
+
"description": "A personality trait sharpened by its antonym (brand-as-person).",
|
|
531
|
+
"additionalProperties": false,
|
|
532
|
+
"required": ["trait", "not"],
|
|
533
|
+
"properties": {
|
|
534
|
+
"trait": { "type": "string", "minLength": 1 },
|
|
535
|
+
"not": { "type": "string", "minLength": 1, "description": "The antonym — what the trait is not." }
|
|
536
|
+
}
|
|
537
|
+
},
|
|
538
|
+
"brandArchetype": {
|
|
539
|
+
"type": "object",
|
|
540
|
+
"description": "Brand archetype assignment (Pearson & Mark). Primary required; secondary/tertiary optional.",
|
|
541
|
+
"additionalProperties": false,
|
|
542
|
+
"required": ["primary"],
|
|
543
|
+
"properties": {
|
|
544
|
+
"primary": { "type": "string", "minLength": 1 },
|
|
545
|
+
"secondary": { "type": "string", "minLength": 1 },
|
|
546
|
+
"tertiary": { "type": "string", "minLength": 1 }
|
|
547
|
+
}
|
|
548
|
+
},
|
|
549
|
+
"brandGoverns": {
|
|
550
|
+
"type": "object",
|
|
551
|
+
"description": "What a pillar governs — design tokens, registry components, and/or meta-surfaces. At least one list is expected; use \"*\" for all of a namespace.",
|
|
552
|
+
"additionalProperties": false,
|
|
553
|
+
"minProperties": 1,
|
|
554
|
+
"properties": {
|
|
555
|
+
"tokens": { "type": "array", "items": { "type": "string" }, "minItems": 1, "description": "Semantic token refs (with or without the leading --), or \"*\"." },
|
|
556
|
+
"components": { "type": "array", "items": { "type": "string" }, "minItems": 1, "description": "Registry component names, or \"*\" for all." },
|
|
557
|
+
"surfaces": { "type": "array", "items": { "type": "string", "enum": ["manifest", "cli", "component-metadata"] }, "minItems": 1, "description": "Meta-surfaces a pillar may govern." }
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
"brandPillar": {
|
|
561
|
+
"type": "object",
|
|
562
|
+
"description": "A strategic pillar — an essence word made operational.",
|
|
563
|
+
"additionalProperties": false,
|
|
564
|
+
"required": ["id", "statement", "governs"],
|
|
565
|
+
"properties": {
|
|
566
|
+
"id": { "type": "string", "minLength": 1 },
|
|
567
|
+
"statement": { "type": "string", "minLength": 1, "description": "The pillar's claim in one line." },
|
|
568
|
+
"governs": { "$ref": "#/$defs/brandGoverns" }
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
"brandVoice": {
|
|
572
|
+
"type": "object",
|
|
573
|
+
"description": "Voice — fixed across the brand; never flexes.",
|
|
574
|
+
"additionalProperties": false,
|
|
575
|
+
"required": ["traits"],
|
|
576
|
+
"properties": {
|
|
577
|
+
"traits": { "type": "array", "items": { "$ref": "#/$defs/brandVoiceTrait" }, "minItems": 1 }
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
"brandVoiceTrait": {
|
|
581
|
+
"type": "object",
|
|
582
|
+
"description": "A fixed voice trait with a worked example.",
|
|
583
|
+
"additionalProperties": false,
|
|
584
|
+
"required": ["name", "do", "dont"],
|
|
585
|
+
"properties": {
|
|
586
|
+
"name": { "type": "string", "minLength": 1 },
|
|
587
|
+
"do": { "type": "string", "minLength": 1, "description": "What to do." },
|
|
588
|
+
"dont": { "type": "string", "minLength": 1, "description": "What not to do." },
|
|
589
|
+
"example": { "type": "string", "minLength": 1, "description": "A worked example sentence." }
|
|
590
|
+
}
|
|
591
|
+
},
|
|
592
|
+
"brandToneEntry": {
|
|
593
|
+
"type": "object",
|
|
594
|
+
"description": "A single tone entry, keyed (in `tone`) to a recognized UI state.",
|
|
595
|
+
"additionalProperties": false,
|
|
596
|
+
"required": ["feeling", "example"],
|
|
597
|
+
"properties": {
|
|
598
|
+
"feeling": { "type": "string", "minLength": 1, "description": "The feeling the copy should evoke in this state." },
|
|
599
|
+
"example": { "type": "string", "minLength": 1, "description": "A worked example message for this state." }
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
"brandLexiconEntry": {
|
|
603
|
+
"type": "object",
|
|
604
|
+
"description": "A lexicon pairing — the word to use and the one to avoid.",
|
|
605
|
+
"additionalProperties": false,
|
|
606
|
+
"required": ["use", "avoid"],
|
|
607
|
+
"properties": {
|
|
608
|
+
"use": { "type": "string", "minLength": 1 },
|
|
609
|
+
"avoid": { "type": "string", "minLength": 1 }
|
|
610
|
+
}
|
|
463
611
|
}
|
|
464
612
|
}
|
|
465
613
|
}
|