@ryuenn3123/agentic-senior-core 3.0.36 → 3.0.38
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/.agent-context/prompts/bootstrap-design.md +109 -113
- package/.agent-context/rules/frontend-architecture.md +92 -104
- package/.agent-context/state/README.md +26 -0
- package/.cursor/mcp.json +10 -0
- package/.cursor/rules/agentic-senior-core.mdc +48 -0
- package/.cursorrules +22 -88
- package/.gemini/instructions.md +25 -16
- package/.github/copilot-instructions.md +25 -16
- package/.github/instructions/agentic-senior-core.instructions.md +47 -0
- package/.instructions.md +98 -207
- package/.windsurf/rules/agentic-senior-core.md +43 -0
- package/.windsurfrules +22 -88
- package/AGENTS.md +23 -26
- package/CLAUDE.md +43 -0
- package/CONTRIBUTING.md +5 -2
- package/GEMINI.md +43 -0
- package/README.md +24 -7
- package/lib/cli/backup.mjs +4 -4
- package/lib/cli/commands/init/project-context.mjs +101 -0
- package/lib/cli/commands/init/runtime-environment.mjs +59 -0
- package/lib/cli/commands/init/setup-decisions.mjs +83 -0
- package/lib/cli/commands/init.mjs +33 -250
- package/lib/cli/commands/optimize.mjs +1 -1
- package/lib/cli/commands/upgrade.mjs +32 -7
- package/lib/cli/compiler.mjs +59 -17
- package/lib/cli/constants.mjs +5 -0
- package/lib/cli/detector.mjs +4 -0
- package/lib/cli/preflight.mjs +3 -3
- package/lib/cli/project-scaffolder/design-contract/validation.mjs +789 -0
- package/lib/cli/project-scaffolder/design-contract.mjs +137 -861
- package/lib/cli/project-scaffolder/prompt-builders.mjs +73 -81
- package/lib/cli/utils/filesystem.mjs +79 -0
- package/lib/cli/utils/managed-surface.mjs +237 -0
- package/lib/cli/utils/prompting.mjs +44 -0
- package/lib/cli/utils.mjs +33 -335
- package/package.json +21 -2
- package/scripts/clean-local-artifacts.mjs +76 -0
- package/scripts/docs-quality-drift-report.mjs +5 -0
- package/scripts/frontend-usability-audit.mjs +23 -19
- package/scripts/governance-weekly-report.mjs +37 -15
- package/scripts/single-source-lazy-loading-audit.mjs +24 -0
- package/scripts/sync-thin-adapters.mjs +99 -129
- package/scripts/v3-purge-audit.mjs +5 -0
- package/scripts/validate/config.mjs +21 -0
- package/scripts/validate/coverage-checks.mjs +55 -0
- package/.agent-context/marketplace/trust-tiers.json +0 -114
- package/.agent-context/state/benchmark-analysis.json +0 -431
- package/.agent-context/state/benchmark-evidence-bundle.json +0 -1040
- package/.agent-context/state/benchmark-history.json +0 -75
- package/.agent-context/state/benchmark-trend-report.csv +0 -5
- package/.agent-context/state/benchmark-trend-report.json +0 -140
- package/.agent-context/state/benchmark-writer-judge-matrix.json +0 -462
- package/.agent-context/state/memory-continuity-benchmark.json +0 -132
- package/.agent-context/state/onboarding-report.json +0 -102
- package/.agent-context/state/quality-trend-report.json +0 -89
- package/.agent-context/state/token-optimization-benchmark.json +0 -130
- package/.agent-context/state/weekly-governance-report.json +0 -329
- package/lib/cli/compatibility.mjs +0 -124
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
import { toTitleCase } from '../utils.mjs';
|
|
2
2
|
import { DESIGN_REQUIRED_SECTIONS } from './constants.mjs';
|
|
3
|
+
import { validateDesignIntentContract } from './design-contract/validation.mjs';
|
|
4
|
+
|
|
5
|
+
const GENERICITY_DRIFT_SIGNALS = [
|
|
6
|
+
'offline-prescribed-style-used-as-final-direction',
|
|
7
|
+
'unresearched-library-or-framework-choice',
|
|
8
|
+
'missing-conceptual-anchor-without-external-research',
|
|
9
|
+
'visual-decisions-not-derived-from-conceptual-anchor',
|
|
10
|
+
'ai-safe-ui-template-look',
|
|
11
|
+
'ai-color-default-palette-without-product-role-behavior',
|
|
12
|
+
'brandless-clean-template-look',
|
|
13
|
+
'interchangeable-product-renaming-test-fails',
|
|
14
|
+
'decorative-grid-or-glow-wallpaper-without-product-function',
|
|
15
|
+
'safe-cream-slate-or-monochrome-palette-used-as-readability-excuse',
|
|
16
|
+
'generic-abstract-logo-or-iconography',
|
|
17
|
+
'timid-anchor-that-renames-dashboard-or-admin-shell',
|
|
18
|
+
'motion-suppressed-without-accessibility-or-performance-reason',
|
|
19
|
+
'motion-or-3d-omitted-from-fear-without-fit-analysis',
|
|
20
|
+
'scale-only-responsive-layout',
|
|
21
|
+
'zero-based-redesign-kept-prior-visual-dna',
|
|
22
|
+
'restyle-instead-of-recomposition',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const FORBIDDEN_PATTERN_SIGNALS = [
|
|
26
|
+
...GENERICITY_DRIFT_SIGNALS.filter((signal) => signal !== 'unresearched-library-or-framework-choice'),
|
|
27
|
+
'single-safe-typographic-family-without-role-contrast-or-rationale',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const VALID_BOLD_SIGNALS = [
|
|
31
|
+
'single-cohesive-conceptual-anchor',
|
|
32
|
+
'high-variance-candidate-selection',
|
|
33
|
+
'context-derived-visual-direction',
|
|
34
|
+
'three-at-a-glance-product-specific-signals',
|
|
35
|
+
'visually-exploratory-accessible-palette-derived-from-product',
|
|
36
|
+
'audacious-accessible-palette-with-product-role-behavior',
|
|
37
|
+
'background-or-geometry-serves-product-function',
|
|
38
|
+
'motion-or-spatial-experience-derived-from-anchor',
|
|
39
|
+
'explicit-3d-canvas-fit-or-nonfit-decision',
|
|
40
|
+
'responsive-recomposition-by-task-priority',
|
|
41
|
+
'purposeful-motion-with-reduced-motion-path',
|
|
42
|
+
];
|
|
3
43
|
|
|
4
44
|
export function shouldBootstrapDesignDocument(discoveryAnswers, initContext) {
|
|
5
45
|
const normalizedDomain = String(discoveryAnswers.primaryDomain || '').trim().toLowerCase();
|
|
@@ -51,26 +91,26 @@ function buildStructureFirstSeedSignals({
|
|
|
51
91
|
: 'the current product context';
|
|
52
92
|
|
|
53
93
|
return {
|
|
54
|
-
designPhilosophy: `
|
|
94
|
+
designPhilosophy: `Synthesize design for ${projectName || 'this project'} from ${evidenceSourceLabel}. Choose visual language, libraries, color, type, spacing, and interaction from ${projectContextLabel}; verify technology claims with official docs.`,
|
|
55
95
|
typographyScaleRatio: 'agent-calibrated-from-content-platform-and-readability',
|
|
56
96
|
baseGridUnit: 'agent-calibrated-from-platform-density-and-implementation-stack',
|
|
57
97
|
spacingPattern: 'agent-defined-from-task-flow-and-viewport-needs',
|
|
58
98
|
densityMode: 'agent-defined-from-user-task-device-and-content-pressure',
|
|
59
|
-
colorIntent: `Choose semantic palette roles from ${projectContextLabel},
|
|
99
|
+
colorIntent: `Choose semantic palette roles from ${projectContextLabel}, repo evidence, and accessibility. Reject scaffold or SaaS palette defaults.`,
|
|
60
100
|
paletteRoles: ['agent-defined-semantic-roles'],
|
|
61
101
|
distinctiveMoves: [
|
|
62
|
-
'Choose one
|
|
102
|
+
'Choose one product-specific move from task, audience, content, repo evidence, and docs.',
|
|
63
103
|
],
|
|
64
|
-
motionPurpose: '
|
|
104
|
+
motionPurpose: 'Use expressive motion when it improves hierarchy, continuity, feedback, memorability, or confidence. Verify new motion libraries with official docs.',
|
|
65
105
|
componentMorphology: {
|
|
66
|
-
mobile: 'Recompose
|
|
67
|
-
tablet: 'Regroup surfaces for medium
|
|
68
|
-
desktop: 'Use
|
|
106
|
+
mobile: 'Recompose for touch, task priority, and constrained attention.',
|
|
107
|
+
tablet: 'Regroup surfaces for medium width without cloning desktop or mobile.',
|
|
108
|
+
desktop: 'Use space for hierarchy and scanability; avoid template grids.',
|
|
69
109
|
},
|
|
70
110
|
mutationRules: {
|
|
71
|
-
mobile: '
|
|
72
|
-
tablet: '
|
|
73
|
-
desktop: '
|
|
111
|
+
mobile: 'Reorder, merge, or disclose content for mobile. Reject scale-only shrink.',
|
|
112
|
+
tablet: 'Regroup for tablet instead of width-only desktop reduction.',
|
|
113
|
+
desktop: 'Use space intentionally; avoid equal-weight modules without evidence.',
|
|
74
114
|
},
|
|
75
115
|
};
|
|
76
116
|
}
|
|
@@ -132,7 +172,7 @@ function buildDesignIntentContractObject({
|
|
|
132
172
|
'ui-primitives-or-rich-media',
|
|
133
173
|
'typography-and-interaction',
|
|
134
174
|
],
|
|
135
|
-
finalDecisionAuthority: '
|
|
175
|
+
finalDecisionAuthority: 'project-fit-accessibility-performance-maintainability-official-docs',
|
|
136
176
|
},
|
|
137
177
|
conceptualAnchor: {
|
|
138
178
|
mode: 'required-when-no-external-research',
|
|
@@ -163,7 +203,7 @@ function buildDesignIntentContractObject({
|
|
|
163
203
|
'typographicDecision',
|
|
164
204
|
],
|
|
165
205
|
rejectGenericQualityWordsOnly: true,
|
|
166
|
-
specificityFloor: 'name-
|
|
206
|
+
specificityFloor: 'name-real-material-instrument-artifact-architecture-editorial-genre-cinematic-behavior-exhibition-system-scientific-apparatus-or-industrial-mechanism',
|
|
167
207
|
},
|
|
168
208
|
forbiddenFinalAnchorTerms: [
|
|
169
209
|
'dashboard',
|
|
@@ -219,42 +259,64 @@ function buildDesignIntentContractObject({
|
|
|
219
259
|
},
|
|
220
260
|
derivedTokenLogic: {
|
|
221
261
|
anchorReference: 'agent-defined-anchor-reference',
|
|
222
|
-
colorDerivationSource: '
|
|
223
|
-
spacingDerivationSource: '
|
|
224
|
-
typographyDerivationSource: '
|
|
225
|
-
motionDerivationSource: '
|
|
226
|
-
validationRule: 'Every
|
|
262
|
+
colorDerivationSource: 'Explain semantic color roles from anchorReference; reject generic palettes without anchor evidence.',
|
|
263
|
+
spacingDerivationSource: 'Explain grid, rhythm, density, and exceptions from anchorReference.',
|
|
264
|
+
typographyDerivationSource: 'Explain display, body, metadata, and data roles from anchorReference.',
|
|
265
|
+
motionDerivationSource: 'Explain duration, easing, choreography, and reduced-motion from anchorReference.',
|
|
266
|
+
validationRule: 'Every token must trace to anchorReference; revise tokens that cannot.',
|
|
227
267
|
},
|
|
228
268
|
motionPaletteDecision: {
|
|
229
269
|
productCategorySignal: 'agent-inferred-starting-heuristic',
|
|
230
|
-
densityDecisionSource: '
|
|
270
|
+
densityDecisionSource: 'Choose motion density from task, content, brand, device, performance, and accessibility. Categories are heuristics.',
|
|
231
271
|
requiredInteractionStates: ['default', 'hover', 'focus-visible', 'active', 'disabled', 'loading', 'empty', 'error', 'success', 'transition'],
|
|
232
|
-
paletteAutopilotRisks: ['dark-slate-default', 'cream-beige-default', 'purple-blue-gradient-default', 'monochrome-template-default', 'uniform-card-surface-default', 'generic-grid-wallpaper-default', 'soft-glow-ai-template-default'],
|
|
233
|
-
spatialDecision: '
|
|
272
|
+
paletteAutopilotRisks: ['dark-slate-default', 'cream-beige-default', 'purple-blue-gradient-default', 'monochrome-template-default', 'uniform-card-surface-default', 'generic-grid-wallpaper-default', 'soft-glow-ai-template-default', 'cyber-neon-terminal-default'],
|
|
273
|
+
spatialDecision: 'State 3D/canvas/WebGL fit. If omitted, name product-fit reason and replacement interaction quality.',
|
|
234
274
|
},
|
|
235
275
|
aiSafeUiAudit: {
|
|
236
276
|
status: 'agent-must-complete-before-ui-implementation',
|
|
237
|
-
failureDefinition: '
|
|
238
|
-
interchangeabilityTest: `If this UI can be renamed from ${projectName} to another product category without changing composition, palette, iconography, and motion
|
|
277
|
+
failureDefinition: 'AI-safe UI uses template cards, generic marks, decorative grid wallpaper, safe palettes, glow backgrounds, or copied scaffold composition.',
|
|
278
|
+
interchangeabilityTest: `If this UI can be renamed from ${projectName} to another product category without changing composition, palette, iconography, and motion, revise it.`,
|
|
239
279
|
requiredProductSpecificSignals: [
|
|
240
280
|
'agent-defined-product-specific-data-treatment',
|
|
241
281
|
'agent-defined-product-specific-motion-or-state-behavior',
|
|
242
282
|
'agent-defined-product-specific-morphology-iconography-or-spatial-structure',
|
|
243
283
|
],
|
|
244
|
-
paletteExplorationRule: 'Use a visually exploratory product-derived palette
|
|
245
|
-
backgroundPatternRule: 'Lines, grids, scanlines, noise, glows, blobs, logos, and
|
|
246
|
-
|
|
284
|
+
paletteExplorationRule: 'Use a visually exploratory product-derived palette with WCAG contrast and status clarity.',
|
|
285
|
+
backgroundPatternRule: 'Lines, grids, scanlines, noise, glows, blobs, logos, and geometry must serve a named product function.',
|
|
286
|
+
aiColorAudit: {
|
|
287
|
+
status: 'agent-must-complete-before-ui-implementation',
|
|
288
|
+
failureDefinition: 'AI color drift uses safe defaults before deriving roles from the product anchor.',
|
|
289
|
+
autopilotRisks: ['cream-editorial-default', 'dark-slate-dashboard-default', 'purple-blue-gradient-default', 'monochrome-minimal-default', 'cyber-neon-terminal-default', 'soft-glow-atmosphere-default'],
|
|
290
|
+
requiredEvidence: [
|
|
291
|
+
'anchor-derived-color-logic',
|
|
292
|
+
'semantic-role-contrast-beyond-surface-decoration',
|
|
293
|
+
'product-specific-color-behavior-that-would-not-transfer',
|
|
294
|
+
],
|
|
295
|
+
reviewQuestion: 'Why does this palette belong to this product?',
|
|
296
|
+
},
|
|
297
|
+
motionSpatialCourageAudit: {
|
|
298
|
+
status: 'agent-must-complete-before-ui-implementation',
|
|
299
|
+
defaultStance: 'Treat motion, scroll choreography, canvas, WebGL, and 3D as first-class options.',
|
|
300
|
+
requiredDecisionFields: [
|
|
301
|
+
'signature-motion-or-interaction',
|
|
302
|
+
'spatial-or-3d-fit',
|
|
303
|
+
'performance-and-reduced-motion-fallback',
|
|
304
|
+
],
|
|
305
|
+
rejectionRule: 'State a product reason and replacement interaction quality before omitting 3D/canvas.',
|
|
306
|
+
reviewQuestion: 'Is the interaction as expressive as the product can responsibly support?',
|
|
307
|
+
},
|
|
308
|
+
reviewQuestion: 'What visible evidence proves this is product-specific?',
|
|
247
309
|
blockingByDefault: true,
|
|
248
310
|
},
|
|
249
311
|
libraryResearchStatus: 'pending-verification',
|
|
250
312
|
libraryDecisions: [
|
|
251
313
|
{
|
|
252
314
|
library: 'agent-defined-or-none',
|
|
253
|
-
purpose: '
|
|
315
|
+
purpose: 'Verify UI-related libraries against current official docs before imports.',
|
|
254
316
|
verifiedAt: null,
|
|
255
317
|
sourceUrl: null,
|
|
256
318
|
stableVersion: null,
|
|
257
|
-
fallbackIfUnavailable: 'Use native CSS, browser APIs, or existing
|
|
319
|
+
fallbackIfUnavailable: 'Use native CSS, browser APIs, or existing dependencies.',
|
|
258
320
|
},
|
|
259
321
|
],
|
|
260
322
|
mathSystems: {
|
|
@@ -369,12 +431,12 @@ function buildDesignIntentContractObject({
|
|
|
369
431
|
status: 'seed-needs-refinement',
|
|
370
432
|
seedMode: 'structure-first-scaffold',
|
|
371
433
|
requiresTaskSpecificRefinement: true,
|
|
372
|
-
primaryExperienceGoal: `Define the main ${String(primaryDomain || 'product').toLowerCase()} journey for ${projectName} from repo evidence,
|
|
434
|
+
primaryExperienceGoal: `Define the main ${String(primaryDomain || 'product').toLowerCase()} journey for ${projectName} from repo evidence, brief, and docs.`,
|
|
373
435
|
surfacePlan: [
|
|
374
436
|
{
|
|
375
437
|
surfaceId: 'agent-defined-primary-experience',
|
|
376
438
|
role: 'primary-context-synthesized-by-agent',
|
|
377
|
-
goal: 'Choose the first task
|
|
439
|
+
goal: 'Choose the first task path from product evidence; reject template shells.',
|
|
378
440
|
antiPatterns: ['dashboard-default', 'scale-only-responsive-layout'],
|
|
379
441
|
},
|
|
380
442
|
],
|
|
@@ -449,12 +511,12 @@ function buildDesignIntentContractObject({
|
|
|
449
511
|
{
|
|
450
512
|
componentId: 'primary-interaction',
|
|
451
513
|
states: ['default', 'hover', 'focus', 'loading', 'error'],
|
|
452
|
-
notes: 'Refine states from project language and
|
|
514
|
+
notes: 'Refine states from project language and anchor; reject anonymous panels.',
|
|
453
515
|
},
|
|
454
516
|
],
|
|
455
517
|
taskFlowNarrative: [
|
|
456
|
-
`Entry:
|
|
457
|
-
'Resolution: define proof, feedback, recovery, and next action
|
|
518
|
+
`Entry: start ${projectName} from real evidence, not a generic opener.`,
|
|
519
|
+
'Resolution: define proof, feedback, recovery, and next action.',
|
|
458
520
|
],
|
|
459
521
|
visualResetStrategy: {
|
|
460
522
|
activatesWhenUserRequests: [
|
|
@@ -465,7 +527,7 @@ function buildDesignIntentContractObject({
|
|
|
465
527
|
existingUiForbiddenAs: ['palette-source', 'layout-source', 'motion-source'],
|
|
466
528
|
requiredResetAxes: ['composition', 'hierarchy', 'motion-or-interaction', 'responsive-information-architecture'],
|
|
467
529
|
},
|
|
468
|
-
signatureMoveRationale: '
|
|
530
|
+
signatureMoveRationale: 'Choose one project-specific visual, motion, type, or interaction move.',
|
|
469
531
|
creativeCommitment: {
|
|
470
532
|
status: 'agent-must-complete-before-ui-implementation',
|
|
471
533
|
requiredFields: [
|
|
@@ -473,7 +535,7 @@ function buildDesignIntentContractObject({
|
|
|
473
535
|
'signatureMotion',
|
|
474
536
|
'typographicDecision',
|
|
475
537
|
],
|
|
476
|
-
failureMode: 'generic quality words without a
|
|
538
|
+
failureMode: 'generic quality words without a real-world reference fail',
|
|
477
539
|
},
|
|
478
540
|
implementationGuardrails: {
|
|
479
541
|
requireBuildFromHandoff: true,
|
|
@@ -488,55 +550,31 @@ function buildDesignIntentContractObject({
|
|
|
488
550
|
{
|
|
489
551
|
key: 'distinctiveness',
|
|
490
552
|
blockingByDefault: true,
|
|
491
|
-
question: '
|
|
553
|
+
question: 'Is the UI authored and product-specific?',
|
|
492
554
|
},
|
|
493
555
|
{
|
|
494
556
|
key: 'contractFidelity',
|
|
495
557
|
blockingByDefault: true,
|
|
496
|
-
question: 'Does the
|
|
558
|
+
question: 'Does the UI follow contract, priorities, and accessibility?',
|
|
497
559
|
},
|
|
498
560
|
{
|
|
499
561
|
key: 'visualConsistency',
|
|
500
562
|
blockingByDefault: false,
|
|
501
|
-
question: 'Do
|
|
563
|
+
question: 'Do type, spacing, color, and states form one system?',
|
|
502
564
|
},
|
|
503
565
|
{
|
|
504
566
|
key: 'heuristicUxQuality',
|
|
505
567
|
blockingByDefault: false,
|
|
506
|
-
question: 'Does the UI preserve
|
|
568
|
+
question: 'Does the UI preserve clarity, feedback, and confidence?',
|
|
507
569
|
},
|
|
508
570
|
{
|
|
509
571
|
key: 'motionDiscipline',
|
|
510
572
|
blockingByDefault: false,
|
|
511
|
-
question: '
|
|
573
|
+
question: 'Is motion purposeful, performant, reduced-motion-safe, and on-tone?',
|
|
512
574
|
},
|
|
513
575
|
],
|
|
514
|
-
genericitySignals: [
|
|
515
|
-
|
|
516
|
-
'unresearched-library-or-framework-choice',
|
|
517
|
-
'missing-conceptual-anchor-without-external-research',
|
|
518
|
-
'visual-decisions-not-derived-from-conceptual-anchor',
|
|
519
|
-
'ai-safe-ui-template-look',
|
|
520
|
-
'interchangeable-product-renaming-test-fails',
|
|
521
|
-
'decorative-grid-or-glow-wallpaper-without-product-function',
|
|
522
|
-
'safe-cream-slate-or-monochrome-palette-used-as-readability-excuse',
|
|
523
|
-
'generic-abstract-logo-or-iconography',
|
|
524
|
-
'timid-anchor-that-renames-dashboard-or-admin-shell',
|
|
525
|
-
'motion-suppressed-without-accessibility-or-performance-reason',
|
|
526
|
-
'scale-only-responsive-layout',
|
|
527
|
-
'zero-based-redesign-kept-prior-visual-dna',
|
|
528
|
-
'restyle-instead-of-recomposition',
|
|
529
|
-
],
|
|
530
|
-
validBoldSignals: [
|
|
531
|
-
'single-cohesive-conceptual-anchor',
|
|
532
|
-
'high-variance-candidate-selection',
|
|
533
|
-
'context-derived-visual-direction',
|
|
534
|
-
'three-at-a-glance-product-specific-signals',
|
|
535
|
-
'visually-exploratory-accessible-palette-derived-from-product',
|
|
536
|
-
'background-or-geometry-serves-product-function',
|
|
537
|
-
'responsive-recomposition-by-task-priority',
|
|
538
|
-
'purposeful-motion-with-reduced-motion-path',
|
|
539
|
-
],
|
|
576
|
+
genericitySignals: [...GENERICITY_DRIFT_SIGNALS],
|
|
577
|
+
validBoldSignals: [...VALID_BOLD_SIGNALS],
|
|
540
578
|
reportingRules: {
|
|
541
579
|
mustExplainGenericity: true,
|
|
542
580
|
mustSeparateTasteFromFailure: true,
|
|
@@ -560,65 +598,45 @@ function buildDesignIntentContractObject({
|
|
|
560
598
|
repoEvidenceOverridesMemory: true,
|
|
561
599
|
requireExplicitContinuityApproval: true,
|
|
562
600
|
forbidCarryoverWhenUnapproved: true,
|
|
563
|
-
approvedExternalConstraintUsage: 'Convert
|
|
601
|
+
approvedExternalConstraintUsage: 'Convert approved external constraints into current-project rules; do not imitate source surfaces.',
|
|
564
602
|
driftSignals: [
|
|
565
603
|
'palette-reused-without-brief-support',
|
|
566
604
|
'prior-ui-visual-dna-carried-into-reset-request',
|
|
567
605
|
],
|
|
568
606
|
},
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
'
|
|
572
|
-
'
|
|
573
|
-
'
|
|
574
|
-
'
|
|
575
|
-
'
|
|
576
|
-
'
|
|
577
|
-
'
|
|
607
|
+
forbiddenPatterns: [...FORBIDDEN_PATTERN_SIGNALS],
|
|
608
|
+
validationHints: [
|
|
609
|
+
'rejectArbitraryHexOnlyPalette',
|
|
610
|
+
'requireViewportMutationRules',
|
|
611
|
+
'requirePerceptualColorRationale',
|
|
612
|
+
'requireTokenLayering',
|
|
613
|
+
'requireTokenAliasingPlan',
|
|
614
|
+
'allowHexDerivatives',
|
|
615
|
+
'requireMotionRationale',
|
|
616
|
+
'requireStateMorphology',
|
|
617
|
+
'requireAccessibilitySplit',
|
|
618
|
+
'requireWcagHardFloor',
|
|
619
|
+
'requireStructuredDesignExecutionPolicy',
|
|
620
|
+
'requireStructuredDesignHandoff',
|
|
621
|
+
'requireVisualResetStrategyWhenZeroBasedRedesignRequested',
|
|
622
|
+
'requireConceptualAnchorWhenNoExternalResearch',
|
|
623
|
+
'requireAgentLedAnchorResearchWhenUserResearchMissing',
|
|
624
|
+
'rejectTimidDashboardAnchor',
|
|
625
|
+
'requireReviewRubric',
|
|
626
|
+
'requireGenericityExplanation',
|
|
627
|
+
'genericityAutoFail',
|
|
628
|
+
'requireSignatureMove',
|
|
629
|
+
'rejectTemplateNeutralLayout',
|
|
630
|
+
'requireAiSafeUiAudit',
|
|
631
|
+
'requireAiColorAudit',
|
|
632
|
+
'rejectAiColorDefaults',
|
|
633
|
+
'requireMotionSpatialCourageAudit',
|
|
634
|
+
'requireExplicit3dCanvasFitDecision',
|
|
635
|
+
'rejectSafetyAsCreativitySubstitute',
|
|
636
|
+
'rejectAiSafeUiTemplateLook',
|
|
637
|
+
'requireThreeProductSpecificSignals',
|
|
638
|
+
'rejectDecorativeBackgroundPatternsWithoutProductFunction',
|
|
578
639
|
],
|
|
579
|
-
forbiddenPatterns: [
|
|
580
|
-
'offline-prescribed-style-used-as-final-direction',
|
|
581
|
-
'missing-conceptual-anchor-without-external-research',
|
|
582
|
-
'visual-decisions-not-derived-from-conceptual-anchor',
|
|
583
|
-
'ai-safe-ui-template-look',
|
|
584
|
-
'interchangeable-product-renaming-test-fails',
|
|
585
|
-
'decorative-grid-or-glow-wallpaper-without-product-function',
|
|
586
|
-
'safe-cream-slate-or-monochrome-palette-used-as-readability-excuse',
|
|
587
|
-
'generic-abstract-logo-or-iconography',
|
|
588
|
-
'timid-anchor-that-renames-dashboard-or-admin-shell',
|
|
589
|
-
'motion-suppressed-without-accessibility-or-performance-reason',
|
|
590
|
-
'scale-only-responsive-layout',
|
|
591
|
-
'zero-based-redesign-kept-prior-visual-dna',
|
|
592
|
-
'restyle-instead-of-recomposition',
|
|
593
|
-
'single-safe-typographic-family-without-role-contrast-or-rationale',
|
|
594
|
-
],
|
|
595
|
-
validationHints: {
|
|
596
|
-
rejectArbitraryHexOnlyPalette: true,
|
|
597
|
-
requireViewportMutationRules: true,
|
|
598
|
-
requirePerceptualColorRationale: true,
|
|
599
|
-
requireTokenLayering: true,
|
|
600
|
-
requireTokenAliasingPlan: true,
|
|
601
|
-
allowHexDerivatives: true,
|
|
602
|
-
requireMotionRationale: true,
|
|
603
|
-
requireStateMorphology: true,
|
|
604
|
-
requireAccessibilitySplit: true,
|
|
605
|
-
requireWcagHardFloor: true,
|
|
606
|
-
requireStructuredDesignExecutionPolicy: true,
|
|
607
|
-
requireStructuredDesignHandoff: true,
|
|
608
|
-
requireVisualResetStrategyWhenZeroBasedRedesignRequested: true,
|
|
609
|
-
requireConceptualAnchorWhenNoExternalResearch: true,
|
|
610
|
-
requireAgentLedAnchorResearchWhenUserResearchMissing: true,
|
|
611
|
-
rejectTimidDashboardAnchor: true,
|
|
612
|
-
requireReviewRubric: true,
|
|
613
|
-
requireGenericityExplanation: true,
|
|
614
|
-
genericityAutoFail: true,
|
|
615
|
-
requireSignatureMove: true,
|
|
616
|
-
rejectTemplateNeutralLayout: true,
|
|
617
|
-
requireAiSafeUiAudit: true,
|
|
618
|
-
rejectAiSafeUiTemplateLook: true,
|
|
619
|
-
requireThreeProductSpecificSignals: true,
|
|
620
|
-
rejectDecorativeBackgroundPatternsWithoutProductFunction: true,
|
|
621
|
-
},
|
|
622
640
|
requiredDesignSections: DESIGN_REQUIRED_SECTIONS,
|
|
623
641
|
implementation: {
|
|
624
642
|
requiredDeliverables: ['docs/DESIGN.md', 'docs/design-intent.json'],
|
|
@@ -644,749 +662,7 @@ function buildDesignIntentContractObject({
|
|
|
644
662
|
};
|
|
645
663
|
}
|
|
646
664
|
|
|
647
|
-
|
|
648
|
-
return typeof value === 'string' && value.trim().length > 0;
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
export function validateDesignContractCompleteness(designIntentContract) {
|
|
652
|
-
const validationIssues = [];
|
|
653
|
-
const conceptualAnchor = designIntentContract?.conceptualAnchor;
|
|
654
|
-
const derivedTokenLogic = designIntentContract?.derivedTokenLogic;
|
|
655
|
-
const libraryDecisions = designIntentContract?.libraryDecisions;
|
|
656
|
-
|
|
657
|
-
const anchorReference = conceptualAnchor?.anchorReference || derivedTokenLogic?.anchorReference;
|
|
658
|
-
if (!hasNonEmptyString(anchorReference)) {
|
|
659
|
-
validationIssues.push('designIntent.conceptualAnchor.anchorReference must be a stable non-empty ID for deterministic validation.');
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
if (!derivedTokenLogic || typeof derivedTokenLogic !== 'object') {
|
|
663
|
-
validationIssues.push('designIntent.derivedTokenLogic must exist.');
|
|
664
|
-
} else {
|
|
665
|
-
if (derivedTokenLogic.anchorReference !== anchorReference) {
|
|
666
|
-
validationIssues.push('designIntent.derivedTokenLogic.anchorReference must exactly match designIntent.conceptualAnchor.anchorReference.');
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
for (const requiredFieldName of [
|
|
670
|
-
'colorDerivationSource',
|
|
671
|
-
'spacingDerivationSource',
|
|
672
|
-
'typographyDerivationSource',
|
|
673
|
-
'motionDerivationSource',
|
|
674
|
-
'validationRule',
|
|
675
|
-
]) {
|
|
676
|
-
if (!hasNonEmptyString(derivedTokenLogic[requiredFieldName])) {
|
|
677
|
-
validationIssues.push(`designIntent.derivedTokenLogic.${requiredFieldName} must be a non-empty string.`);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
if (
|
|
682
|
-
hasNonEmptyString(derivedTokenLogic.validationRule)
|
|
683
|
-
&& !derivedTokenLogic.validationRule.includes('anchorReference')
|
|
684
|
-
) {
|
|
685
|
-
validationIssues.push('designIntent.derivedTokenLogic.validationRule must require traceability to anchorReference.');
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
if (!['verified', 'pending-verification', 'no-external-library-needed'].includes(designIntentContract?.libraryResearchStatus)) {
|
|
690
|
-
validationIssues.push('designIntent.libraryResearchStatus must be verified, pending-verification, or no-external-library-needed.');
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
if (!Array.isArray(libraryDecisions)) {
|
|
694
|
-
validationIssues.push('designIntent.libraryDecisions must be an array.');
|
|
695
|
-
} else {
|
|
696
|
-
for (const [libraryIndex, libraryDecision] of libraryDecisions.entries()) {
|
|
697
|
-
if (!libraryDecision || typeof libraryDecision !== 'object') {
|
|
698
|
-
validationIssues.push(`designIntent.libraryDecisions[${libraryIndex}] must be an object.`);
|
|
699
|
-
continue;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
if (!hasNonEmptyString(libraryDecision.library)) {
|
|
703
|
-
validationIssues.push(`designIntent.libraryDecisions[${libraryIndex}].library must be a non-empty string.`);
|
|
704
|
-
}
|
|
705
|
-
if (!hasNonEmptyString(libraryDecision.purpose)) {
|
|
706
|
-
validationIssues.push(`designIntent.libraryDecisions[${libraryIndex}].purpose must be a non-empty string.`);
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
const hasVerification = hasNonEmptyString(libraryDecision.verifiedAt)
|
|
710
|
-
&& hasNonEmptyString(libraryDecision.sourceUrl);
|
|
711
|
-
const hasFallback = hasNonEmptyString(libraryDecision.fallbackIfUnavailable);
|
|
712
|
-
|
|
713
|
-
if (!hasVerification && !hasFallback) {
|
|
714
|
-
validationIssues.push(`designIntent.libraryDecisions[${libraryIndex}] must either record verification source or provide fallbackIfUnavailable.`);
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
return validationIssues;
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
export function validateDesignIntentContract(designIntentContract) {
|
|
723
|
-
const validationErrors = [];
|
|
724
|
-
|
|
725
|
-
if (!designIntentContract || typeof designIntentContract !== 'object') {
|
|
726
|
-
return ['Design intent contract must be an object.'];
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
validationErrors.push(...validateDesignContractCompleteness(designIntentContract));
|
|
730
|
-
|
|
731
|
-
if (designIntentContract.mode !== 'dynamic') {
|
|
732
|
-
validationErrors.push('designIntent.mode must equal "dynamic".');
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
if (!designIntentContract.project || typeof designIntentContract.project !== 'object') {
|
|
736
|
-
validationErrors.push('designIntent.project must exist.');
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
if (!designIntentContract.designPhilosophy || typeof designIntentContract.designPhilosophy !== 'string') {
|
|
740
|
-
validationErrors.push('designIntent.designPhilosophy must be a non-empty string.');
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
if (!designIntentContract.externalResearchIntake || typeof designIntentContract.externalResearchIntake !== 'object') {
|
|
744
|
-
validationErrors.push('designIntent.externalResearchIntake must exist.');
|
|
745
|
-
} else {
|
|
746
|
-
if (designIntentContract.externalResearchIntake.userSuppliedResearchPolicy !== 'read-as-candidate-evidence-not-final-prescription') {
|
|
747
|
-
validationErrors.push('designIntent.externalResearchIntake.userSuppliedResearchPolicy must preserve user research as candidate evidence.');
|
|
748
|
-
}
|
|
749
|
-
if (designIntentContract.externalResearchIntake.requireOfficialDocsVerificationForTechnologyClaims !== true) {
|
|
750
|
-
validationErrors.push('designIntent.externalResearchIntake.requireOfficialDocsVerificationForTechnologyClaims must equal true.');
|
|
751
|
-
}
|
|
752
|
-
if (
|
|
753
|
-
!Array.isArray(designIntentContract.externalResearchIntake.candidateDomains)
|
|
754
|
-
|| !designIntentContract.externalResearchIntake.candidateDomains.includes('motion-and-scroll')
|
|
755
|
-
) {
|
|
756
|
-
validationErrors.push('designIntent.externalResearchIntake.candidateDomains must include motion-and-scroll.');
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
if (!designIntentContract.conceptualAnchor || typeof designIntentContract.conceptualAnchor !== 'object') {
|
|
761
|
-
validationErrors.push('designIntent.conceptualAnchor must exist.');
|
|
762
|
-
} else {
|
|
763
|
-
const conceptualAnchor = designIntentContract.conceptualAnchor;
|
|
764
|
-
if (conceptualAnchor.mode !== 'required-when-no-external-research') {
|
|
765
|
-
validationErrors.push('designIntent.conceptualAnchor.mode must equal "required-when-no-external-research".');
|
|
766
|
-
}
|
|
767
|
-
if (conceptualAnchor.seedMode !== 'selection-policy-only') {
|
|
768
|
-
validationErrors.push('designIntent.conceptualAnchor.seedMode must equal "selection-policy-only".');
|
|
769
|
-
}
|
|
770
|
-
if (conceptualAnchor.requiresAgentSelectionBeforeUiImplementation !== true) {
|
|
771
|
-
validationErrors.push('designIntent.conceptualAnchor.requiresAgentSelectionBeforeUiImplementation must equal true.');
|
|
772
|
-
}
|
|
773
|
-
if (!hasNonEmptyString(conceptualAnchor.anchorReference)) {
|
|
774
|
-
validationErrors.push('designIntent.conceptualAnchor.anchorReference must be a stable non-empty ID.');
|
|
775
|
-
}
|
|
776
|
-
const userResearchAbsencePolicy = conceptualAnchor.userResearchAbsencePolicy;
|
|
777
|
-
if (!userResearchAbsencePolicy || typeof userResearchAbsencePolicy !== 'object') {
|
|
778
|
-
validationErrors.push('designIntent.conceptualAnchor.userResearchAbsencePolicy must exist.');
|
|
779
|
-
} else {
|
|
780
|
-
if (userResearchAbsencePolicy.userSuppliedResearchOnly !== true) {
|
|
781
|
-
validationErrors.push('designIntent.conceptualAnchor.userResearchAbsencePolicy.userSuppliedResearchOnly must equal true.');
|
|
782
|
-
}
|
|
783
|
-
if (userResearchAbsencePolicy.scaffoldSeedDoesNotCountAsResearch !== true) {
|
|
784
|
-
validationErrors.push('designIntent.conceptualAnchor.userResearchAbsencePolicy.scaffoldSeedDoesNotCountAsResearch must equal true.');
|
|
785
|
-
}
|
|
786
|
-
if (userResearchAbsencePolicy.priorUiDoesNotCountAsResearch !== true) {
|
|
787
|
-
validationErrors.push('designIntent.conceptualAnchor.userResearchAbsencePolicy.priorUiDoesNotCountAsResearch must equal true.');
|
|
788
|
-
}
|
|
789
|
-
if (userResearchAbsencePolicy.requireAgentLedResearchWhenAvailable !== true) {
|
|
790
|
-
validationErrors.push('designIntent.conceptualAnchor.userResearchAbsencePolicy.requireAgentLedResearchWhenAvailable must equal true.');
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
const candidateSelectionPolicy = conceptualAnchor.candidateSelectionPolicy;
|
|
794
|
-
if (!candidateSelectionPolicy || typeof candidateSelectionPolicy !== 'object') {
|
|
795
|
-
validationErrors.push('designIntent.conceptualAnchor.candidateSelectionPolicy must exist.');
|
|
796
|
-
} else {
|
|
797
|
-
if (candidateSelectionPolicy.considerAtLeast < 3) {
|
|
798
|
-
validationErrors.push('designIntent.conceptualAnchor.candidateSelectionPolicy.considerAtLeast must be at least 3.');
|
|
799
|
-
}
|
|
800
|
-
if (candidateSelectionPolicy.discardObviousCandidateCount < 2) {
|
|
801
|
-
validationErrors.push('designIntent.conceptualAnchor.candidateSelectionPolicy.discardObviousCandidateCount must be at least 2.');
|
|
802
|
-
}
|
|
803
|
-
if (candidateSelectionPolicy.minimumCandidateDistance !== 'high') {
|
|
804
|
-
validationErrors.push('designIntent.conceptualAnchor.candidateSelectionPolicy.minimumCandidateDistance must equal "high".');
|
|
805
|
-
}
|
|
806
|
-
if (candidateSelectionPolicy.discardPredictableCandidates !== true) {
|
|
807
|
-
validationErrors.push('designIntent.conceptualAnchor.candidateSelectionPolicy.discardPredictableCandidates must equal true.');
|
|
808
|
-
}
|
|
809
|
-
if (candidateSelectionPolicy.preferDistinctiveOverSafe !== true) {
|
|
810
|
-
validationErrors.push('designIntent.conceptualAnchor.candidateSelectionPolicy.preferDistinctiveOverSafe must equal true.');
|
|
811
|
-
}
|
|
812
|
-
if (candidateSelectionPolicy.doNotRevealHiddenCandidateList !== true) {
|
|
813
|
-
validationErrors.push('designIntent.conceptualAnchor.candidateSelectionPolicy.doNotRevealHiddenCandidateList must equal true.');
|
|
814
|
-
}
|
|
815
|
-
if (candidateSelectionPolicy.outputOnlyChosenAnchor !== true) {
|
|
816
|
-
validationErrors.push('designIntent.conceptualAnchor.candidateSelectionPolicy.outputOnlyChosenAnchor must equal true.');
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
const creativeCommitmentPolicy = conceptualAnchor.creativeCommitmentPolicy;
|
|
820
|
-
if (!creativeCommitmentPolicy || typeof creativeCommitmentPolicy !== 'object') {
|
|
821
|
-
validationErrors.push('designIntent.conceptualAnchor.creativeCommitmentPolicy must exist.');
|
|
822
|
-
} else {
|
|
823
|
-
if (creativeCommitmentPolicy.requiredBeforeComplianceReview !== true) {
|
|
824
|
-
validationErrors.push('designIntent.conceptualAnchor.creativeCommitmentPolicy.requiredBeforeComplianceReview must equal true.');
|
|
825
|
-
}
|
|
826
|
-
if (creativeCommitmentPolicy.recordInDesignDocs !== true) {
|
|
827
|
-
validationErrors.push('designIntent.conceptualAnchor.creativeCommitmentPolicy.recordInDesignDocs must equal true.');
|
|
828
|
-
}
|
|
829
|
-
if (
|
|
830
|
-
!Array.isArray(creativeCommitmentPolicy.requiredCommitmentFields)
|
|
831
|
-
|| !creativeCommitmentPolicy.requiredCommitmentFields.includes('specificReferencePoint')
|
|
832
|
-
|| !creativeCommitmentPolicy.requiredCommitmentFields.includes('signatureMotion')
|
|
833
|
-
|| !creativeCommitmentPolicy.requiredCommitmentFields.includes('typographicDecision')
|
|
834
|
-
) {
|
|
835
|
-
validationErrors.push('designIntent.conceptualAnchor.creativeCommitmentPolicy.requiredCommitmentFields must include specificReferencePoint, signatureMotion, and typographicDecision.');
|
|
836
|
-
}
|
|
837
|
-
if (creativeCommitmentPolicy.rejectGenericQualityWordsOnly !== true) {
|
|
838
|
-
validationErrors.push('designIntent.conceptualAnchor.creativeCommitmentPolicy.rejectGenericQualityWordsOnly must equal true.');
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
if (
|
|
842
|
-
!Array.isArray(conceptualAnchor.forbiddenFinalAnchorTerms)
|
|
843
|
-
|| !conceptualAnchor.forbiddenFinalAnchorTerms.includes('dashboard')
|
|
844
|
-
|| !conceptualAnchor.forbiddenFinalAnchorTerms.includes('cards')
|
|
845
|
-
|| !conceptualAnchor.forbiddenFinalAnchorTerms.includes('safe-admin-layout')
|
|
846
|
-
) {
|
|
847
|
-
validationErrors.push('designIntent.conceptualAnchor.forbiddenFinalAnchorTerms must reject basic UI labels.');
|
|
848
|
-
}
|
|
849
|
-
if (
|
|
850
|
-
!Array.isArray(conceptualAnchor.sourceDomains)
|
|
851
|
-
|| conceptualAnchor.sourceDomains.length < 4
|
|
852
|
-
|| !conceptualAnchor.sourceDomains.includes('complex-physical-engineering')
|
|
853
|
-
|| !conceptualAnchor.sourceDomains.includes('cinematic-spatial-interface')
|
|
854
|
-
|| !conceptualAnchor.sourceDomains.includes('premium-interactive-web-experiences')
|
|
855
|
-
) {
|
|
856
|
-
validationErrors.push('designIntent.conceptualAnchor.sourceDomains must list broad non-template anchor domains.');
|
|
857
|
-
}
|
|
858
|
-
const visualRiskBudget = conceptualAnchor.visualRiskBudget;
|
|
859
|
-
if (!visualRiskBudget || typeof visualRiskBudget !== 'object') {
|
|
860
|
-
validationErrors.push('designIntent.conceptualAnchor.visualRiskBudget must exist.');
|
|
861
|
-
} else {
|
|
862
|
-
if (visualRiskBudget.mode !== 'high-distinctiveness-with-accessibility-and-performance-guardrails') {
|
|
863
|
-
validationErrors.push('designIntent.conceptualAnchor.visualRiskBudget.mode must preserve high-distinctiveness guardrails.');
|
|
864
|
-
}
|
|
865
|
-
if (visualRiskBudget.allowRichMotionAndMicroInteraction !== true) {
|
|
866
|
-
validationErrors.push('designIntent.conceptualAnchor.visualRiskBudget.allowRichMotionAndMicroInteraction must equal true.');
|
|
867
|
-
}
|
|
868
|
-
if (visualRiskBudget.rejectTimidDefaultWhenAnchorSupportsExpressiveUi !== true) {
|
|
869
|
-
validationErrors.push('designIntent.conceptualAnchor.visualRiskBudget.rejectTimidDefaultWhenAnchorSupportsExpressiveUi must equal true.');
|
|
870
|
-
}
|
|
871
|
-
if (visualRiskBudget.requireReducedMotionFallback !== true) {
|
|
872
|
-
validationErrors.push('designIntent.conceptualAnchor.visualRiskBudget.requireReducedMotionFallback must equal true.');
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
if (
|
|
876
|
-
!Array.isArray(conceptualAnchor.requiredDerivedAxes)
|
|
877
|
-
|| !conceptualAnchor.requiredDerivedAxes.includes('typography')
|
|
878
|
-
|| !conceptualAnchor.requiredDerivedAxes.includes('responsive-composition')
|
|
879
|
-
) {
|
|
880
|
-
validationErrors.push('designIntent.conceptualAnchor.requiredDerivedAxes must include typography and responsive-composition.');
|
|
881
|
-
}
|
|
882
|
-
const finalAnchorContract = conceptualAnchor.finalAnchorContract;
|
|
883
|
-
if (!finalAnchorContract || typeof finalAnchorContract !== 'object') {
|
|
884
|
-
validationErrors.push('designIntent.conceptualAnchor.finalAnchorContract must exist.');
|
|
885
|
-
} else {
|
|
886
|
-
if (
|
|
887
|
-
!Array.isArray(finalAnchorContract.requiredFields)
|
|
888
|
-
|| !finalAnchorContract.requiredFields.includes('anchorReference')
|
|
889
|
-
|| !finalAnchorContract.requiredFields.includes('agentResearchMode')
|
|
890
|
-
|| !finalAnchorContract.requiredFields.includes('specificReferencePoint')
|
|
891
|
-
|| !finalAnchorContract.requiredFields.includes('signatureMotion')
|
|
892
|
-
|| !finalAnchorContract.requiredFields.includes('typographicDecision')
|
|
893
|
-
|| !finalAnchorContract.requiredFields.includes('derivedTokenLogic')
|
|
894
|
-
|| !finalAnchorContract.requiredFields.includes('visualRiskBudget')
|
|
895
|
-
|| !finalAnchorContract.requiredFields.includes('motionRiskBudget')
|
|
896
|
-
|| !finalAnchorContract.requiredFields.includes('cohesionChecks')
|
|
897
|
-
) {
|
|
898
|
-
validationErrors.push('designIntent.conceptualAnchor.finalAnchorContract.requiredFields must require anchorReference, agentResearchMode, specificReferencePoint, signatureMotion, typographicDecision, derivedTokenLogic, visualRiskBudget, motionRiskBudget, and cohesionChecks.');
|
|
899
|
-
}
|
|
900
|
-
if (
|
|
901
|
-
!Array.isArray(finalAnchorContract.derivedTokenLogicAxes)
|
|
902
|
-
|| !finalAnchorContract.derivedTokenLogicAxes.includes('motion')
|
|
903
|
-
|| !finalAnchorContract.derivedTokenLogicAxes.includes('morphology')
|
|
904
|
-
) {
|
|
905
|
-
validationErrors.push('designIntent.conceptualAnchor.finalAnchorContract.derivedTokenLogicAxes must include motion and morphology.');
|
|
906
|
-
}
|
|
907
|
-
if (
|
|
908
|
-
!Array.isArray(finalAnchorContract.cohesionChecks)
|
|
909
|
-
|| !finalAnchorContract.cohesionChecks.includes('no-dashboard-mental-model')
|
|
910
|
-
|| !finalAnchorContract.cohesionChecks.includes('motion-derived-from-anchor')
|
|
911
|
-
) {
|
|
912
|
-
validationErrors.push('designIntent.conceptualAnchor.finalAnchorContract.cohesionChecks must reject dashboard mental models and require motion derivation.');
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
if (!designIntentContract.mathSystems || typeof designIntentContract.mathSystems !== 'object') {
|
|
918
|
-
validationErrors.push('designIntent.mathSystems must exist.');
|
|
919
|
-
} else {
|
|
920
|
-
if (!String(designIntentContract.mathSystems.typographyScaleRatio || '').trim()) {
|
|
921
|
-
validationErrors.push('designIntent.mathSystems.typographyScaleRatio must describe the chosen or pending type scale decision.');
|
|
922
|
-
}
|
|
923
|
-
if (!String(designIntentContract.mathSystems.baseGridUnit || '').trim()) {
|
|
924
|
-
validationErrors.push('designIntent.mathSystems.baseGridUnit must describe the chosen or pending spacing grid decision.');
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
if (!designIntentContract.aiSafeUiAudit || typeof designIntentContract.aiSafeUiAudit !== 'object') {
|
|
929
|
-
validationErrors.push('designIntent.aiSafeUiAudit must exist.');
|
|
930
|
-
} else {
|
|
931
|
-
const aiSafeUiAudit = designIntentContract.aiSafeUiAudit;
|
|
932
|
-
if (aiSafeUiAudit.status !== 'agent-must-complete-before-ui-implementation') {
|
|
933
|
-
validationErrors.push('designIntent.aiSafeUiAudit.status must require completion before UI implementation.');
|
|
934
|
-
}
|
|
935
|
-
if (!String(aiSafeUiAudit.failureDefinition || '').includes('AI-safe')) {
|
|
936
|
-
validationErrors.push('designIntent.aiSafeUiAudit.failureDefinition must define AI-safe UI drift.');
|
|
937
|
-
}
|
|
938
|
-
if (!String(aiSafeUiAudit.interchangeabilityTest || '').includes('renamed')) {
|
|
939
|
-
validationErrors.push('designIntent.aiSafeUiAudit.interchangeabilityTest must include the rename/interchangeability test.');
|
|
940
|
-
}
|
|
941
|
-
if (!Array.isArray(aiSafeUiAudit.requiredProductSpecificSignals) || aiSafeUiAudit.requiredProductSpecificSignals.length < 3) {
|
|
942
|
-
validationErrors.push('designIntent.aiSafeUiAudit.requiredProductSpecificSignals must list at least three product-specific signals.');
|
|
943
|
-
}
|
|
944
|
-
if (!String(aiSafeUiAudit.paletteExplorationRule || '').trim()) {
|
|
945
|
-
validationErrors.push('designIntent.aiSafeUiAudit.paletteExplorationRule must be a non-empty string.');
|
|
946
|
-
}
|
|
947
|
-
if (!String(aiSafeUiAudit.backgroundPatternRule || '').trim()) {
|
|
948
|
-
validationErrors.push('designIntent.aiSafeUiAudit.backgroundPatternRule must be a non-empty string.');
|
|
949
|
-
}
|
|
950
|
-
if (!String(aiSafeUiAudit.reviewQuestion || '').trim()) {
|
|
951
|
-
validationErrors.push('designIntent.aiSafeUiAudit.reviewQuestion must be a non-empty string.');
|
|
952
|
-
}
|
|
953
|
-
if (aiSafeUiAudit.blockingByDefault !== true) {
|
|
954
|
-
validationErrors.push('designIntent.aiSafeUiAudit.blockingByDefault must equal true.');
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
if (!designIntentContract.tokenSystem || typeof designIntentContract.tokenSystem !== 'object') {
|
|
959
|
-
validationErrors.push('designIntent.tokenSystem must exist.');
|
|
960
|
-
} else {
|
|
961
|
-
const taxonomyOrder = designIntentContract.tokenSystem.taxonomyOrder;
|
|
962
|
-
if (!Array.isArray(taxonomyOrder) || taxonomyOrder.join('|') !== 'primitive|semantic|component') {
|
|
963
|
-
validationErrors.push('designIntent.tokenSystem.taxonomyOrder must equal ["primitive","semantic","component"].');
|
|
964
|
-
}
|
|
965
|
-
if (designIntentContract.tokenSystem.primitiveColorSpace !== 'OKLCH') {
|
|
966
|
-
validationErrors.push('designIntent.tokenSystem.primitiveColorSpace must equal "OKLCH".');
|
|
967
|
-
}
|
|
968
|
-
if (designIntentContract.tokenSystem.requireSemanticAliases !== true) {
|
|
969
|
-
validationErrors.push('designIntent.tokenSystem.requireSemanticAliases must equal true.');
|
|
970
|
-
}
|
|
971
|
-
if (designIntentContract.tokenSystem.semanticAliasesMutableWithoutComponentRewrite !== true) {
|
|
972
|
-
validationErrors.push('designIntent.tokenSystem.semanticAliasesMutableWithoutComponentRewrite must equal true.');
|
|
973
|
-
}
|
|
974
|
-
if (designIntentContract.tokenSystem.componentTokensConsumeSemantic !== true) {
|
|
975
|
-
validationErrors.push('designIntent.tokenSystem.componentTokensConsumeSemantic must equal true.');
|
|
976
|
-
}
|
|
977
|
-
const fallbackPolicy = designIntentContract.tokenSystem.fallbackPolicy;
|
|
978
|
-
if (!fallbackPolicy || typeof fallbackPolicy !== 'object') {
|
|
979
|
-
validationErrors.push('designIntent.tokenSystem.fallbackPolicy must exist.');
|
|
980
|
-
} else {
|
|
981
|
-
if (fallbackPolicy.forbidRawHexOutsidePrimitives !== true) {
|
|
982
|
-
validationErrors.push('designIntent.tokenSystem.fallbackPolicy.forbidRawHexOutsidePrimitives must equal true.');
|
|
983
|
-
}
|
|
984
|
-
if (fallbackPolicy.forbidRawSpacingOutsidePrimitives !== true) {
|
|
985
|
-
validationErrors.push('designIntent.tokenSystem.fallbackPolicy.forbidRawSpacingOutsidePrimitives must equal true.');
|
|
986
|
-
}
|
|
987
|
-
if (fallbackPolicy.requireDocumentedExceptionForLegacyBypass !== true) {
|
|
988
|
-
validationErrors.push('designIntent.tokenSystem.fallbackPolicy.requireDocumentedExceptionForLegacyBypass must equal true.');
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
const namingConstraints = designIntentContract.tokenSystem.namingConstraints;
|
|
992
|
-
if (!namingConstraints || typeof namingConstraints !== 'object') {
|
|
993
|
-
validationErrors.push('designIntent.tokenSystem.namingConstraints must exist.');
|
|
994
|
-
} else {
|
|
995
|
-
if (namingConstraints.forbidCurlyBracesInNames !== true) {
|
|
996
|
-
validationErrors.push('designIntent.tokenSystem.namingConstraints.forbidCurlyBracesInNames must equal true.');
|
|
997
|
-
}
|
|
998
|
-
if (namingConstraints.forbidDotsInNames !== true) {
|
|
999
|
-
validationErrors.push('designIntent.tokenSystem.namingConstraints.forbidDotsInNames must equal true.');
|
|
1000
|
-
}
|
|
1001
|
-
if (namingConstraints.forbidSquareBracketsInNames !== true) {
|
|
1002
|
-
validationErrors.push('designIntent.tokenSystem.namingConstraints.forbidSquareBracketsInNames must equal true.');
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
if (!designIntentContract.colorTruth || typeof designIntentContract.colorTruth !== 'object') {
|
|
1008
|
-
validationErrors.push('designIntent.colorTruth must exist.');
|
|
1009
|
-
} else {
|
|
1010
|
-
if (designIntentContract.colorTruth.format !== 'OKLCH') {
|
|
1011
|
-
validationErrors.push('designIntent.colorTruth.format must equal "OKLCH".');
|
|
1012
|
-
}
|
|
1013
|
-
if (designIntentContract.colorTruth.allowHexDerivatives !== true) {
|
|
1014
|
-
validationErrors.push('designIntent.colorTruth.allowHexDerivatives must equal true.');
|
|
1015
|
-
}
|
|
1016
|
-
if (!String(designIntentContract.colorTruth.intent || '').trim()) {
|
|
1017
|
-
validationErrors.push('designIntent.colorTruth.intent must be a non-empty string.');
|
|
1018
|
-
}
|
|
1019
|
-
const paletteRoles = designIntentContract.colorTruth.paletteRoles;
|
|
1020
|
-
if (!Array.isArray(paletteRoles) || paletteRoles.length < 1) {
|
|
1021
|
-
validationErrors.push('designIntent.colorTruth.paletteRoles must define or request agent-defined semantic palette roles.');
|
|
1022
|
-
}
|
|
1023
|
-
if (designIntentContract.colorTruth.rolesMustBeAgentDefined !== true) {
|
|
1024
|
-
validationErrors.push('designIntent.colorTruth.rolesMustBeAgentDefined must equal true.');
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
if (!designIntentContract.crossViewportAdaptation || typeof designIntentContract.crossViewportAdaptation !== 'object') {
|
|
1029
|
-
validationErrors.push('designIntent.crossViewportAdaptation must exist.');
|
|
1030
|
-
} else {
|
|
1031
|
-
const mutationRules = designIntentContract.crossViewportAdaptation.mutationRules;
|
|
1032
|
-
if (!mutationRules || typeof mutationRules !== 'object') {
|
|
1033
|
-
validationErrors.push('designIntent.crossViewportAdaptation.mutationRules must exist.');
|
|
1034
|
-
} else {
|
|
1035
|
-
for (const viewportKey of ['mobile', 'tablet', 'desktop']) {
|
|
1036
|
-
if (!String(mutationRules[viewportKey] || '').trim()) {
|
|
1037
|
-
validationErrors.push(`designIntent.crossViewportAdaptation.mutationRules.${viewportKey} must be a non-empty string.`);
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
if (!designIntentContract.motionSystem || typeof designIntentContract.motionSystem !== 'object') {
|
|
1044
|
-
validationErrors.push('designIntent.motionSystem must exist.');
|
|
1045
|
-
} else {
|
|
1046
|
-
if (designIntentContract.motionSystem.allowMeaningfulMotion !== true) {
|
|
1047
|
-
validationErrors.push('designIntent.motionSystem.allowMeaningfulMotion must equal true.');
|
|
1048
|
-
}
|
|
1049
|
-
if (!String(designIntentContract.motionSystem.purpose || '').trim()) {
|
|
1050
|
-
validationErrors.push('designIntent.motionSystem.purpose must be a non-empty string.');
|
|
1051
|
-
}
|
|
1052
|
-
if (designIntentContract.motionSystem.respectReducedMotion !== true) {
|
|
1053
|
-
validationErrors.push('designIntent.motionSystem.respectReducedMotion must equal true.');
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
if (!designIntentContract.componentMorphology || typeof designIntentContract.componentMorphology !== 'object') {
|
|
1058
|
-
validationErrors.push('designIntent.componentMorphology must exist.');
|
|
1059
|
-
} else {
|
|
1060
|
-
if (designIntentContract.componentMorphology.requireStateBehaviorMatrix !== true) {
|
|
1061
|
-
validationErrors.push('designIntent.componentMorphology.requireStateBehaviorMatrix must equal true.');
|
|
1062
|
-
}
|
|
1063
|
-
if (!Array.isArray(designIntentContract.componentMorphology.stateKeys) || designIntentContract.componentMorphology.stateKeys.length < 4) {
|
|
1064
|
-
validationErrors.push('designIntent.componentMorphology.stateKeys must contain multiple interaction states.');
|
|
1065
|
-
}
|
|
1066
|
-
const viewportBehavior = designIntentContract.componentMorphology.viewportBehavior;
|
|
1067
|
-
if (!viewportBehavior || typeof viewportBehavior !== 'object') {
|
|
1068
|
-
validationErrors.push('designIntent.componentMorphology.viewportBehavior must exist.');
|
|
1069
|
-
} else {
|
|
1070
|
-
for (const viewportKey of ['mobile', 'tablet', 'desktop']) {
|
|
1071
|
-
if (!String(viewportBehavior[viewportKey] || '').trim()) {
|
|
1072
|
-
validationErrors.push(`designIntent.componentMorphology.viewportBehavior.${viewportKey} must be a non-empty string.`);
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
if (!designIntentContract.accessibilityPolicy || typeof designIntentContract.accessibilityPolicy !== 'object') {
|
|
1079
|
-
validationErrors.push('designIntent.accessibilityPolicy must exist.');
|
|
1080
|
-
} else {
|
|
1081
|
-
if (designIntentContract.accessibilityPolicy.hardComplianceFloor !== 'WCAG-2.2-AA') {
|
|
1082
|
-
validationErrors.push('designIntent.accessibilityPolicy.hardComplianceFloor must equal "WCAG-2.2-AA".');
|
|
1083
|
-
}
|
|
1084
|
-
if (designIntentContract.accessibilityPolicy.advisoryContrastModel !== 'APCA') {
|
|
1085
|
-
validationErrors.push('designIntent.accessibilityPolicy.advisoryContrastModel must equal "APCA".');
|
|
1086
|
-
}
|
|
1087
|
-
if (designIntentContract.accessibilityPolicy.failOnHardViolations !== true) {
|
|
1088
|
-
validationErrors.push('designIntent.accessibilityPolicy.failOnHardViolations must equal true.');
|
|
1089
|
-
}
|
|
1090
|
-
if (designIntentContract.accessibilityPolicy.advisoryFindingsDoNotBlockByDefault !== true) {
|
|
1091
|
-
validationErrors.push('designIntent.accessibilityPolicy.advisoryFindingsDoNotBlockByDefault must equal true.');
|
|
1092
|
-
}
|
|
1093
|
-
const hardRequirements = designIntentContract.accessibilityPolicy.hardRequirements;
|
|
1094
|
-
if (!hardRequirements || typeof hardRequirements !== 'object') {
|
|
1095
|
-
validationErrors.push('designIntent.accessibilityPolicy.hardRequirements must exist.');
|
|
1096
|
-
} else {
|
|
1097
|
-
for (const requirementKey of [
|
|
1098
|
-
'textContrastMinimum',
|
|
1099
|
-
'nonTextContrast',
|
|
1100
|
-
'useOfColorOnlyProhibited',
|
|
1101
|
-
'focusVisible',
|
|
1102
|
-
'focusAppearance',
|
|
1103
|
-
'targetSizeMinimum',
|
|
1104
|
-
'keyboardAccess',
|
|
1105
|
-
'reflowRequired',
|
|
1106
|
-
'accessibleAuthenticationMinimum',
|
|
1107
|
-
'statusMessagesAndDynamicStateAccess',
|
|
1108
|
-
]) {
|
|
1109
|
-
if (hardRequirements[requirementKey] !== true) {
|
|
1110
|
-
validationErrors.push(`designIntent.accessibilityPolicy.hardRequirements.${requirementKey} must equal true.`);
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
const advisoryChecks = designIntentContract.accessibilityPolicy.advisoryChecks;
|
|
1115
|
-
if (!advisoryChecks || typeof advisoryChecks !== 'object') {
|
|
1116
|
-
validationErrors.push('designIntent.accessibilityPolicy.advisoryChecks must exist.');
|
|
1117
|
-
} else {
|
|
1118
|
-
for (const advisoryKey of [
|
|
1119
|
-
'perceptualContrastReview',
|
|
1120
|
-
'darkModeContrastTuning',
|
|
1121
|
-
'typographyReadabilityTuning',
|
|
1122
|
-
]) {
|
|
1123
|
-
if (advisoryChecks[advisoryKey] !== true) {
|
|
1124
|
-
validationErrors.push(`designIntent.accessibilityPolicy.advisoryChecks.${advisoryKey} must equal true.`);
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
if (!designIntentContract.contextHygiene || typeof designIntentContract.contextHygiene !== 'object') {
|
|
1131
|
-
validationErrors.push('designIntent.contextHygiene must exist.');
|
|
1132
|
-
} else {
|
|
1133
|
-
if (designIntentContract.contextHygiene.continuityMode !== 'opt-in-only') {
|
|
1134
|
-
validationErrors.push('designIntent.contextHygiene.continuityMode must equal "opt-in-only".');
|
|
1135
|
-
}
|
|
1136
|
-
if (designIntentContract.contextHygiene.repoEvidenceOverridesMemory !== true) {
|
|
1137
|
-
validationErrors.push('designIntent.contextHygiene.repoEvidenceOverridesMemory must equal true.');
|
|
1138
|
-
}
|
|
1139
|
-
if (designIntentContract.contextHygiene.requireExplicitContinuityApproval !== true) {
|
|
1140
|
-
validationErrors.push('designIntent.contextHygiene.requireExplicitContinuityApproval must equal true.');
|
|
1141
|
-
}
|
|
1142
|
-
if (designIntentContract.contextHygiene.forbidCarryoverWhenUnapproved !== true) {
|
|
1143
|
-
validationErrors.push('designIntent.contextHygiene.forbidCarryoverWhenUnapproved must equal true.');
|
|
1144
|
-
}
|
|
1145
|
-
if (!Array.isArray(designIntentContract.contextHygiene.allowedSources) || designIntentContract.contextHygiene.allowedSources.length < 4) {
|
|
1146
|
-
validationErrors.push('designIntent.contextHygiene.allowedSources must list the approved design evidence sources.');
|
|
1147
|
-
}
|
|
1148
|
-
if (!Array.isArray(designIntentContract.contextHygiene.taintedSources) || designIntentContract.contextHygiene.taintedSources.length < 3) {
|
|
1149
|
-
validationErrors.push('designIntent.contextHygiene.taintedSources must list tainted carryover sources.');
|
|
1150
|
-
}
|
|
1151
|
-
if (!String(designIntentContract.contextHygiene.approvedExternalConstraintUsage || '').trim()) {
|
|
1152
|
-
validationErrors.push('designIntent.contextHygiene.approvedExternalConstraintUsage must be a non-empty string.');
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
if (!designIntentContract.designExecutionPolicy || typeof designIntentContract.designExecutionPolicy !== 'object') {
|
|
1157
|
-
validationErrors.push('designIntent.designExecutionPolicy must exist.');
|
|
1158
|
-
} else {
|
|
1159
|
-
if (designIntentContract.designExecutionPolicy.representationStrategy !== 'surface-plan-v1') {
|
|
1160
|
-
validationErrors.push('designIntent.designExecutionPolicy.representationStrategy must equal "surface-plan-v1".');
|
|
1161
|
-
}
|
|
1162
|
-
for (const requiredFlagName of [
|
|
1163
|
-
'requireSurfacePlan',
|
|
1164
|
-
'requireComponentGraph',
|
|
1165
|
-
'requireViewportMutationPlan',
|
|
1166
|
-
'requireInteractionStateMatrix',
|
|
1167
|
-
'requireContentPriorityMap',
|
|
1168
|
-
'requireTaskFlowNarrative',
|
|
1169
|
-
'requireSignatureMoveRationale',
|
|
1170
|
-
'requireCreativeCommitmentGate',
|
|
1171
|
-
'requireStructuredHandoff',
|
|
1172
|
-
'requireRepoEvidenceAlignment',
|
|
1173
|
-
'forbidScreenshotDependency',
|
|
1174
|
-
'requirePerSurfaceMutationOps',
|
|
1175
|
-
'forbidUniformSiblingSurfaceTreatment',
|
|
1176
|
-
'zeroBasedRedesignResetsPriorVisualsWhenRequested',
|
|
1177
|
-
]) {
|
|
1178
|
-
if (designIntentContract.designExecutionPolicy[requiredFlagName] !== true) {
|
|
1179
|
-
validationErrors.push(`designIntent.designExecutionPolicy.${requiredFlagName} must equal true.`);
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
if (designIntentContract.designExecutionPolicy.handoffFormatVersion !== 'ui-handoff-v1') {
|
|
1183
|
-
validationErrors.push('designIntent.designExecutionPolicy.handoffFormatVersion must equal "ui-handoff-v1".');
|
|
1184
|
-
}
|
|
1185
|
-
if (
|
|
1186
|
-
!Array.isArray(designIntentContract.designExecutionPolicy.semanticReviewFocus)
|
|
1187
|
-
|| designIntentContract.designExecutionPolicy.semanticReviewFocus.length < 4
|
|
1188
|
-
) {
|
|
1189
|
-
validationErrors.push('designIntent.designExecutionPolicy.semanticReviewFocus must list the required review dimensions.');
|
|
1190
|
-
}
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
if (!designIntentContract.designExecutionHandoff || typeof designIntentContract.designExecutionHandoff !== 'object') {
|
|
1194
|
-
validationErrors.push('designIntent.designExecutionHandoff must exist.');
|
|
1195
|
-
} else {
|
|
1196
|
-
if (designIntentContract.designExecutionHandoff.version !== 'ui-handoff-v1') {
|
|
1197
|
-
validationErrors.push('designIntent.designExecutionHandoff.version must equal "ui-handoff-v1".');
|
|
1198
|
-
}
|
|
1199
|
-
if (designIntentContract.designExecutionHandoff.seedMode !== 'structure-first-scaffold') {
|
|
1200
|
-
validationErrors.push('designIntent.designExecutionHandoff.seedMode must equal "structure-first-scaffold".');
|
|
1201
|
-
}
|
|
1202
|
-
if (designIntentContract.designExecutionHandoff.requiresTaskSpecificRefinement !== true) {
|
|
1203
|
-
validationErrors.push('designIntent.designExecutionHandoff.requiresTaskSpecificRefinement must equal true.');
|
|
1204
|
-
}
|
|
1205
|
-
if (!String(designIntentContract.designExecutionHandoff.primaryExperienceGoal || '').trim()) {
|
|
1206
|
-
validationErrors.push('designIntent.designExecutionHandoff.primaryExperienceGoal must be a non-empty string.');
|
|
1207
|
-
}
|
|
1208
|
-
if (!Array.isArray(designIntentContract.designExecutionHandoff.surfacePlan) || designIntentContract.designExecutionHandoff.surfacePlan.length < 1) {
|
|
1209
|
-
validationErrors.push('designIntent.designExecutionHandoff.surfacePlan must define at least one planned surface.');
|
|
1210
|
-
}
|
|
1211
|
-
const componentGraph = designIntentContract.designExecutionHandoff.componentGraph;
|
|
1212
|
-
if (!componentGraph || typeof componentGraph !== 'object') {
|
|
1213
|
-
validationErrors.push('designIntent.designExecutionHandoff.componentGraph must exist.');
|
|
1214
|
-
} else {
|
|
1215
|
-
if (!Array.isArray(componentGraph.nodes) || componentGraph.nodes.length < 2) {
|
|
1216
|
-
validationErrors.push('designIntent.designExecutionHandoff.componentGraph.nodes must list the primary execution nodes.');
|
|
1217
|
-
}
|
|
1218
|
-
if (!Array.isArray(componentGraph.edges) || componentGraph.edges.length < 1) {
|
|
1219
|
-
validationErrors.push('designIntent.designExecutionHandoff.componentGraph.edges must define relationships between UI nodes.');
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
const contentPriorityMap = designIntentContract.designExecutionHandoff.contentPriorityMap;
|
|
1223
|
-
if (!contentPriorityMap || typeof contentPriorityMap !== 'object') {
|
|
1224
|
-
validationErrors.push('designIntent.designExecutionHandoff.contentPriorityMap must exist.');
|
|
1225
|
-
} else {
|
|
1226
|
-
for (const priorityBucket of ['primary', 'secondary', 'deferred']) {
|
|
1227
|
-
if (!Array.isArray(contentPriorityMap[priorityBucket]) || contentPriorityMap[priorityBucket].length < 1) {
|
|
1228
|
-
validationErrors.push(`designIntent.designExecutionHandoff.contentPriorityMap.${priorityBucket} must contain at least one item.`);
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
const viewportMutationPlan = designIntentContract.designExecutionHandoff.viewportMutationPlan;
|
|
1233
|
-
if (!viewportMutationPlan || typeof viewportMutationPlan !== 'object') {
|
|
1234
|
-
validationErrors.push('designIntent.designExecutionHandoff.viewportMutationPlan must exist.');
|
|
1235
|
-
} else {
|
|
1236
|
-
for (const viewportKey of ['mobile', 'tablet', 'desktop']) {
|
|
1237
|
-
const viewportPlan = viewportMutationPlan[viewportKey];
|
|
1238
|
-
if (!viewportPlan || typeof viewportPlan !== 'object') {
|
|
1239
|
-
validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey} must be an object.`);
|
|
1240
|
-
continue;
|
|
1241
|
-
}
|
|
1242
|
-
if (!String(viewportPlan.primaryOperation || '').trim()) {
|
|
1243
|
-
validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey}.primaryOperation must be a non-empty string.`);
|
|
1244
|
-
}
|
|
1245
|
-
if (!Array.isArray(viewportPlan.requiredSurfaceActions) || viewportPlan.requiredSurfaceActions.length < 2) {
|
|
1246
|
-
validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey}.requiredSurfaceActions must contain at least two actions.`);
|
|
1247
|
-
}
|
|
1248
|
-
if (!Array.isArray(viewportPlan.forbiddenPatterns) || viewportPlan.forbiddenPatterns.length < 1) {
|
|
1249
|
-
validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey}.forbiddenPatterns must contain at least one anti-pattern.`);
|
|
1250
|
-
}
|
|
1251
|
-
if (!String(viewportPlan.rationale || '').trim()) {
|
|
1252
|
-
validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey}.rationale must be a non-empty string.`);
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
if (!Array.isArray(designIntentContract.designExecutionHandoff.interactionStateMatrix) || designIntentContract.designExecutionHandoff.interactionStateMatrix.length < 1) {
|
|
1257
|
-
validationErrors.push('designIntent.designExecutionHandoff.interactionStateMatrix must list key component state expectations.');
|
|
1258
|
-
}
|
|
1259
|
-
if (!Array.isArray(designIntentContract.designExecutionHandoff.taskFlowNarrative) || designIntentContract.designExecutionHandoff.taskFlowNarrative.length < 2) {
|
|
1260
|
-
validationErrors.push('designIntent.designExecutionHandoff.taskFlowNarrative must describe the key UI task flow in sequence.');
|
|
1261
|
-
}
|
|
1262
|
-
if (!String(designIntentContract.designExecutionHandoff.signatureMoveRationale || '').trim()) {
|
|
1263
|
-
validationErrors.push('designIntent.designExecutionHandoff.signatureMoveRationale must explain the chosen authored move.');
|
|
1264
|
-
}
|
|
1265
|
-
const creativeCommitment = designIntentContract.designExecutionHandoff.creativeCommitment;
|
|
1266
|
-
if (!creativeCommitment || typeof creativeCommitment !== 'object') {
|
|
1267
|
-
validationErrors.push('designIntent.designExecutionHandoff.creativeCommitment must exist.');
|
|
1268
|
-
} else {
|
|
1269
|
-
if (creativeCommitment.status !== 'agent-must-complete-before-ui-implementation') {
|
|
1270
|
-
validationErrors.push('designIntent.designExecutionHandoff.creativeCommitment.status must equal "agent-must-complete-before-ui-implementation".');
|
|
1271
|
-
}
|
|
1272
|
-
if (
|
|
1273
|
-
!Array.isArray(creativeCommitment.requiredFields)
|
|
1274
|
-
|| !creativeCommitment.requiredFields.includes('specificReferencePoint')
|
|
1275
|
-
|| !creativeCommitment.requiredFields.includes('signatureMotion')
|
|
1276
|
-
|| !creativeCommitment.requiredFields.includes('typographicDecision')
|
|
1277
|
-
) {
|
|
1278
|
-
validationErrors.push('designIntent.designExecutionHandoff.creativeCommitment.requiredFields must include specificReferencePoint, signatureMotion, and typographicDecision.');
|
|
1279
|
-
}
|
|
1280
|
-
if (!hasNonEmptyString(creativeCommitment.failureMode)) {
|
|
1281
|
-
validationErrors.push('designIntent.designExecutionHandoff.creativeCommitment.failureMode must be a non-empty string.');
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
const implementationGuardrails = designIntentContract.designExecutionHandoff.implementationGuardrails;
|
|
1285
|
-
if (!implementationGuardrails || typeof implementationGuardrails !== 'object') {
|
|
1286
|
-
validationErrors.push('designIntent.designExecutionHandoff.implementationGuardrails must exist.');
|
|
1287
|
-
} else {
|
|
1288
|
-
for (const requiredFlagName of [
|
|
1289
|
-
'requireBuildFromHandoff',
|
|
1290
|
-
'requireGapNotesBeforeFallback',
|
|
1291
|
-
'forbidGenericLayoutFallbackWithoutReason',
|
|
1292
|
-
]) {
|
|
1293
|
-
if (implementationGuardrails[requiredFlagName] !== true) {
|
|
1294
|
-
validationErrors.push(`designIntent.designExecutionHandoff.implementationGuardrails.${requiredFlagName} must equal true.`);
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
|
-
if (!designIntentContract.reviewRubric || typeof designIntentContract.reviewRubric !== 'object') {
|
|
1301
|
-
validationErrors.push('designIntent.reviewRubric must exist.');
|
|
1302
|
-
} else {
|
|
1303
|
-
if (designIntentContract.reviewRubric.version !== 'ui-rubric-v1') {
|
|
1304
|
-
validationErrors.push('designIntent.reviewRubric.version must equal "ui-rubric-v1".');
|
|
1305
|
-
}
|
|
1306
|
-
if (designIntentContract.reviewRubric.genericityAutoFail !== true) {
|
|
1307
|
-
validationErrors.push('designIntent.reviewRubric.genericityAutoFail must equal true.');
|
|
1308
|
-
}
|
|
1309
|
-
if (!Array.isArray(designIntentContract.reviewRubric.dimensions) || designIntentContract.reviewRubric.dimensions.length < 5) {
|
|
1310
|
-
validationErrors.push('designIntent.reviewRubric.dimensions must define the required rubric dimensions.');
|
|
1311
|
-
} else {
|
|
1312
|
-
for (const requiredRubricKey of [
|
|
1313
|
-
'distinctiveness',
|
|
1314
|
-
'contractFidelity',
|
|
1315
|
-
'visualConsistency',
|
|
1316
|
-
'heuristicUxQuality',
|
|
1317
|
-
'motionDiscipline',
|
|
1318
|
-
]) {
|
|
1319
|
-
if (!designIntentContract.reviewRubric.dimensions.some((dimension) => dimension?.key === requiredRubricKey)) {
|
|
1320
|
-
validationErrors.push(`designIntent.reviewRubric.dimensions is missing "${requiredRubricKey}".`);
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
}
|
|
1324
|
-
if (!Array.isArray(designIntentContract.reviewRubric.genericitySignals) || designIntentContract.reviewRubric.genericitySignals.length < 3) {
|
|
1325
|
-
validationErrors.push('designIntent.reviewRubric.genericitySignals must list common genericity drift signals.');
|
|
1326
|
-
} else {
|
|
1327
|
-
for (const requiredSignal of [
|
|
1328
|
-
'ai-safe-ui-template-look',
|
|
1329
|
-
'interchangeable-product-renaming-test-fails',
|
|
1330
|
-
'decorative-grid-or-glow-wallpaper-without-product-function',
|
|
1331
|
-
]) {
|
|
1332
|
-
if (!designIntentContract.reviewRubric.genericitySignals.includes(requiredSignal)) {
|
|
1333
|
-
validationErrors.push(`designIntent.reviewRubric.genericitySignals must include "${requiredSignal}".`);
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
|
-
if (!Array.isArray(designIntentContract.reviewRubric.validBoldSignals) || designIntentContract.reviewRubric.validBoldSignals.length < 3) {
|
|
1338
|
-
validationErrors.push('designIntent.reviewRubric.validBoldSignals must list legitimate authored signals.');
|
|
1339
|
-
} else {
|
|
1340
|
-
for (const requiredSignal of [
|
|
1341
|
-
'three-at-a-glance-product-specific-signals',
|
|
1342
|
-
'visually-exploratory-accessible-palette-derived-from-product',
|
|
1343
|
-
]) {
|
|
1344
|
-
if (!designIntentContract.reviewRubric.validBoldSignals.includes(requiredSignal)) {
|
|
1345
|
-
validationErrors.push(`designIntent.reviewRubric.validBoldSignals must include "${requiredSignal}".`);
|
|
1346
|
-
}
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
if (!designIntentContract.reviewRubric.reportingRules || typeof designIntentContract.reviewRubric.reportingRules !== 'object') {
|
|
1350
|
-
validationErrors.push('designIntent.reviewRubric.reportingRules must exist.');
|
|
1351
|
-
} else {
|
|
1352
|
-
for (const requiredFlagName of [
|
|
1353
|
-
'mustExplainGenericity',
|
|
1354
|
-
'mustSeparateTasteFromFailure',
|
|
1355
|
-
'contractFidelityOverridesPersonalTaste',
|
|
1356
|
-
]) {
|
|
1357
|
-
if (designIntentContract.reviewRubric.reportingRules[requiredFlagName] !== true) {
|
|
1358
|
-
validationErrors.push(`designIntent.reviewRubric.reportingRules.${requiredFlagName} must equal true.`);
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
|
|
1364
|
-
if (!Array.isArray(designIntentContract.requiredDesignSections) || designIntentContract.requiredDesignSections.length !== DESIGN_REQUIRED_SECTIONS.length) {
|
|
1365
|
-
validationErrors.push('designIntent.requiredDesignSections must match the required design contract sections.');
|
|
1366
|
-
} else {
|
|
1367
|
-
for (const requiredSectionName of DESIGN_REQUIRED_SECTIONS) {
|
|
1368
|
-
if (!designIntentContract.requiredDesignSections.includes(requiredSectionName)) {
|
|
1369
|
-
validationErrors.push(`designIntent.requiredDesignSections is missing "${requiredSectionName}".`);
|
|
1370
|
-
}
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
if (!Array.isArray(designIntentContract.forbiddenPatterns) || designIntentContract.forbiddenPatterns.length < 4) {
|
|
1375
|
-
validationErrors.push('designIntent.forbiddenPatterns must list concrete anti-generic patterns.');
|
|
1376
|
-
} else {
|
|
1377
|
-
for (const requiredPattern of [
|
|
1378
|
-
'ai-safe-ui-template-look',
|
|
1379
|
-
'interchangeable-product-renaming-test-fails',
|
|
1380
|
-
'decorative-grid-or-glow-wallpaper-without-product-function',
|
|
1381
|
-
]) {
|
|
1382
|
-
if (!designIntentContract.forbiddenPatterns.includes(requiredPattern)) {
|
|
1383
|
-
validationErrors.push(`designIntent.forbiddenPatterns must include "${requiredPattern}".`);
|
|
1384
|
-
}
|
|
1385
|
-
}
|
|
1386
|
-
}
|
|
1387
|
-
|
|
1388
|
-
return validationErrors;
|
|
1389
|
-
}
|
|
665
|
+
export { validateDesignContractCompleteness, validateDesignIntentContract } from './design-contract/validation.mjs';
|
|
1390
666
|
|
|
1391
667
|
export function buildDesignIntentSeedFromSignals({
|
|
1392
668
|
projectName,
|