openuispec 0.1.18 → 0.1.19

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 (96) hide show
  1. package/README.md +52 -34
  2. package/cli/index.ts +1 -1
  3. package/docs/stress-test-maturity-report.md +97 -0
  4. package/examples/todo-orbit/AGENTS.md +127 -0
  5. package/examples/todo-orbit/CLAUDE.md +127 -0
  6. package/examples/todo-orbit/README.md +62 -0
  7. package/examples/todo-orbit/generated/android/Todo Orbit/README.md +14 -0
  8. package/examples/todo-orbit/generated/android/Todo Orbit/app/build.gradle.kts +58 -0
  9. package/examples/todo-orbit/generated/android/Todo Orbit/app/proguard-rules.pro +1 -0
  10. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/AndroidManifest.xml +20 -0
  11. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/MainActivity.kt +14 -0
  12. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/TodoOrbitApp.kt +345 -0
  13. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/AppLogic.kt +231 -0
  14. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/Models.kt +169 -0
  15. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/Strings.kt +8 -0
  16. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/components/CommonComponents.kt +185 -0
  17. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/AnalyticsScreen.kt +193 -0
  18. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/SettingsScreen.kt +102 -0
  19. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/TasksScreen.kt +342 -0
  20. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/sheets/EditorSheets.kt +344 -0
  21. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/theme/TodoOrbitTheme.kt +59 -0
  22. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values/strings.xml +148 -0
  23. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values-ru/strings.xml +154 -0
  24. package/examples/todo-orbit/generated/android/Todo Orbit/build.gradle.kts +4 -0
  25. package/examples/todo-orbit/generated/android/Todo Orbit/gradle/wrapper/gradle-wrapper.jar +0 -0
  26. package/examples/todo-orbit/generated/android/Todo Orbit/gradle/wrapper/gradle-wrapper.properties +7 -0
  27. package/examples/todo-orbit/generated/android/Todo Orbit/gradle.properties +4 -0
  28. package/examples/todo-orbit/generated/android/Todo Orbit/gradlew +248 -0
  29. package/examples/todo-orbit/generated/android/Todo Orbit/gradlew.bat +93 -0
  30. package/examples/todo-orbit/generated/android/Todo Orbit/settings.gradle.kts +18 -0
  31. package/examples/todo-orbit/generated/ios/Todo Orbit/README.md +29 -0
  32. package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/en.lproj/Localizable.strings +118 -0
  33. package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/ru.lproj/Localizable.strings +118 -0
  34. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/App/TodoOrbitApp.swift +50 -0
  35. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/OrbitChrome.swift +204 -0
  36. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/SchedulePreviewView.swift +126 -0
  37. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/TrendChartView.swift +70 -0
  38. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/RecurringRuleSheet.swift +123 -0
  39. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/TaskEditorSheet.swift +60 -0
  40. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Models/DomainModels.swift +238 -0
  41. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/AnalyticsView.swift +94 -0
  42. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/SettingsView.swift +74 -0
  43. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/TasksHomeView.swift +363 -0
  44. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Support/AppModel.swift +324 -0
  45. package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/project.pbxproj +408 -0
  46. package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  47. package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/xcshareddata/xcschemes/TodoOrbit.xcscheme +79 -0
  48. package/examples/todo-orbit/generated/ios/Todo Orbit/project.yml +24 -0
  49. package/examples/todo-orbit/generated/web/Todo Orbit/index.html +16 -0
  50. package/examples/todo-orbit/generated/web/Todo Orbit/package-lock.json +1087 -0
  51. package/examples/todo-orbit/generated/web/Todo Orbit/package.json +24 -0
  52. package/examples/todo-orbit/generated/web/Todo Orbit/src/App.tsx +2114 -0
  53. package/examples/todo-orbit/generated/web/Todo Orbit/src/main.tsx +13 -0
  54. package/examples/todo-orbit/generated/web/Todo Orbit/src/styles.css +886 -0
  55. package/examples/todo-orbit/generated/web/Todo Orbit/tsconfig.json +19 -0
  56. package/examples/todo-orbit/generated/web/Todo Orbit/vite.config.ts +6 -0
  57. package/examples/todo-orbit/openuispec/README.md +158 -0
  58. package/examples/todo-orbit/openuispec/contracts/.gitkeep +0 -0
  59. package/examples/todo-orbit/openuispec/contracts/action_trigger.yaml +28 -0
  60. package/examples/todo-orbit/openuispec/contracts/collection.yaml +32 -0
  61. package/examples/todo-orbit/openuispec/contracts/data_display.yaml +38 -0
  62. package/examples/todo-orbit/openuispec/contracts/feedback.yaml +32 -0
  63. package/examples/todo-orbit/openuispec/contracts/input_field.yaml +52 -0
  64. package/examples/todo-orbit/openuispec/contracts/nav_container.yaml +47 -0
  65. package/examples/todo-orbit/openuispec/contracts/surface.yaml +28 -0
  66. package/examples/todo-orbit/openuispec/contracts/x_schedule_preview.yaml +134 -0
  67. package/examples/todo-orbit/openuispec/contracts/x_task_trend_chart.yaml +139 -0
  68. package/examples/todo-orbit/openuispec/flows/.gitkeep +0 -0
  69. package/examples/todo-orbit/openuispec/flows/create_recurring_rule.yaml +253 -0
  70. package/examples/todo-orbit/openuispec/flows/create_task.yaml +118 -0
  71. package/examples/todo-orbit/openuispec/flows/edit_task.yaml +126 -0
  72. package/examples/todo-orbit/openuispec/locales/.gitkeep +0 -0
  73. package/examples/todo-orbit/openuispec/locales/en.json +150 -0
  74. package/examples/todo-orbit/openuispec/locales/ru.json +150 -0
  75. package/examples/todo-orbit/openuispec/openuispec.yaml +122 -0
  76. package/examples/todo-orbit/openuispec/platform/.gitkeep +0 -0
  77. package/examples/todo-orbit/openuispec/platform/android.yaml +19 -0
  78. package/examples/todo-orbit/openuispec/platform/ios.yaml +20 -0
  79. package/examples/todo-orbit/openuispec/platform/web.yaml +22 -0
  80. package/examples/todo-orbit/openuispec/screens/.gitkeep +0 -0
  81. package/examples/todo-orbit/openuispec/screens/analytics.yaml +139 -0
  82. package/examples/todo-orbit/openuispec/screens/home.yaml +172 -0
  83. package/examples/todo-orbit/openuispec/screens/settings.yaml +148 -0
  84. package/examples/todo-orbit/openuispec/screens/task_detail.yaml +223 -0
  85. package/examples/todo-orbit/openuispec/tokens/.gitkeep +0 -0
  86. package/examples/todo-orbit/openuispec/tokens/color.yaml +93 -0
  87. package/examples/todo-orbit/openuispec/tokens/elevation.yaml +25 -0
  88. package/examples/todo-orbit/openuispec/tokens/icons.yaml +92 -0
  89. package/examples/todo-orbit/openuispec/tokens/layout.yaml +107 -0
  90. package/examples/todo-orbit/openuispec/tokens/motion.yaml +39 -0
  91. package/examples/todo-orbit/openuispec/tokens/spacing.yaml +18 -0
  92. package/examples/todo-orbit/openuispec/tokens/themes.yaml +23 -0
  93. package/examples/todo-orbit/openuispec/tokens/typography.yaml +52 -0
  94. package/package.json +1 -1
  95. package/schema/validate.ts +0 -2
  96. package/spec/openuispec-v0.1.md +76 -12
@@ -0,0 +1,92 @@
1
+ icons:
2
+ sizes:
3
+ sm:
4
+ semantic: "Small inline icon size"
5
+ value: 16
6
+ md:
7
+ semantic: "Default icon size for actions and list items"
8
+ value: 20
9
+ lg:
10
+ semantic: "Prominent icon size for empty states and hero elements"
11
+ value: 24
12
+
13
+ variants:
14
+ default: "outline"
15
+ suffixes:
16
+ _fill: "Filled variant for active or completed states"
17
+
18
+ fallback:
19
+ strategy: "name_passthrough"
20
+ missing_icon: "questionmark_circle"
21
+
22
+ registry:
23
+ actions:
24
+ plus:
25
+ semantic: "Create a new task or item"
26
+ platform:
27
+ ios: "plus"
28
+ android: "add"
29
+ web: "plus"
30
+ search:
31
+ semantic: "Search tasks"
32
+ platform:
33
+ ios: "magnifyingglass"
34
+ android: "search"
35
+ web: "search"
36
+ trash:
37
+ semantic: "Delete a task"
38
+ platform:
39
+ ios: "trash"
40
+ android: "delete"
41
+ web: "trash-2"
42
+ checkmark:
43
+ semantic: "Confirm completion"
44
+ variants: ["circle", "circle_fill", "list"]
45
+ platform:
46
+ ios: "checkmark"
47
+ android: "check"
48
+ web: "check"
49
+
50
+ objects:
51
+ calendar:
52
+ semantic: "Date and scheduling"
53
+ platform:
54
+ ios: "calendar"
55
+ android: "calendar_today"
56
+ web: "calendar"
57
+ gear:
58
+ semantic: "Settings and preferences"
59
+ variants: ["fill"]
60
+ platform:
61
+ ios: "gear"
62
+ android: "settings"
63
+ web: "settings"
64
+ globe:
65
+ semantic: "Language and locale selection"
66
+ platform:
67
+ ios: "globe"
68
+ android: "language"
69
+ web: "languages"
70
+ flag:
71
+ semantic: "Priority marker"
72
+ variants: ["fill"]
73
+ platform:
74
+ ios: "flag"
75
+ android: "flag"
76
+ web: "flag"
77
+
78
+ custom:
79
+ todo_orbit:
80
+ checkmark_list:
81
+ semantic: "Todo list navigation icon"
82
+ platform:
83
+ ios: "checklist"
84
+ android: "checklist"
85
+ web: "list-checks"
86
+ chart_line:
87
+ semantic: "Analytics and trend visualization icon"
88
+ variants: ["fill"]
89
+ platform:
90
+ ios: "chart.line.uptrend.xyaxis"
91
+ android: "insert_chart"
92
+ web: "chart-line"
@@ -0,0 +1,107 @@
1
+ layout:
2
+ size_classes:
3
+ compact:
4
+ semantic: "Phone-first single-column layouts"
5
+ width: { max: 640 }
6
+ columns: 4
7
+ margin: "spacing.md"
8
+ content_max_width: null
9
+ examples: "Phones in portrait, narrow browser windows"
10
+ regular:
11
+ semantic: "Tablet portrait and large phone landscape layouts"
12
+ width: { min: 641, max: 1024 }
13
+ columns: 8
14
+ margin: "spacing.lg"
15
+ content_max_width: 860
16
+ examples: "Tablets in portrait, wide phones in landscape"
17
+ expanded:
18
+ semantic: "Desktop and large-tablet multi-column layouts"
19
+ width: { min: 1025 }
20
+ columns: 12
21
+ margin: "spacing.xl"
22
+ content_max_width: 1240
23
+ examples: "Desktop browsers, tablets in landscape"
24
+
25
+ platform_mapping:
26
+ ios:
27
+ uses: "UIUserInterfaceSizeClass"
28
+ compact: ".compact horizontal"
29
+ regular: ".regular horizontal"
30
+ expanded: ".regular horizontal + width > 1024"
31
+ android:
32
+ uses: "WindowSizeClass"
33
+ compact: "WindowWidthSizeClass.Compact"
34
+ regular: "WindowWidthSizeClass.Medium"
35
+ expanded: "WindowWidthSizeClass.Expanded"
36
+ web:
37
+ uses: "media queries"
38
+ compact: "@media (max-width: 640px)"
39
+ regular: "@media (min-width: 641px) and (max-width: 1024px)"
40
+ expanded: "@media (min-width: 1025px)"
41
+
42
+ primitives:
43
+ stack:
44
+ semantic: "Vertical content flow"
45
+ props:
46
+ spacing: { type: token_ref, default: "spacing.md" }
47
+ align: { type: enum, values: [leading, center, trailing, stretch], default: stretch }
48
+ padding: { type: token_ref, required: false }
49
+ platform_mapping:
50
+ ios: "VStack"
51
+ android: "Column"
52
+ web: "flex-direction: column"
53
+ row:
54
+ semantic: "Horizontal content flow"
55
+ props:
56
+ spacing: { type: token_ref, default: "spacing.sm" }
57
+ align: { type: enum, values: [top, center, bottom, baseline, stretch], default: center }
58
+ justify: { type: enum, values: [start, center, end, space-between, space-around], default: start }
59
+ wrap: { type: bool, default: false }
60
+ platform_mapping:
61
+ ios: "HStack"
62
+ android: "Row"
63
+ web: "flex-direction: row"
64
+ grid:
65
+ semantic: "Responsive 2D arrangement"
66
+ props:
67
+ columns: { type: "int or adaptive_map", default: 2 }
68
+ gap: { type: token_ref, default: "spacing.md" }
69
+ platform_mapping:
70
+ ios: "LazyVGrid"
71
+ android: "LazyVerticalGrid"
72
+ web: "display: grid"
73
+ scroll_vertical:
74
+ semantic: "Scrollable vertical canvas"
75
+ props:
76
+ safe_area: { type: bool, default: true }
77
+ padding: { type: token_ref, required: false }
78
+ platform_mapping:
79
+ ios: "ScrollView(.vertical)"
80
+ android: "LazyColumn or verticalScroll"
81
+ web: "overflow-y: auto"
82
+ split_view:
83
+ semantic: "Master-detail two-pane layout"
84
+ props:
85
+ primary_width: { type: "fraction or token_ref", default: 0.36 }
86
+ divider: { type: bool, default: true }
87
+ collapse_at: { type: size_class, default: "compact" }
88
+ platform_mapping:
89
+ ios: "NavigationSplitView"
90
+ android: "ListDetailPaneScaffold"
91
+ web: "CSS Grid with two columns"
92
+
93
+ reflow_rules:
94
+ action_trigger:
95
+ compact: { full_width: true }
96
+ regular: { full_width: false }
97
+ nav_container:
98
+ compact: { variant: "tab_bar" }
99
+ regular: { variant: "rail" }
100
+ expanded: { variant: "sidebar" }
101
+ task_actions:
102
+ compact: { layout: stack }
103
+ regular: { layout: row }
104
+ stat_group:
105
+ compact: { layout: grid, columns: 2 }
106
+ regular: { layout: row }
107
+ expanded: { layout: row }
@@ -0,0 +1,39 @@
1
+ motion:
2
+ duration:
3
+ instant: 100
4
+ quick: 180
5
+ normal: 280
6
+ slow: 420
7
+
8
+ easing:
9
+ default: "ease-out"
10
+ enter: "ease-out"
11
+ exit: "ease-in"
12
+ emphasis: "cubic-bezier(0.2, 0, 0, 1)"
13
+
14
+ reduced_motion: "remove-animation"
15
+
16
+ patterns:
17
+ press_feedback:
18
+ duration: "instant"
19
+ property: "scale"
20
+ value: 0.98
21
+ state_change:
22
+ duration: "quick"
23
+ property: "opacity, border-color, background"
24
+ screen_enter:
25
+ duration: "normal"
26
+ easing: "enter"
27
+ pattern: "slide-from-trailing"
28
+ screen_exit:
29
+ duration: "quick"
30
+ easing: "exit"
31
+ pattern: "slide-to-leading"
32
+ checkbox_check:
33
+ duration: "quick"
34
+ easing: "emphasis"
35
+ pattern: "scale-bounce"
36
+ modal_present:
37
+ duration: "normal"
38
+ easing: "enter"
39
+ pattern: "fade-and-lift"
@@ -0,0 +1,18 @@
1
+ spacing:
2
+ base_unit: 4
3
+ platform_flex: 0.15
4
+
5
+ scale:
6
+ none: 0
7
+ xs: 4
8
+ sm: 8
9
+ md: { base: 16, range: [12, 16] }
10
+ lg: { base: 24, range: [20, 24] }
11
+ xl: 32
12
+ xxl: 40
13
+
14
+ aliases:
15
+ page_margin: { horizontal: md, vertical: md }
16
+ card_padding: { all: md }
17
+ section_gap: lg
18
+ inline_gap: sm
@@ -0,0 +1,23 @@
1
+ themes:
2
+ default: "light"
3
+
4
+ variants:
5
+ light:
6
+ surface.primary: { lightness: [97, 100] }
7
+ surface.secondary: { lightness: [93, 97] }
8
+ surface.tertiary: { lightness: [89, 94] }
9
+ text.primary: { lightness: [8, 14] }
10
+ text.secondary: { lightness: [36, 46] }
11
+ border.default: { opacity: 0.22 }
12
+ dark:
13
+ surface.primary: { lightness: [10, 14] }
14
+ surface.secondary: { lightness: [14, 18] }
15
+ surface.tertiary: { lightness: [18, 24] }
16
+ text.primary: { lightness: [90, 95] }
17
+ text.secondary: { lightness: [62, 70] }
18
+ border.default: { opacity: 0.18 }
19
+
20
+ platform:
21
+ ios: { supports_dynamic: true }
22
+ android: { dynamic_color: true }
23
+ web: { prefers_color_scheme: true, css_custom_properties: true }
@@ -0,0 +1,52 @@
1
+ typography:
2
+ font_family:
3
+ primary:
4
+ semantic: "Main UI typeface for the todo app"
5
+ value: "Manrope"
6
+ fallback_strategy: "modern-sans"
7
+ platform:
8
+ ios: { system_alternative: "SF Pro" }
9
+ android: { system_alternative: "Google Sans" }
10
+ web: { load_strategy: "swap", source: "google_fonts" }
11
+
12
+ scale:
13
+ display:
14
+ semantic: "Large empty-state and hero copy"
15
+ size: { base: 30, range: [28, 34] }
16
+ weight: 700
17
+ tracking: -0.02
18
+ line_height: 1.15
19
+ heading_lg:
20
+ semantic: "Primary screen titles"
21
+ size: { base: 24, range: [22, 28] }
22
+ weight: 700
23
+ tracking: -0.02
24
+ line_height: 1.2
25
+ heading:
26
+ semantic: "Section headings and modal titles"
27
+ size: { base: 18, range: [17, 20] }
28
+ weight: 600
29
+ tracking: -0.01
30
+ line_height: 1.3
31
+ heading_sm:
32
+ semantic: "Compact emphasized labels"
33
+ size: { base: 15, range: [14, 17] }
34
+ weight: 600
35
+ line_height: 1.35
36
+ body:
37
+ semantic: "Primary body copy"
38
+ size: { base: 16, range: [15, 17] }
39
+ weight: 400
40
+ line_height: 1.5
41
+ body_sm:
42
+ semantic: "Supporting text and subtitles"
43
+ size: { base: 14, range: [13, 15] }
44
+ weight: 400
45
+ tracking: 0.004
46
+ line_height: 1.45
47
+ caption:
48
+ semantic: "Tiny labels and metadata"
49
+ size: { base: 12, range: [11, 13] }
50
+ weight: 500
51
+ tracking: 0.015
52
+ line_height: 1.35
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openuispec",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "A semantic UI specification format for AI-native, platform-native app development",
@@ -407,8 +407,6 @@ function validateFile(
407
407
  return errors.length;
408
408
  }
409
409
 
410
- // ── validation groups ────────────────────────────────────────────────
411
-
412
410
  // ── includes resolution ──────────────────────────────────────────────
413
411
 
414
412
  interface Includes {
@@ -13,6 +13,8 @@
13
13
 
14
14
  OpenUISpec is not a cross-platform framework. It is a **semantic design language specification** from which AI generates native platform code. The spec describes *what* UI does and *how it should feel* — never *which widget to use*.
15
15
 
16
+ OpenUISpec is a shared UI sync language for native products, optimized for solo developers but also intended for teams that need a durable synchronization layer between product intent and platform code. It is not a pixel-perfect design description and it does not aim to erase platform differences. Its goal is semantic consistency with bounded native variation.
17
+
16
18
  ### Core principles
17
19
 
18
20
  1. **Semantic over visual.** The spec defines behavioral intent, not pixel layouts. A "primary action trigger" maps to `Button` in SwiftUI, `Button` in Compose, and `<button>` in HTML — the spec never says "button."
@@ -1720,6 +1722,8 @@ Layout primitives are the building blocks for arranging content. They replace th
1720
1722
  | `split_view` | Side-by-side master-detail | `NavigationSplitView` | `ListDetailPaneScaffold` | CSS Grid |
1721
1723
  | `adaptive` | Changes layout per size class | — | — | — |
1722
1724
 
1725
+ Layout primitives must remain usable across the size classes they are generated for. Multi-pane or master-detail patterns require an explicit compact fallback rather than assuming large-screen behavior will degrade correctly.
1726
+
1723
1727
  Each primitive has typed props:
1724
1728
 
1725
1729
  ```yaml
@@ -2022,17 +2026,21 @@ This section defines the rules any AI code generator must follow when producing
2022
2026
  Every AI generator, regardless of platform target, MUST:
2023
2027
 
2024
2028
  1. Produce **compilable code** that builds without errors on the target platform.
2025
- 2. Map every `contract` reference to the correct native widget per `platform_mapping`.
2026
- 3. Apply all `tokens` values within their declared `range` constraints.
2027
- 4. Implement every `state` declared in each used contract, including transitions.
2028
- 5. Set correct `a11y.role` and `a11y.label` for every component instance. For contextual containers such as `collection`, derive the label from the visible heading/header via `aria-labelledby` or the platform equivalent when possible instead of requiring a dedicated prop.
2029
- 6. Respect `themes` by generating light/dark mode support.
2030
- 7. Handle `empty`, `loading`, and `error` states for `collection` contracts.
2031
- 8. Wire all `action.navigate` declarations to the platform's navigation system.
2032
- 9. Apply `motion.reduced_motion` preferences globally.
2033
- 10. Implement all three size classes (`compact`, `regular`, `expanded`) and apply `adaptive` overrides from screen files.
2034
- 11. Validate all `props` types and report spec errors before generating code.
2035
- 12. Generate platform-native localization resources from JSON locale files when `i18n` config is present (see Section 11).
2029
+ 2. Refresh its knowledge of the current target platform implementation model before generation when the output depends on toolchain-specific conventions, project formats, packaging rules, resource wiring, or fast-moving framework APIs.
2030
+ 3. Map every `contract` reference to the correct native widget per `platform_mapping`.
2031
+ 4. Apply all `tokens` values within their declared `range` constraints.
2032
+ 5. Implement every `state` declared in each used contract, including transitions.
2033
+ 6. Set correct `a11y.role` and `a11y.label` for every component instance. For contextual containers such as `collection`, derive the label from the visible heading/header via `aria-labelledby` or the platform equivalent when possible instead of requiring a dedicated prop.
2034
+ 7. Respect `themes` by generating light/dark mode support.
2035
+ 8. Handle `empty`, `loading`, and `error` states for `collection` contracts.
2036
+ 9. Wire all `action.navigate` declarations to the platform's navigation system.
2037
+ 10. Apply `motion.reduced_motion` preferences globally.
2038
+ 11. Implement all three size classes (`compact`, `regular`, `expanded`) and apply `adaptive` overrides from screen files.
2039
+ 12. Validate all `props` types and report spec errors before generating code.
2040
+ 13. Generate platform-native localization resources from JSON locale files when `i18n` config is present (see Section 11).
2041
+ 14. Emit a valid native project or target configuration that bundles every generated runtime resource, including localization files, assets, and generated metadata. A generated resource file that is not connected to the runnable target is non-compliant.
2042
+ 15. Adapt navigation and container patterns for every supported size class and form factor. A generator may not assume that a large-screen or multi-pane layout will remain usable on compact layouts without an explicit fallback.
2043
+ 16. Preserve required contract semantics when mapping to native widgets. A platform-native substitution may change the implementation primitive, but it may not drop required token-driven shapes, borders, visual states, or interaction semantics declared by the contract.
2036
2044
 
2037
2045
  ### 8.3 Validation
2038
2046
 
@@ -2975,7 +2983,7 @@ Generators produce platform-native localization resources from the JSON source:
2975
2983
 
2976
2984
  | Platform | Output format | Plurals | Notes |
2977
2985
  |----------|--------------|---------|-------|
2978
- | **iOS** | `.xcstrings` (Xcode 15+) | Built-in plural rules | ICU plurals map to `.stringsdict` entries within `.xcstrings` |
2986
+ | **iOS** | `.xcstrings` (Xcode 15+) or correctly bundled `.strings` resources | Built-in plural rules | ICU plurals map to `.stringsdict` entries within `.xcstrings`; generated locale resources must be attached to the runnable target and resolvable at runtime |
2979
2987
  | **Android** | `res/values-{locale}/strings.xml` + `plurals.xml` | `<plurals>` element | ICU selects map to conditional logic in generated code |
2980
2988
  | **Web** | JSON bundles per locale | `react-intl` / `i18next` ICU plugin | Direct ICU MessageFormat — no conversion needed |
2981
2989
 
@@ -2993,6 +3001,7 @@ i18n:
2993
3001
  **MUST:**
2994
3002
  - Resolve every `$t:key` reference to the corresponding locale string
2995
3003
  - Generate platform-native locale files from JSON sources for each supported locale
3004
+ - Ensure generated locale files are actually bundled by the runnable platform target and available at runtime
2996
3005
  - Pass `t_params` data paths to ICU placeholders at runtime
2997
3006
  - Apply `$direction` from the active locale to layout direction
2998
3007
  - Use the `fallback_strategy` for missing keys (default: fall back to `default_locale`)
@@ -3201,6 +3210,61 @@ ios:
3201
3210
  - Generate test code based on `test_cases`
3202
3211
  - Add platform-specific enhancements beyond what the contract specifies
3203
3212
 
3213
+ ### 12.8 Extending standard contracts
3214
+
3215
+ The 7 built-in contract families (Section 4) can be extended per-project using `contracts/<name>.yaml` files. Extensions add project-specific **variants**, **token overrides**, **platform mapping**, and **generation hints** without redefining the base contract. The base definition (props, states, a11y) remains authoritative from the spec.
3216
+
3217
+ ```yaml
3218
+ # contracts/input_field.yaml
3219
+ input_field:
3220
+ variants:
3221
+ cut_corner:
3222
+ semantic: "Angled corner input for branded forms"
3223
+ tokens:
3224
+ cut_size: "spacing.sm"
3225
+ border: { color: "color.semantic.border", width: 1 }
3226
+ platform_mapping:
3227
+ ios: { shape: "CutCornerShape", clip: true }
3228
+ android: { shape: "CutCornerShape" }
3229
+ web: { style: "clip-path" }
3230
+ generation:
3231
+ must_handle:
3232
+ - "Cut top-right and bottom-left corners by cut_size"
3233
+ - "Maintain focus ring that follows the cut shape"
3234
+ should_handle:
3235
+ - "Animate corner cut on focus"
3236
+ ```
3237
+
3238
+ **Root key:** The contract family name (e.g. `input_field`, `action_trigger`). Not `x_` prefixed — that is reserved for fully custom contracts.
3239
+
3240
+ **Available extension fields** (all optional):
3241
+
3242
+ | Field | Purpose |
3243
+ |-------|---------|
3244
+ | `variants` | Named style/behavior presets with their own tokens, platform_mapping, and generation hints |
3245
+ | `additional_props` | Props beyond what the spec defines for this contract |
3246
+ | `tokens` | Contract-level token overrides |
3247
+ | `platform_mapping` | Per-platform implementation hints |
3248
+ | `generation` | AI generation hints (must_handle, should_handle, may_handle) |
3249
+ | `test_cases` | Behavioral verification scenarios |
3250
+
3251
+ **Usage in screens:** Reference a variant by name in the `variant` field of a contract instance:
3252
+
3253
+ ```yaml
3254
+ - contract: input_field
3255
+ variant: cut_corner
3256
+ props:
3257
+ label: "Email"
3258
+ input_type: email
3259
+ ```
3260
+
3261
+ **Key differences from custom contracts (Section 12.1–12.7):**
3262
+
3263
+ - Standard extensions do **not** redefine `semantic`, `props`, `states`, or `a11y` — these come from the spec
3264
+ - Required props from the base contract still apply (e.g. `input_field` always requires `props.label`)
3265
+ - An empty extension (`input_field: {}`) is valid and means "use the spec definition as-is"
3266
+ - Validated against `contract.schema.json`, not `custom-contract.schema.json`
3267
+
3204
3268
  ---
3205
3269
 
3206
3270
  ## 13. Form validation and field dependencies