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