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.
- package/README.md +63 -18
- package/cli/index.ts +21 -3
- package/cli/init.ts +27 -11
- package/docs/implementation-notes.md +119 -0
- package/docs/release-notes-v0.1.26.md +64 -0
- package/docs/release-notes-v0.1.27.md +28 -0
- package/docs/release-notes-v0.1.28.md +25 -0
- package/docs/stress-test-maturity-report.md +1 -1
- package/drift/index.ts +396 -22
- package/examples/taskflow/AGENTS.md +112 -0
- package/examples/taskflow/CLAUDE.md +112 -0
- package/examples/taskflow/generated/android/TaskFlow/README.md +43 -0
- package/examples/taskflow/generated/android/TaskFlow/app/build.gradle.kts +76 -0
- package/examples/taskflow/generated/android/TaskFlow/app/proguard-rules.pro +1 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/AndroidManifest.xml +21 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/MainActivity.kt +19 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/TaskFlowApp.kt +283 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/model/DomainModels.kt +106 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/model/SampleData.kt +57 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/components/Common.kt +109 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/HomeScreen.kt +112 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/ProjectsScreen.kt +61 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/SettingsScreen.kt +82 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/TaskDetailScreen.kt +111 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/sheets/Sheets.kt +77 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Color.kt +30 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Theme.kt +86 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Type.kt +57 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/res/values/strings.xml +155 -0
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/res/values/themes.xml +4 -0
- package/examples/taskflow/generated/android/TaskFlow/build.gradle.kts +5 -0
- package/examples/taskflow/generated/android/TaskFlow/gradle/gradle-daemon-jvm.properties +12 -0
- package/examples/taskflow/generated/android/TaskFlow/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/examples/taskflow/generated/android/TaskFlow/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/examples/taskflow/generated/android/TaskFlow/gradle.properties +4 -0
- package/examples/taskflow/generated/android/TaskFlow/gradlew +18 -0
- package/examples/taskflow/generated/android/TaskFlow/gradlew.bat +12 -0
- package/examples/taskflow/generated/android/TaskFlow/settings.gradle.kts +18 -0
- package/examples/taskflow/generated/ios/TaskFlow/README.md +21 -0
- package/examples/taskflow/generated/ios/TaskFlow/Resources/en.lproj/Localizable.strings +115 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/App/TaskFlowApp.swift +24 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Components/AppChrome.swift +150 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Flows/TaskEditorSheet.swift +220 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Models/DomainModels.swift +122 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/CalendarView.swift +21 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/HomeView.swift +201 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProfileEditView.swift +48 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProjectDetailView.swift +59 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProjectsView.swift +63 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/SettingsView.swift +85 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/TaskDetailView.swift +219 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Support/AppModel.swift +320 -0
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Support/AppSupport.swift +41 -0
- package/examples/taskflow/generated/ios/TaskFlow/project.yml +26 -0
- package/examples/taskflow/generated/web/TaskFlow/README.md +19 -0
- package/examples/taskflow/generated/web/TaskFlow/index.html +12 -0
- package/examples/taskflow/generated/web/TaskFlow/package-lock.json +1908 -0
- package/examples/taskflow/generated/web/TaskFlow/package.json +24 -0
- package/examples/taskflow/generated/web/TaskFlow/src/App.tsx +58 -0
- package/examples/taskflow/generated/web/TaskFlow/src/AppShell.tsx +55 -0
- package/examples/taskflow/generated/web/TaskFlow/src/components/Common.tsx +82 -0
- package/examples/taskflow/generated/web/TaskFlow/src/components/Modals.tsx +191 -0
- package/examples/taskflow/generated/web/TaskFlow/src/components/Nav.tsx +41 -0
- package/examples/taskflow/generated/web/TaskFlow/src/generated/messages.ts +131 -0
- package/examples/taskflow/generated/web/TaskFlow/src/hooks.ts +25 -0
- package/examples/taskflow/generated/web/TaskFlow/src/i18n.ts +39 -0
- package/examples/taskflow/generated/web/TaskFlow/src/locales.en.json +111 -0
- package/examples/taskflow/generated/web/TaskFlow/src/main.tsx +13 -0
- package/examples/taskflow/generated/web/TaskFlow/src/screens/HomeScreen.tsx +111 -0
- package/examples/taskflow/generated/web/TaskFlow/src/screens/ProjectsScreen.tsx +82 -0
- package/examples/taskflow/generated/web/TaskFlow/src/screens/SettingsScreens.tsx +132 -0
- package/examples/taskflow/generated/web/TaskFlow/src/screens/TaskDetail.tsx +105 -0
- package/examples/taskflow/generated/web/TaskFlow/src/store.ts +216 -0
- package/examples/taskflow/generated/web/TaskFlow/src/styles.css +617 -0
- package/examples/taskflow/generated/web/TaskFlow/src/types.ts +64 -0
- package/examples/taskflow/generated/web/TaskFlow/src/utils.ts +78 -0
- package/examples/taskflow/generated/web/TaskFlow/tsconfig.json +21 -0
- package/examples/taskflow/generated/web/TaskFlow/vite.config.ts +6 -0
- package/examples/taskflow/openuispec/README.md +49 -0
- package/examples/todo-orbit/AGENTS.md +46 -14
- package/examples/todo-orbit/CLAUDE.md +46 -14
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/components/CommonComponents.kt +69 -18
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/TasksScreen.kt +5 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/sheets/EditorSheets.kt +5 -2
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values/strings.xml +1 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values-ru/strings.xml +1 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/en.lproj/Localizable.strings +1 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/ru.lproj/Localizable.strings +1 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/RecurringRuleSheet.swift +3 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/TaskEditorSheet.swift +1 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/SettingsView.swift +2 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/TasksHomeView.swift +1 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Support/AppModel.swift +1 -1
- package/examples/todo-orbit/generated/web/Todo Orbit/src/App.tsx +59 -6
- package/examples/todo-orbit/generated/web/Todo Orbit/src/styles.css +40 -0
- package/examples/todo-orbit/openuispec/README.md +24 -131
- package/examples/todo-orbit/openuispec/flows/create_recurring_rule.yaml +3 -0
- package/examples/todo-orbit/openuispec/flows/create_task.yaml +1 -0
- package/examples/todo-orbit/openuispec/flows/edit_task.yaml +1 -0
- package/examples/todo-orbit/openuispec/locales/en.json +1 -0
- package/examples/todo-orbit/openuispec/locales/ru.json +1 -0
- package/examples/todo-orbit/openuispec/screens/task_detail.yaml +1 -0
- package/examples/todo-orbit/openuispec/tokens/icons.yaml +6 -0
- package/package.json +6 -1
- package/prepare/index.ts +391 -0
- package/schema/semantic-lint.ts +592 -0
- package/schema/validate.ts +17 -13
- package/status/index.ts +200 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/README.md +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/action_trigger.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/collection.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/data_display.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/feedback.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/input_field.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/nav_container.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/surface.yaml +0 -0
- /package/examples/taskflow/{contracts → openuispec/contracts}/x_media_player.yaml +0 -0
- /package/examples/taskflow/{flows → openuispec/flows}/create_task.yaml +0 -0
- /package/examples/taskflow/{flows → openuispec/flows}/edit_task.yaml +0 -0
- /package/examples/taskflow/{locales → openuispec/locales}/en.json +0 -0
- /package/examples/taskflow/{openuispec.yaml → openuispec/openuispec.yaml} +0 -0
- /package/examples/taskflow/{platform → openuispec/platform}/android.yaml +0 -0
- /package/examples/taskflow/{platform → openuispec/platform}/ios.yaml +0 -0
- /package/examples/taskflow/{platform → openuispec/platform}/web.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/calendar.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/home.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/profile_edit.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/project_detail.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/projects.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/settings.yaml +0 -0
- /package/examples/taskflow/{screens → openuispec/screens}/task_detail.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/color.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/elevation.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/icons.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/layout.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/motion.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/spacing.yaml +0 -0
- /package/examples/taskflow/{tokens → openuispec/tokens}/themes.yaml +0 -0
- /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
|
|
183
|
-
openuispec drift --
|
|
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.
|
|
273
|
-
6.
|
|
274
|
-
7. Run \`openuispec
|
|
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 --
|
|
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
|
|
514
|
-
openuispec
|
|
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
|