openuispec 0.1.25 → 0.1.28

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 (139) hide show
  1. package/README.md +63 -18
  2. package/cli/index.ts +21 -3
  3. package/cli/init.ts +27 -11
  4. package/docs/implementation-notes.md +119 -0
  5. package/docs/release-notes-v0.1.26.md +64 -0
  6. package/docs/release-notes-v0.1.27.md +28 -0
  7. package/docs/release-notes-v0.1.28.md +25 -0
  8. package/docs/stress-test-maturity-report.md +1 -1
  9. package/drift/index.ts +396 -22
  10. package/examples/taskflow/AGENTS.md +112 -0
  11. package/examples/taskflow/CLAUDE.md +112 -0
  12. package/examples/taskflow/generated/android/TaskFlow/README.md +43 -0
  13. package/examples/taskflow/generated/android/TaskFlow/app/build.gradle.kts +76 -0
  14. package/examples/taskflow/generated/android/TaskFlow/app/proguard-rules.pro +1 -0
  15. package/examples/taskflow/generated/android/TaskFlow/app/src/main/AndroidManifest.xml +21 -0
  16. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/MainActivity.kt +19 -0
  17. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/TaskFlowApp.kt +283 -0
  18. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/model/DomainModels.kt +106 -0
  19. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/model/SampleData.kt +57 -0
  20. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/components/Common.kt +109 -0
  21. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/HomeScreen.kt +112 -0
  22. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/ProjectsScreen.kt +61 -0
  23. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/SettingsScreen.kt +82 -0
  24. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/TaskDetailScreen.kt +111 -0
  25. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/sheets/Sheets.kt +77 -0
  26. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Color.kt +30 -0
  27. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Theme.kt +86 -0
  28. package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Type.kt +57 -0
  29. package/examples/taskflow/generated/android/TaskFlow/app/src/main/res/values/strings.xml +155 -0
  30. package/examples/taskflow/generated/android/TaskFlow/app/src/main/res/values/themes.xml +4 -0
  31. package/examples/taskflow/generated/android/TaskFlow/build.gradle.kts +5 -0
  32. package/examples/taskflow/generated/android/TaskFlow/gradle/gradle-daemon-jvm.properties +12 -0
  33. package/examples/taskflow/generated/android/TaskFlow/gradle/wrapper/gradle-wrapper.jar +0 -0
  34. package/examples/taskflow/generated/android/TaskFlow/gradle/wrapper/gradle-wrapper.properties +7 -0
  35. package/examples/taskflow/generated/android/TaskFlow/gradle.properties +4 -0
  36. package/examples/taskflow/generated/android/TaskFlow/gradlew +18 -0
  37. package/examples/taskflow/generated/android/TaskFlow/gradlew.bat +12 -0
  38. package/examples/taskflow/generated/android/TaskFlow/settings.gradle.kts +18 -0
  39. package/examples/taskflow/generated/ios/TaskFlow/README.md +21 -0
  40. package/examples/taskflow/generated/ios/TaskFlow/Resources/en.lproj/Localizable.strings +115 -0
  41. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/App/TaskFlowApp.swift +24 -0
  42. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Components/AppChrome.swift +150 -0
  43. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Flows/TaskEditorSheet.swift +220 -0
  44. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Models/DomainModels.swift +122 -0
  45. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/CalendarView.swift +21 -0
  46. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/HomeView.swift +201 -0
  47. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProfileEditView.swift +48 -0
  48. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProjectDetailView.swift +59 -0
  49. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProjectsView.swift +63 -0
  50. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/SettingsView.swift +85 -0
  51. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/TaskDetailView.swift +219 -0
  52. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Support/AppModel.swift +320 -0
  53. package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Support/AppSupport.swift +41 -0
  54. package/examples/taskflow/generated/ios/TaskFlow/project.yml +26 -0
  55. package/examples/taskflow/generated/web/TaskFlow/README.md +19 -0
  56. package/examples/taskflow/generated/web/TaskFlow/index.html +12 -0
  57. package/examples/taskflow/generated/web/TaskFlow/package-lock.json +1908 -0
  58. package/examples/taskflow/generated/web/TaskFlow/package.json +24 -0
  59. package/examples/taskflow/generated/web/TaskFlow/src/App.tsx +58 -0
  60. package/examples/taskflow/generated/web/TaskFlow/src/AppShell.tsx +55 -0
  61. package/examples/taskflow/generated/web/TaskFlow/src/components/Common.tsx +82 -0
  62. package/examples/taskflow/generated/web/TaskFlow/src/components/Modals.tsx +191 -0
  63. package/examples/taskflow/generated/web/TaskFlow/src/components/Nav.tsx +41 -0
  64. package/examples/taskflow/generated/web/TaskFlow/src/generated/messages.ts +131 -0
  65. package/examples/taskflow/generated/web/TaskFlow/src/hooks.ts +25 -0
  66. package/examples/taskflow/generated/web/TaskFlow/src/i18n.ts +39 -0
  67. package/examples/taskflow/generated/web/TaskFlow/src/locales.en.json +111 -0
  68. package/examples/taskflow/generated/web/TaskFlow/src/main.tsx +13 -0
  69. package/examples/taskflow/generated/web/TaskFlow/src/screens/HomeScreen.tsx +111 -0
  70. package/examples/taskflow/generated/web/TaskFlow/src/screens/ProjectsScreen.tsx +82 -0
  71. package/examples/taskflow/generated/web/TaskFlow/src/screens/SettingsScreens.tsx +132 -0
  72. package/examples/taskflow/generated/web/TaskFlow/src/screens/TaskDetail.tsx +105 -0
  73. package/examples/taskflow/generated/web/TaskFlow/src/store.ts +216 -0
  74. package/examples/taskflow/generated/web/TaskFlow/src/styles.css +617 -0
  75. package/examples/taskflow/generated/web/TaskFlow/src/types.ts +64 -0
  76. package/examples/taskflow/generated/web/TaskFlow/src/utils.ts +78 -0
  77. package/examples/taskflow/generated/web/TaskFlow/tsconfig.json +21 -0
  78. package/examples/taskflow/generated/web/TaskFlow/vite.config.ts +6 -0
  79. package/examples/taskflow/openuispec/README.md +49 -0
  80. package/examples/todo-orbit/AGENTS.md +46 -14
  81. package/examples/todo-orbit/CLAUDE.md +46 -14
  82. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/components/CommonComponents.kt +69 -18
  83. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/TasksScreen.kt +5 -0
  84. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/sheets/EditorSheets.kt +5 -2
  85. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values/strings.xml +1 -0
  86. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values-ru/strings.xml +1 -0
  87. package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/en.lproj/Localizable.strings +1 -0
  88. package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/ru.lproj/Localizable.strings +1 -0
  89. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/RecurringRuleSheet.swift +3 -0
  90. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/TaskEditorSheet.swift +1 -0
  91. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/SettingsView.swift +2 -0
  92. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/TasksHomeView.swift +1 -0
  93. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Support/AppModel.swift +1 -1
  94. package/examples/todo-orbit/generated/web/Todo Orbit/src/App.tsx +59 -6
  95. package/examples/todo-orbit/generated/web/Todo Orbit/src/styles.css +40 -0
  96. package/examples/todo-orbit/openuispec/README.md +24 -131
  97. package/examples/todo-orbit/openuispec/flows/create_recurring_rule.yaml +3 -0
  98. package/examples/todo-orbit/openuispec/flows/create_task.yaml +1 -0
  99. package/examples/todo-orbit/openuispec/flows/edit_task.yaml +1 -0
  100. package/examples/todo-orbit/openuispec/locales/en.json +1 -0
  101. package/examples/todo-orbit/openuispec/locales/ru.json +1 -0
  102. package/examples/todo-orbit/openuispec/screens/task_detail.yaml +1 -0
  103. package/examples/todo-orbit/openuispec/tokens/icons.yaml +6 -0
  104. package/package.json +6 -1
  105. package/prepare/index.ts +391 -0
  106. package/schema/semantic-lint.ts +592 -0
  107. package/schema/validate.ts +17 -13
  108. package/status/index.ts +200 -0
  109. /package/examples/taskflow/{contracts → openuispec/contracts}/README.md +0 -0
  110. /package/examples/taskflow/{contracts → openuispec/contracts}/action_trigger.yaml +0 -0
  111. /package/examples/taskflow/{contracts → openuispec/contracts}/collection.yaml +0 -0
  112. /package/examples/taskflow/{contracts → openuispec/contracts}/data_display.yaml +0 -0
  113. /package/examples/taskflow/{contracts → openuispec/contracts}/feedback.yaml +0 -0
  114. /package/examples/taskflow/{contracts → openuispec/contracts}/input_field.yaml +0 -0
  115. /package/examples/taskflow/{contracts → openuispec/contracts}/nav_container.yaml +0 -0
  116. /package/examples/taskflow/{contracts → openuispec/contracts}/surface.yaml +0 -0
  117. /package/examples/taskflow/{contracts → openuispec/contracts}/x_media_player.yaml +0 -0
  118. /package/examples/taskflow/{flows → openuispec/flows}/create_task.yaml +0 -0
  119. /package/examples/taskflow/{flows → openuispec/flows}/edit_task.yaml +0 -0
  120. /package/examples/taskflow/{locales → openuispec/locales}/en.json +0 -0
  121. /package/examples/taskflow/{openuispec.yaml → openuispec/openuispec.yaml} +0 -0
  122. /package/examples/taskflow/{platform → openuispec/platform}/android.yaml +0 -0
  123. /package/examples/taskflow/{platform → openuispec/platform}/ios.yaml +0 -0
  124. /package/examples/taskflow/{platform → openuispec/platform}/web.yaml +0 -0
  125. /package/examples/taskflow/{screens → openuispec/screens}/calendar.yaml +0 -0
  126. /package/examples/taskflow/{screens → openuispec/screens}/home.yaml +0 -0
  127. /package/examples/taskflow/{screens → openuispec/screens}/profile_edit.yaml +0 -0
  128. /package/examples/taskflow/{screens → openuispec/screens}/project_detail.yaml +0 -0
  129. /package/examples/taskflow/{screens → openuispec/screens}/projects.yaml +0 -0
  130. /package/examples/taskflow/{screens → openuispec/screens}/settings.yaml +0 -0
  131. /package/examples/taskflow/{screens → openuispec/screens}/task_detail.yaml +0 -0
  132. /package/examples/taskflow/{tokens → openuispec/tokens}/color.yaml +0 -0
  133. /package/examples/taskflow/{tokens → openuispec/tokens}/elevation.yaml +0 -0
  134. /package/examples/taskflow/{tokens → openuispec/tokens}/icons.yaml +0 -0
  135. /package/examples/taskflow/{tokens → openuispec/tokens}/layout.yaml +0 -0
  136. /package/examples/taskflow/{tokens → openuispec/tokens}/motion.yaml +0 -0
  137. /package/examples/taskflow/{tokens → openuispec/tokens}/spacing.yaml +0 -0
  138. /package/examples/taskflow/{tokens → openuispec/tokens}/themes.yaml +0 -0
  139. /package/examples/taskflow/{tokens → openuispec/tokens}/typography.yaml +0 -0
package/README.md CHANGED
@@ -68,7 +68,7 @@ For platform generation, treat these as hard output constraints:
68
68
 
69
69
  See the examples for concrete reference projects:
70
70
 
71
- - [TaskFlow](./examples/taskflow/) for a compact spec covering all 7 contract families
71
+ - [TaskFlow](./examples/taskflow/openuispec/) for a compact spec covering all 7 contract families
72
72
  - [Todo Orbit](./examples/todo-orbit/openuispec/) for a bilingual task app with generated iOS, Android, and web targets under `examples/todo-orbit/generated/`
73
73
 
74
74
  ## Repository structure
@@ -137,11 +137,13 @@ openuispec/
137
137
  │ ├── openuispec/ # Source OpenUISpec project
138
138
  │ ├── generated/ # Generated iOS, Android, and web apps
139
139
  │ └── artifacts/ # Screenshots and supporting outputs
140
- ├── cli/ # CLI tool (openuispec init, drift, validate)
140
+ ├── cli/ # CLI tool (openuispec init, drift, prepare, validate)
141
141
  │ ├── index.ts # Entry point
142
142
  │ └── init.ts # Project scaffolding + AI rules
143
143
  ├── drift/ # Drift detection (spec change tracking)
144
144
  │ └── index.ts # Hash-based drift checker
145
+ ├── prepare/ # AI-ready target work bundle generation
146
+ │ └── index.ts # Baseline-aware target preparation
145
147
  ├── LICENSE
146
148
  └── README.md
147
149
  ```
@@ -152,21 +154,21 @@ Every file type has a corresponding JSON Schema in `schema/`. **Read the schema
152
154
 
153
155
  | File | Schema | Root key | Example |
154
156
  |------|--------|----------|---------|
155
- | `openuispec.yaml` | `openuispec.schema.json` | `spec_version` | [openuispec.yaml](./examples/taskflow/openuispec.yaml) |
156
- | `screens/*.yaml` | `screen.schema.json` | `<screen_id>` | [home.yaml](./examples/taskflow/screens/home.yaml) |
157
- | `flows/*.yaml` | `flow.schema.json` | `<flow_id>` | [create_task.yaml](./examples/taskflow/flows/create_task.yaml) |
158
- | `platform/*.yaml` | `platform.schema.json` | `platform` | [ios.yaml](./examples/taskflow/platform/ios.yaml) |
159
- | `locales/*.json` | `locale.schema.json` | (object) | [en.json](./examples/taskflow/locales/en.json) |
160
- | `contracts/<name>.yaml` | `contract.schema.json` | `<contract_name>` | [input_field.yaml](./examples/taskflow/contracts/input_field.yaml) |
161
- | `contracts/x_*.yaml` | `custom-contract.schema.json` | `<x_name>` | [x_media_player.yaml](./examples/taskflow/contracts/x_media_player.yaml) |
162
- | `tokens/color.yaml` | `tokens/color.schema.json` | `color` | [color.yaml](./examples/taskflow/tokens/color.yaml) |
163
- | `tokens/typography.yaml` | `tokens/typography.schema.json` | `typography` | [typography.yaml](./examples/taskflow/tokens/typography.yaml) |
164
- | `tokens/spacing.yaml` | `tokens/spacing.schema.json` | `spacing` | [spacing.yaml](./examples/taskflow/tokens/spacing.yaml) |
165
- | `tokens/elevation.yaml` | `tokens/elevation.schema.json` | `elevation` | [elevation.yaml](./examples/taskflow/tokens/elevation.yaml) |
166
- | `tokens/motion.yaml` | `tokens/motion.schema.json` | `motion` | [motion.yaml](./examples/taskflow/tokens/motion.yaml) |
167
- | `tokens/layout.yaml` | `tokens/layout.schema.json` | `layout` | [layout.yaml](./examples/taskflow/tokens/layout.yaml) |
168
- | `tokens/themes.yaml` | `tokens/themes.schema.json` | `themes` | [themes.yaml](./examples/taskflow/tokens/themes.yaml) |
169
- | `tokens/icons.yaml` | `tokens/icons.schema.json` | `icons` | [icons.yaml](./examples/taskflow/tokens/icons.yaml) |
157
+ | `openuispec.yaml` | `openuispec.schema.json` | `spec_version` | [openuispec.yaml](./examples/taskflow/openuispec/openuispec.yaml) |
158
+ | `screens/*.yaml` | `screen.schema.json` | `<screen_id>` | [home.yaml](./examples/taskflow/openuispec/screens/home.yaml) |
159
+ | `flows/*.yaml` | `flow.schema.json` | `<flow_id>` | [create_task.yaml](./examples/taskflow/openuispec/flows/create_task.yaml) |
160
+ | `platform/*.yaml` | `platform.schema.json` | `platform` | [ios.yaml](./examples/taskflow/openuispec/platform/ios.yaml) |
161
+ | `locales/*.json` | `locale.schema.json` | (object) | [en.json](./examples/taskflow/openuispec/locales/en.json) |
162
+ | `contracts/<name>.yaml` | `contract.schema.json` | `<contract_name>` | [input_field.yaml](./examples/taskflow/openuispec/contracts/input_field.yaml) |
163
+ | `contracts/x_*.yaml` | `custom-contract.schema.json` | `<x_name>` | [x_media_player.yaml](./examples/taskflow/openuispec/contracts/x_media_player.yaml) |
164
+ | `tokens/color.yaml` | `tokens/color.schema.json` | `color` | [color.yaml](./examples/taskflow/openuispec/tokens/color.yaml) |
165
+ | `tokens/typography.yaml` | `tokens/typography.schema.json` | `typography` | [typography.yaml](./examples/taskflow/openuispec/tokens/typography.yaml) |
166
+ | `tokens/spacing.yaml` | `tokens/spacing.schema.json` | `spacing` | [spacing.yaml](./examples/taskflow/openuispec/tokens/spacing.yaml) |
167
+ | `tokens/elevation.yaml` | `tokens/elevation.schema.json` | `elevation` | [elevation.yaml](./examples/taskflow/openuispec/tokens/elevation.yaml) |
168
+ | `tokens/motion.yaml` | `tokens/motion.schema.json` | `motion` | [motion.yaml](./examples/taskflow/openuispec/tokens/motion.yaml) |
169
+ | `tokens/layout.yaml` | `tokens/layout.schema.json` | `layout` | [layout.yaml](./examples/taskflow/openuispec/tokens/layout.yaml) |
170
+ | `tokens/themes.yaml` | `tokens/themes.schema.json` | `themes` | [themes.yaml](./examples/taskflow/openuispec/tokens/themes.yaml) |
171
+ | `tokens/icons.yaml` | `tokens/icons.schema.json` | `icons` | [icons.yaml](./examples/taskflow/openuispec/tokens/icons.yaml) |
170
172
 
171
173
  Every token file **must** have a single root wrapper key matching its type:
172
174
 
@@ -183,6 +185,8 @@ brand:
183
185
 
184
186
  Validate with: `openuispec validate`
185
187
 
188
+ Use `openuispec validate semantic` to run cross-reference linting for locale keys, formatter refs, mapper refs, contracts, icons, navigation targets, and API endpoint references.
189
+
186
190
  ## Output directories
187
191
 
188
192
  By default, drift stores state in `generated/<target>/<project>/`. To point targets to your actual code directories, add `output_dir` to `openuispec.yaml`:
@@ -196,7 +200,48 @@ generation:
196
200
  ios: "../kmp-ui/iosApp/"
197
201
  ```
198
202
 
199
- Paths are relative to `openuispec.yaml`. The `.openuispec-state.json` file is stored inside each output directory.
203
+ Paths are relative to `openuispec.yaml`. The `.openuispec-state.json` file is stored inside each output directory and records spec file hashes plus the git baseline commit metadata captured at snapshot time.
204
+
205
+ `openuispec drift --snapshot --target <target>` requires that target output directory to already exist. If it does not, generate the target code first, then snapshot the accepted baseline.
206
+
207
+ Use the commands like this:
208
+ - `openuispec validate` checks schema correctness
209
+ - `openuispec validate semantic` checks cross-references such as locale keys, formatters, mappers, contracts, icons, navigation targets, and API endpoints
210
+ - `openuispec drift --target <t> --explain` explains semantic spec changes since that target's accepted baseline
211
+ - `openuispec prepare --target <t>` turns those changes into an AI-ready target update bundle
212
+ - `openuispec status` shows every target's snapshot state, baseline commit, and whether that target is behind the current spec, still needs a baseline, or has not been generated yet
213
+
214
+ If a target snapshot was created before baseline metadata was added, `--explain` and `status` will tell you to re-run `openuispec drift --snapshot --target <target>` for that target.
215
+
216
+ ## Target update workflow
217
+
218
+ When a shared spec change needs to be applied to a target:
219
+
220
+ ```bash
221
+ openuispec validate
222
+ openuispec drift --target ios --explain
223
+ openuispec prepare --target ios
224
+ # update the ios implementation
225
+ # ensure the ios output directory already exists
226
+ openuispec drift --snapshot --target ios
227
+ ```
228
+
229
+ Meaning:
230
+ - `validate` checks schema correctness
231
+ - `validate semantic` checks cross-reference integrity
232
+ - `drift --explain` shows semantic spec changes since that target's accepted baseline
233
+ - `prepare` packages those changes into an AI/developer work bundle
234
+ - `drift --snapshot` accepts the updated state after the target UI has been updated and the target output directory exists
235
+
236
+ Before picking the next platform to update, run:
237
+
238
+ ```bash
239
+ openuispec status
240
+ ```
241
+
242
+ to see which targets are already up to date and which ones still need to catch up with shared spec changes.
243
+
244
+ `drift --snapshot` is bookkeeping. It does not prove that the target code matches the spec, and it will not create a missing target output directory for you.
200
245
 
201
246
  ## Spec at a glance
202
247
 
package/cli/index.ts CHANGED
@@ -5,7 +5,10 @@
5
5
  * Usage:
6
6
  * openuispec init Create a new spec project
7
7
  * openuispec drift [--target <t>] Check for spec drift
8
- * openuispec drift --snapshot --target <t> Snapshot current state
8
+ * openuispec drift --snapshot --target <t> Snapshot current state + git baseline
9
+ * openuispec drift --target <t> --explain Explain semantic changes since baseline
10
+ * openuispec prepare --target <t> Build an AI-ready target update bundle
11
+ * openuispec status Show cross-target baseline/drift status
9
12
  * openuispec validate [group...] Validate spec files against schemas
10
13
  */
11
14
 
@@ -55,6 +58,18 @@ async function main(): Promise<void> {
55
58
  break;
56
59
  }
57
60
 
61
+ case "prepare": {
62
+ const { runPrepare } = await import("../prepare/index.js");
63
+ runPrepare(rest);
64
+ break;
65
+ }
66
+
67
+ case "status": {
68
+ const { runStatus } = await import("../status/index.js");
69
+ runStatus(rest);
70
+ break;
71
+ }
72
+
58
73
  case "validate": {
59
74
  const { runValidate } = await import("../schema/validate.js");
60
75
  runValidate(rest);
@@ -72,10 +87,13 @@ Usage:
72
87
  openuispec init Create a new spec project
73
88
  openuispec update-rules Update AI rules to match installed version
74
89
  openuispec drift [--target <t>] Check for spec drift
75
- openuispec drift --snapshot --target <t> Snapshot current state
90
+ openuispec drift --snapshot --target <t> Snapshot current state + git baseline
91
+ openuispec drift --target <t> --explain Explain semantic changes since baseline
92
+ openuispec prepare --target <t> Build an AI-ready target update bundle
93
+ openuispec status Show cross-target baseline/drift status
76
94
  openuispec validate [group...] Validate spec files
77
95
 
78
- Validate groups: manifest, tokens, screens, flows, platform, locales, contracts
96
+ Validate groups: manifest, tokens, screens, flows, platform, locales, contracts, semantic
79
97
 
80
98
  Docs: https://openuispec.rsteam.uz
81
99
  `);
package/cli/init.ts CHANGED
@@ -171,16 +171,19 @@ Do NOT guess the file format — skipping this step will produce invalid YAML th
171
171
  **Reference files inside the package (read in this order):**
172
172
  1. \`README.md\` — schema tables, file format reference, root keys
173
173
  2. \`spec/openuispec-v0.1.md\` — full specification (contracts, layout, expressions, etc.)
174
- 3. \`examples/taskflow/\` — complete working example with all file types
174
+ 3. \`examples/taskflow/openuispec/\` — complete working example with all file types
175
175
  4. \`schema/\` — JSON Schemas for validation
176
176
 
177
177
  ## CLI commands
178
178
 
179
179
  \`\`\`bash
180
180
  openuispec validate # Validate spec files against schemas
181
+ openuispec validate semantic # Run semantic cross-reference linting
181
182
  openuispec validate screens # Validate only screens
182
- openuispec drift --target ${targets[0]} # Check for spec drift
183
- openuispec drift --snapshot --target ${targets[0]} # Snapshot current state
183
+ openuispec status # Show cross-target baseline/drift status
184
+ openuispec drift --target ${targets[0]} --explain # Explain semantic spec drift
185
+ openuispec prepare --target ${targets[0]} # Build an AI-ready target update bundle
186
+ openuispec drift --snapshot --target ${targets[0]} # Snapshot current state + git baseline after target output exists
184
187
  \`\`\`
185
188
 
186
189
  ## Learn more
@@ -215,7 +218,7 @@ Do NOT guess the file format — skipping this step will produce invalid YAML th
215
218
  **Reference files inside the package (read in this order):**
216
219
  1. \`README.md\` — schema tables, file format reference, root wrapper keys
217
220
  2. \`spec/openuispec-v0.1.md\` — full specification (contracts, layout, expressions, adaptive, etc.)
218
- 3. \`examples/taskflow/\` — complete working example with all file types
221
+ 3. \`examples/taskflow/openuispec/\` — complete working example with all file types
219
222
  4. \`schema/\` — JSON Schemas for every file type
220
223
 
221
224
  These files are updated with each package version. Always read from the installed package,
@@ -269,9 +272,13 @@ Spec-first workflow:
269
272
  2. Update the spec first.
270
273
  3. Update the affected generated/native UI code to match the spec.
271
274
  4. Run \`openuispec validate\`.
272
- 5. Verify the affected UI targets build/run if possible.
273
- 6. Only then run \`openuispec drift --snapshot --target <target>\` for affected targets.
274
- 7. Run \`openuispec drift --target <target>\` as a bookkeeping check.
275
+ 5. Run \`openuispec validate semantic\`.
276
+ 6. Run \`openuispec drift --target <target> --explain\` to inspect semantic changes since that target's baseline.
277
+ 7. Run \`openuispec prepare --target <target>\` to build the AI/developer work bundle for that target.
278
+ 8. Verify the affected UI targets build/run if possible.
279
+ 9. Only then run \`openuispec drift --snapshot --target <target>\` for affected targets, after that target output directory exists.
280
+ 10. Run \`openuispec drift --target <target> --explain\` again to confirm no spec changes remain for that target.
281
+ 11. Use \`openuispec status\` to see which other targets are still behind the updated spec.
275
282
 
276
283
  ### Start from platform code when:
277
284
  - the change is platform-specific polish
@@ -286,13 +293,18 @@ Platform-first workflow:
286
293
  ### Never do this:
287
294
  - Do not snapshot drift immediately after changing spec unless the UI code has also been updated.
288
295
  - Do not treat \`openuispec drift\` as proof that generated UI matches the spec.
296
+ - Do not skip \`--explain\` / \`prepare\` when another platform needs to catch up with shared spec changes.
289
297
  - Do not modify generated UI without checking whether the spec must change first.
290
298
 
291
299
  ## CLI commands
292
300
  - \`openuispec init\` — scaffold a new spec project
293
301
  - \`openuispec validate [group...]\` — validate spec files against schemas
302
+ - \`openuispec validate semantic\` — run semantic cross-reference linting
294
303
  - \`openuispec drift --target <t>\` — check for spec drift
295
- - \`openuispec drift --snapshot --target <t>\`snapshot current state
304
+ - \`openuispec drift --target <t> --explain\` explain semantic spec drift since the target baseline
305
+ - \`openuispec drift --snapshot --target <t>\` — snapshot current state after the target output exists
306
+ - \`openuispec prepare --target <t>\` — build an AI-ready target update bundle
307
+ - \`openuispec status\` — show cross-target baseline/drift status
296
308
  - \`openuispec update-rules\` — update AI rules to match installed package version
297
309
  - \`openuispec drift --all\` — include stubs in drift check
298
310
  ${RULES_END_MARKER}
@@ -499,7 +511,7 @@ Getting started (new project):
499
511
  2. Create screens in ${specDir}/screens/ (one YAML per screen)
500
512
  3. Create flows in ${specDir}/flows/ (multi-step navigation)
501
513
  4. Ask AI to generate native code from the spec
502
- 5. Run \`openuispec drift --snapshot --target ${targets[0]}\` to baseline
514
+ 5. Run \`openuispec drift --snapshot --target ${targets[0]}\` to baseline the first accepted target state after that target output directory exists
503
515
 
504
516
  Getting started (existing project):
505
517
  1. Ask AI to read your existing UI code and generate spec files:
@@ -507,11 +519,15 @@ Getting started (existing project):
507
519
  2. Spec screens incrementally: stub → draft → ready
508
520
  3. Only ready/draft screens are tracked by drift detection
509
521
  4. Run \`openuispec validate\` to check specs against the schema
522
+ 5. Use \`openuispec drift --target ${targets[0]} --explain\` and \`openuispec prepare --target ${targets[0]}\` before asking AI to update a target
510
523
 
511
524
  Commands:
512
525
  openuispec validate Validate spec files
513
- openuispec drift --target ios Check for spec changes
514
- openuispec drift --snapshot --target ios Save current state
526
+ openuispec validate semantic Check semantic cross-references
527
+ openuispec status Show cross-target baseline/drift status
528
+ openuispec drift --target ios --explain Explain semantic spec changes
529
+ openuispec prepare --target ios Build an AI-ready target update bundle
530
+ openuispec drift --snapshot --target ios Save current state + git baseline after target output exists
515
531
 
516
532
  AI rules have been added to CLAUDE.md and AGENTS.md.
517
533
 
@@ -0,0 +1,119 @@
1
+ # Implementation Notes
2
+
3
+ ## Drift baseline metadata
4
+
5
+ - `.openuispec-state.json` now stores:
6
+ - spec file hashes
7
+ - snapshot timestamp
8
+ - target
9
+ - git baseline metadata: `kind`, `commit`, `branch`
10
+ - Snapshot behavior:
11
+ - `kind: git_commit` means the tracked spec files matched `HEAD` exactly at snapshot time
12
+ - `kind: working_tree` means the snapshot was taken from a dirty spec working tree
13
+ - This baseline metadata is a pointer to the accepted spec state for a target. It is not a proof that the target UI code is aligned.
14
+ - Backward compatibility:
15
+ - older `.openuispec-state.json` files do not include `baseline`
16
+ - `drift --explain` and `status` must report that clearly and ask the user to re-run `openuispec drift --snapshot --target <target>`
17
+ - hash-only snapshots are still valid for basic drift counts
18
+
19
+ ## Drift `--explain`
20
+
21
+ - Document that `openuispec drift --target <target> --explain` explains **spec changes since that target's own snapshot baseline**, not platform code changes.
22
+ - Call out the common cross-platform workflow:
23
+ - iOS developer updates shared spec and iOS code, then snapshots only `ios`
24
+ - Android developer pulls later without updating `generated/android/.../.openuispec-state.json`
25
+ - `openuispec drift --target android --explain` should then show the shared spec changes Android still needs to apply
26
+ - Clarify that if another developer also updates and commits a target's `.openuispec-state.json`, that target will no longer see those spec changes as drift.
27
+ - Clarify that `--explain` requires an exact `git_commit` baseline. If the snapshot was taken from a dirty working tree, explanations are intentionally unavailable until the target is re-snapshotted from a clean commit.
28
+ - Current behavior:
29
+ - compares baseline spec files from git to current working-tree spec files
30
+ - parses YAML/JSON semantically
31
+ - reports property-level changes
32
+ - text and JSON output both include semantic explanations
33
+ - Current limitation:
34
+ - explanations are spec-only
35
+ - no platform-code verification is attempted
36
+
37
+ ## `prepare` command
38
+
39
+ - `openuispec prepare --target <target>` is the operational bridge between spec drift and AI implementation work.
40
+ - It should be documented as:
41
+ 1. read the target's snapshot baseline
42
+ 2. compute semantic spec changes since that baseline
43
+ 3. produce an AI-ready bundle with likely target scope
44
+ - Current output includes:
45
+ - project and target
46
+ - output directory
47
+ - likely code roots
48
+ - baseline commit info
49
+ - semantic change summary
50
+ - per-spec-file work items
51
+ - best-effort candidate target files
52
+ - next-step guidance
53
+ - Important positioning:
54
+ - `prepare` does not generate code
55
+ - `prepare` does not verify code correctness
56
+ - `prepare` packages the spec delta into scoped implementation work for AI or developers
57
+
58
+ ## Semantic linting
59
+
60
+ - `openuispec validate semantic` is now the high-signal semantic consistency pass on top of schema validation.
61
+ - Current checks:
62
+ - locale key references from `$t:...`
63
+ - formatter references from `format:...`
64
+ - mapper references from `map:...`
65
+ - contract references
66
+ - icon references
67
+ - screen/flow destination references
68
+ - API endpoint references
69
+ - submit-form `form_id` references
70
+ - locale coverage against the default locale
71
+ - Token validation behavior:
72
+ - validates app-level references for `color.*`, `spacing.*`, `typography.*`, and `elevation.*`
73
+ - token resolution is normalized to actual token-family shapes, not raw YAML object paths
74
+ - skips dynamic token expressions such as `color.priority.{task.priority}`
75
+ - skips token-default checking inside contract definition files to avoid false positives on contract-local token names
76
+ - Icon validation behavior:
77
+ - uses icon registry + custom icons + declared variant suffixes
78
+ - treats generated variants like `checkmark_list_fill` as valid when the base icon exists and `_fill` is a declared suffix
79
+ - skips dynamic/data-driven icon strings such as `item.icon` or `{project.icon}`
80
+ - Current limitation:
81
+ - semantic lint is intentionally heuristic
82
+ - it validates stable cross-references, not full behavioral correctness
83
+
84
+ ## `status` command
85
+
86
+ - `openuispec status` is the cross-target overview command.
87
+ - Current output includes, per target:
88
+ - output directory
89
+ - whether the output directory exists
90
+ - snapshot present or missing
91
+ - snapshot timestamp
92
+ - baseline kind / commit / branch
93
+ - changed / added / removed spec file counts
94
+ - `behind` boolean
95
+ - `explain_available` boolean
96
+ - note for missing or legacy snapshots
97
+ - Important positioning:
98
+ - `status` answers "which targets are behind shared spec changes?"
99
+ - `status` should distinguish "needs generation" from "needs baseline"
100
+ - `status` does not verify code alignment
101
+ - Real-world behavior to document:
102
+ - if `web` was re-snapshotted after the new baseline metadata was added, but `ios` and `android` still have older state files, `status` should show:
103
+ - `web`: baseline available, explain available
104
+ - `ios` / `android`: snapshot exists, but no baseline metadata, explain unavailable with re-snapshot note
105
+
106
+ ## Workflow docs follow-up
107
+
108
+ - Recommended target workflow now is:
109
+ 1. `openuispec validate`
110
+ 2. `openuispec validate semantic`
111
+ 3. `openuispec status`
112
+ 4. `openuispec drift --target <target> --explain`
113
+ 5. `openuispec prepare --target <target>`
114
+ 6. update target UI code
115
+ 7. build/run and review
116
+ 8. ensure the target output directory exists
117
+ 9. `openuispec drift --snapshot --target <target>`
118
+ - `drift --snapshot` should continue to be described as bookkeeping/baselining, not as proof that the target implementation matches the spec.
119
+ - If the target output directory does not exist yet, the CLI should direct the user to run code generation first instead of implying that snapshot can initialize an empty target.
@@ -0,0 +1,64 @@
1
+ # OpenUISpec v0.1.26
2
+
3
+ This release expands OpenUISpec as a spec-management and AI-orchestration tool for multi-platform UI work.
4
+
5
+ ## New features
6
+
7
+ - `openuispec drift --target <target> --explain`
8
+ Explains semantic spec changes since a target's accepted baseline instead of only reporting file drift.
9
+
10
+ - Git baseline metadata in `.openuispec-state.json`
11
+ Drift snapshots now record the git baseline commit and branch for each target.
12
+
13
+ - `openuispec prepare --target <target>`
14
+ Produces an AI-ready target update bundle with:
15
+ - semantic change summary
16
+ - likely code roots
17
+ - candidate target files
18
+ - next-step guidance
19
+
20
+ - `openuispec validate semantic`
21
+ Adds semantic cross-reference linting for:
22
+ - locale keys
23
+ - formatter refs
24
+ - mapper refs
25
+ - contract refs
26
+ - icon refs
27
+ - navigation targets
28
+ - API endpoint refs
29
+ - submit-form refs
30
+
31
+ - `openuispec status`
32
+ Shows cross-target snapshot state, baseline metadata, and which targets are behind the current spec.
33
+
34
+ ## Workflow updates
35
+
36
+ Recommended target workflow is now:
37
+
38
+ 1. `openuispec validate`
39
+ 2. `openuispec validate semantic`
40
+ 3. `openuispec status`
41
+ 4. `openuispec drift --target <target> --explain`
42
+ 5. `openuispec prepare --target <target>`
43
+ 6. update target UI
44
+ 7. `openuispec drift --snapshot --target <target>`
45
+
46
+ `drift --snapshot` remains a bookkeeping step. It does not prove target code alignment.
47
+
48
+ ## Docs and rule updates
49
+
50
+ - Public README updated for `--explain`, `prepare`, `validate semantic`, and `status`
51
+ - Project scaffolding/rules updated in `init`
52
+ - Sample AI rules and sample spec README updated to match the new workflow
53
+
54
+ ## Reliability improvements
55
+
56
+ - Added regression tests for:
57
+ - `drift --explain` + `prepare`
58
+ - semantic linting
59
+ - cross-target `status`
60
+ - CI now runs the test suite in addition to schema validation
61
+
62
+ ## Sample fix
63
+
64
+ - Fixed Todo Orbit sample semantic linting by adding the missing `pencil` icon token
@@ -0,0 +1,28 @@
1
+ # OpenUISpec v0.1.27
2
+
3
+ This patch supersedes `v0.1.26`.
4
+
5
+ ## Fix
6
+
7
+ - Fixed npm install / publish lifecycle breakage caused by naming the repo script `prepare`.
8
+ - The package now uses `prepare:target` for the repo-local helper script.
9
+ - `openuispec prepare --target <target>` remains the CLI command.
10
+
11
+ ## Includes from v0.1.26
12
+
13
+ - `openuispec drift --target <target> --explain`
14
+ - git baseline metadata in `.openuispec-state.json`
15
+ - `openuispec prepare --target <target>`
16
+ - `openuispec validate semantic`
17
+ - `openuispec status`
18
+ - updated workflow docs, AI rules, tests, CI, and sample fixes
19
+
20
+ ## Recommended workflow
21
+
22
+ 1. `openuispec validate`
23
+ 2. `openuispec validate semantic`
24
+ 3. `openuispec status`
25
+ 4. `openuispec drift --target <target> --explain`
26
+ 5. `openuispec prepare --target <target>`
27
+ 6. update target UI
28
+ 7. `openuispec drift --snapshot --target <target>`
@@ -0,0 +1,25 @@
1
+ # OpenUISpec v0.1.28
2
+
3
+ This patch supersedes `v0.1.27`.
4
+
5
+ ## Fixes
6
+
7
+ - Fixed the drift/prepare onboarding dead-end for targets that have not been generated yet.
8
+ - `drift --snapshot` now keeps the guard against baselining an empty target.
9
+ - Missing-snapshot guidance now tells users to generate the target output first when the output directory does not exist.
10
+ - Improved `status` to distinguish:
11
+ - targets that need generation
12
+ - targets that need a baseline snapshot
13
+ - Updated workflow docs and generated project templates to describe the generation-first requirement before snapshotting.
14
+ - Stabilized the affected CLI tests in this repo by invoking TypeScript entrypoints through the `tsx` loader path instead of the IPC-based binary wrapper.
15
+
16
+ ## Recommended workflow
17
+
18
+ 1. `openuispec validate`
19
+ 2. `openuispec validate semantic`
20
+ 3. `openuispec status`
21
+ 4. `openuispec drift --target <target> --explain`
22
+ 5. `openuispec prepare --target <target>`
23
+ 6. update target UI
24
+ 7. ensure the target output directory exists
25
+ 8. `openuispec drift --snapshot --target <target>`
@@ -14,7 +14,7 @@ This assessment stress-tested the project at four layers:
14
14
 
15
15
  ```bash
16
16
  npm ci
17
- npm run validate # from examples/taskflow (workspace script)
17
+ npm run validate # from examples/taskflow/openuispec (workspace script)
18
18
  npx tsx ../../../schema/validate.ts # from examples/todo-orbit/openuispec
19
19
  npx tsc --noEmit
20
20
  for t in ios android web; do