openuispec 0.1.45 → 0.1.47

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 (138) hide show
  1. package/README.md +17 -5
  2. package/cli/init.ts +21 -3
  3. package/examples/social-app/.mcp.json +10 -0
  4. package/examples/social-app/AGENTS.md +114 -0
  5. package/examples/social-app/CLAUDE.md +114 -0
  6. package/examples/social-app/README.md +19 -0
  7. package/examples/social-app/backend/.gitkeep +1 -0
  8. package/examples/social-app/generated/android/social-app/app/build.gradle.kts +92 -0
  9. package/examples/social-app/generated/android/social-app/app/src/main/AndroidManifest.xml +26 -0
  10. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/AppContainer.kt +20 -0
  11. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/MainActivity.kt +35 -0
  12. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/SocialAppApplication.kt +13 -0
  13. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/MockData.kt +98 -0
  14. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/AppPreferences.kt +19 -0
  15. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/DataStorePreferencesRepository.kt +68 -0
  16. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/PreferencesRepository.kt +15 -0
  17. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/model/Models.kt +34 -0
  18. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/MainShell.kt +390 -0
  19. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/components/Components.kt +234 -0
  20. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/components/ContractPrimitives.kt +641 -0
  21. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/navigation/RootComponent.kt +113 -0
  22. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/ChatDetailScreen.kt +212 -0
  23. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/CreatePostScreen.kt +113 -0
  24. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/DiscoverScreen.kt +137 -0
  25. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/EditProfileScreen.kt +180 -0
  26. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/HomeFeedScreen.kt +157 -0
  27. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/MessagesInboxScreen.kt +85 -0
  28. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/NotificationsScreen.kt +74 -0
  29. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/PostDetailScreen.kt +293 -0
  30. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/ProfileSelfScreen.kt +116 -0
  31. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SearchResultsScreen.kt +161 -0
  32. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SettingsScreen.kt +164 -0
  33. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SettingsStore.kt +95 -0
  34. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/UserProfileScreen.kt +123 -0
  35. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Color.kt +33 -0
  36. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Shape.kt +41 -0
  37. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Spacing.kt +20 -0
  38. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Theme.kt +82 -0
  39. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Type.kt +60 -0
  40. package/examples/social-app/generated/android/social-app/app/src/main/res/drawable/ic_launcher_foreground.xml +9 -0
  41. package/examples/social-app/generated/android/social-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  42. package/examples/social-app/generated/android/social-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
  43. package/examples/social-app/generated/android/social-app/app/src/main/res/values/strings.xml +91 -0
  44. package/examples/social-app/generated/android/social-app/app/src/main/res/values/themes.xml +10 -0
  45. package/examples/social-app/generated/android/social-app/app/src/main/res/values-ru/strings.xml +79 -0
  46. package/examples/social-app/generated/android/social-app/app/src/main/res/values-uz/strings.xml +79 -0
  47. package/examples/social-app/generated/android/social-app/app/src/main/xml/AndroidManifest.xml +23 -0
  48. package/examples/social-app/generated/android/social-app/build.gradle.kts +6 -0
  49. package/examples/social-app/generated/android/social-app/gradle/libs.versions.toml +48 -0
  50. package/examples/social-app/generated/android/social-app/gradle/wrapper/gradle-wrapper.properties +8 -0
  51. package/examples/social-app/generated/android/social-app/gradle.properties +11 -0
  52. package/examples/social-app/generated/android/social-app/gradlew +25 -0
  53. package/examples/social-app/generated/android/social-app/settings.gradle.kts +23 -0
  54. package/examples/social-app/generated/web/social-app/index.html +12 -0
  55. package/examples/social-app/generated/web/social-app/package-lock.json +2517 -0
  56. package/examples/social-app/generated/web/social-app/package.json +27 -0
  57. package/examples/social-app/generated/web/social-app/src/app/App.tsx +58 -0
  58. package/examples/social-app/generated/web/social-app/src/components/Shell.tsx +259 -0
  59. package/examples/social-app/generated/web/social-app/src/components/cards.tsx +317 -0
  60. package/examples/social-app/generated/web/social-app/src/components/ui.tsx +340 -0
  61. package/examples/social-app/generated/web/social-app/src/flows/CreatePostFlow.tsx +86 -0
  62. package/examples/social-app/generated/web/social-app/src/i18n.tsx +59 -0
  63. package/examples/social-app/generated/web/social-app/src/lib/icons.tsx +85 -0
  64. package/examples/social-app/generated/web/social-app/src/lib/tokens.ts +70 -0
  65. package/examples/social-app/generated/web/social-app/src/lib/utils.ts +97 -0
  66. package/examples/social-app/generated/web/social-app/src/locales/en.json +67 -0
  67. package/examples/social-app/generated/web/social-app/src/locales/ru.json +67 -0
  68. package/examples/social-app/generated/web/social-app/src/locales/uz.json +67 -0
  69. package/examples/social-app/generated/web/social-app/src/main.tsx +16 -0
  70. package/examples/social-app/generated/web/social-app/src/screens/ChatDetailScreen.tsx +90 -0
  71. package/examples/social-app/generated/web/social-app/src/screens/DiscoverScreen.tsx +86 -0
  72. package/examples/social-app/generated/web/social-app/src/screens/EditProfileScreen.tsx +57 -0
  73. package/examples/social-app/generated/web/social-app/src/screens/HomeFeedScreen.tsx +103 -0
  74. package/examples/social-app/generated/web/social-app/src/screens/MessagesInboxScreen.tsx +52 -0
  75. package/examples/social-app/generated/web/social-app/src/screens/NotificationsScreen.tsx +41 -0
  76. package/examples/social-app/generated/web/social-app/src/screens/PostDetailScreen.tsx +115 -0
  77. package/examples/social-app/generated/web/social-app/src/screens/ProfileSelfScreen.tsx +57 -0
  78. package/examples/social-app/generated/web/social-app/src/screens/ProfileUserScreen.tsx +76 -0
  79. package/examples/social-app/generated/web/social-app/src/screens/SearchResultsScreen.tsx +96 -0
  80. package/examples/social-app/generated/web/social-app/src/screens/SettingsScreen.tsx +79 -0
  81. package/examples/social-app/generated/web/social-app/src/state/store.ts +592 -0
  82. package/examples/social-app/generated/web/social-app/src/styles.css +124 -0
  83. package/examples/social-app/generated/web/social-app/src/vite-env.d.ts +1 -0
  84. package/examples/social-app/generated/web/social-app/tsconfig.json +22 -0
  85. package/examples/social-app/generated/web/social-app/tsconfig.node.json +13 -0
  86. package/examples/social-app/generated/web/social-app/tsconfig.node.tsbuildinfo +1 -0
  87. package/examples/social-app/generated/web/social-app/tsconfig.tsbuildinfo +1 -0
  88. package/examples/social-app/generated/web/social-app/vite.config.d.ts +2 -0
  89. package/examples/social-app/generated/web/social-app/vite.config.js +6 -0
  90. package/examples/social-app/generated/web/social-app/vite.config.ts +7 -0
  91. package/examples/social-app/openuispec/README.md +56 -0
  92. package/examples/social-app/openuispec/contracts/.gitkeep +0 -0
  93. package/examples/social-app/openuispec/contracts/action_trigger.yaml +104 -0
  94. package/examples/social-app/openuispec/contracts/collection.yaml +43 -0
  95. package/examples/social-app/openuispec/contracts/data_display.yaml +47 -0
  96. package/examples/social-app/openuispec/contracts/feedback.yaml +49 -0
  97. package/examples/social-app/openuispec/contracts/input_field.yaml +41 -0
  98. package/examples/social-app/openuispec/contracts/nav_container.yaml +34 -0
  99. package/examples/social-app/openuispec/contracts/surface.yaml +41 -0
  100. package/examples/social-app/openuispec/flows/.gitkeep +0 -0
  101. package/examples/social-app/openuispec/flows/create_post.yaml +66 -0
  102. package/examples/social-app/openuispec/locales/.gitkeep +0 -0
  103. package/examples/social-app/openuispec/locales/en.json +67 -0
  104. package/examples/social-app/openuispec/locales/ru.json +67 -0
  105. package/examples/social-app/openuispec/locales/uz.json +67 -0
  106. package/examples/social-app/openuispec/openuispec.yaml +214 -0
  107. package/examples/social-app/openuispec/platform/.gitkeep +0 -0
  108. package/examples/social-app/openuispec/platform/android.yaml +30 -0
  109. package/examples/social-app/openuispec/platform/ios.yaml +19 -0
  110. package/examples/social-app/openuispec/platform/web.yaml +23 -0
  111. package/examples/social-app/openuispec/screens/.gitkeep +0 -0
  112. package/examples/social-app/openuispec/screens/chat_detail.yaml +53 -0
  113. package/examples/social-app/openuispec/screens/discover.yaml +78 -0
  114. package/examples/social-app/openuispec/screens/edit_profile.yaml +78 -0
  115. package/examples/social-app/openuispec/screens/home_feed.yaml +138 -0
  116. package/examples/social-app/openuispec/screens/messages_inbox.yaml +43 -0
  117. package/examples/social-app/openuispec/screens/notifications.yaml +29 -0
  118. package/examples/social-app/openuispec/screens/post_detail.yaml +86 -0
  119. package/examples/social-app/openuispec/screens/profile_self.yaml +53 -0
  120. package/examples/social-app/openuispec/screens/profile_user.yaml +60 -0
  121. package/examples/social-app/openuispec/screens/search_results.yaml +62 -0
  122. package/examples/social-app/openuispec/screens/settings.yaml +99 -0
  123. package/examples/social-app/openuispec/tokens/.gitkeep +0 -0
  124. package/examples/social-app/openuispec/tokens/color.yaml +76 -0
  125. package/examples/social-app/openuispec/tokens/elevation.yaml +31 -0
  126. package/examples/social-app/openuispec/tokens/icons.yaml +147 -0
  127. package/examples/social-app/openuispec/tokens/layout.yaml +37 -0
  128. package/examples/social-app/openuispec/tokens/motion.yaml +28 -0
  129. package/examples/social-app/openuispec/tokens/spacing.yaml +19 -0
  130. package/examples/social-app/openuispec/tokens/themes.yaml +31 -0
  131. package/examples/social-app/openuispec/tokens/typography.yaml +50 -0
  132. package/examples/social-app/package.json +12 -0
  133. package/examples/taskflow/openuispec/openuispec.yaml +2 -0
  134. package/examples/todo-orbit/openuispec/openuispec.yaml +2 -0
  135. package/mcp-server/index.ts +200 -10
  136. package/package.json +1 -1
  137. package/schema/openuispec.schema.json +7 -0
  138. package/spec/openuispec-v0.1.md +13 -0
package/README.md CHANGED
@@ -82,10 +82,11 @@ This replaces the old approach of writing instructions in CLAUDE.md and hoping t
82
82
  | **Claude Code** | `.mcp.json` | Always |
83
83
  | **Codex** | `.codex/config.toml` | Always |
84
84
  | **VS Code / Copilot** | `.vscode/mcp.json` | If `.vscode/` exists |
85
+ | **Gemini CLI** | `.gemini/settings.json` | If `.gemini/` exists |
85
86
 
86
87
  Manual setup (if needed):
87
88
 
88
- **Claude Code** (`.mcp.json`), **VS Code / Copilot** (`.vscode/mcp.json`):
89
+ **Claude Code** (`.mcp.json`), **VS Code / Copilot** (`.vscode/mcp.json`), **Gemini CLI** (`.gemini/settings.json`):
89
90
  ```json
90
91
  {
91
92
  "mcpServers": {
@@ -114,10 +115,14 @@ Or run directly: `openuispec mcp`
114
115
  | `openuispec_spec_schema` | Before creating/editing spec files | Returns the full JSON schema for a specific spec type — exact structure, required fields, allowed values |
115
116
  | `openuispec_prepare` | Before UI code generation | Returns spec context, platform config, generation constraints |
116
117
  | `openuispec_read_specs` | Before and after generation | Loads spec file contents — the authoritative source for tokens, screens, contracts |
117
- | `openuispec_check` | After generation | Schema validation + concrete audit checklist from your spec |
118
+ | `openuispec_check` | After generation | Schema validation + concrete audit checklist from your spec. Optional `screens`/`contracts` params scope the audit |
118
119
  | `openuispec_validate` | After spec edits | Schema-only validation, optionally filtered by group |
119
120
  | `openuispec_drift` | Before updates | Detect spec drift since last snapshot, with semantic explanation |
120
121
  | `openuispec_status` | Anytime | Cross-target summary: baselines, drift, next steps |
122
+ | `openuispec_get_screen` | Incremental edits | Get a single screen spec by name — faster than `read_specs` for targeted work |
123
+ | `openuispec_get_contract` | Incremental edits | Get a single contract spec, optionally filtered to one variant |
124
+ | `openuispec_get_tokens` | Incremental edits | Get tokens for a specific category (color, typography, spacing, etc.) |
125
+ | `openuispec_get_locale` | Incremental edits | Get a single locale file, optionally filtered to specific keys |
121
126
 
122
127
  The server includes **protocol-level instructions** that trigger on UI-related requests independently of CLAUDE.md rules — so even if CLAUDE.md is buried under other project rules, the MCP enforcement still works.
123
128
 
@@ -137,6 +142,7 @@ See the examples for reference:
137
142
 
138
143
  - [TaskFlow](./examples/taskflow/openuispec/) — compact reference spec covering all 7 contract families
139
144
  - [Todo Orbit](./examples/todo-orbit/openuispec/) — bilingual task app with localization, custom contracts, and generated native/web targets
145
+ - [Social App](./examples/social-app/openuispec/) — trilingual social app with feeds, messaging, profiles, and generated Android/web targets
140
146
 
141
147
  ## Repository structure
142
148
 
@@ -174,6 +180,7 @@ openuispec/
174
180
  │ │ ├── generated/ # Generated iOS, Android, and web apps
175
181
  │ │ ├── README.md # Sample overview and structure
176
182
  │ │ └── AGENTS.md / CLAUDE.md # AI rules generated from the package
183
+ │ ├── social-app/ # Social app sample (trilingual, Android + Web)
177
184
  │ └── todo-orbit/ # Full showcase sample
178
185
  │ ├── openuispec/ # Source OpenUISpec project
179
186
  │ ├── generated/ # Generated iOS, Android, and web apps
@@ -183,7 +190,7 @@ openuispec/
183
190
  │ ├── index.ts # Entry point
184
191
  │ └── init.ts # Project scaffolding + AI rules
185
192
  ├── mcp-server/ # MCP server (openuispec-mcp)
186
- │ └── index.ts # Stdio transport, 8 tools
193
+ │ └── index.ts # Stdio transport, 12 tools
187
194
  ├── check/ # Composite validation command
188
195
  │ └── index.ts # Schema + semantic + readiness
189
196
  ├── drift/ # Drift detection (spec change tracking)
@@ -242,6 +249,8 @@ By default, drift stores state in `generated/<target>/<project>/`. To point targ
242
249
  ```yaml
243
250
  generation:
244
251
  targets: [ios, android, web]
252
+ extra_rules:
253
+ - "Generation hint strings may start with [common], [ios], [android], or [web] to indicate scope."
245
254
  output_dir:
246
255
  web: "../web-ui/"
247
256
  android: "../kmp-ui/"
@@ -254,6 +263,8 @@ Paths are relative to `openuispec.yaml`. The `.openuispec-state.json` file is st
254
263
 
255
264
  If `api.endpoints` are declared, `generation.code_roots.backend` is required. It should point at the backend folder the AI must inspect when generating API clients or wiring request/response behavior.
256
265
 
266
+ `generation.extra_rules` can hold project-wide generation conventions for AI and humans. For example, projects may declare that generation hint strings use prefixes such as `[common]`, `[ios]`, `[android]`, and `[web]` to indicate scope.
267
+
257
268
  `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.
258
269
 
259
270
  Use the commands like this:
@@ -344,7 +355,7 @@ to see which targets are already up to date and which ones still need to catch u
344
355
 
345
356
  ## Status
346
357
 
347
- **v0.1 — Draft**. The spec covers all foundational layers. TaskFlow provides a compact reference app, and Todo Orbit extends coverage with localization, recurring-rule flows, custom contracts, and generated native/web targets.
358
+ **v0.1 — Draft**. The spec covers all foundational layers. TaskFlow provides a compact reference app, Todo Orbit extends coverage with localization, recurring-rule flows, custom contracts, and generated native/web targets, and Social App demonstrates a trilingual social feed app with generated Android and web targets.
348
359
 
349
360
  ### Roadmap
350
361
 
@@ -363,7 +374,8 @@ to see which targets are already up to date and which ones still need to catch u
363
374
  - [x] CLI tool (`openuispec init` for project scaffolding + AI rules)
364
375
  - [x] MCP server for AI tool integration (`openuispec-mcp`)
365
376
  - [x] Multi-platform showcase app (`examples/todo-orbit/`)
366
- - [ ] More example apps (e-commerce, social, dashboard)
377
+ - [x] Social app example (`examples/social-app/`)
378
+ - [ ] More example apps (e-commerce, dashboard)
367
379
 
368
380
  ## Contributing
369
381
 
package/cli/init.ts CHANGED
@@ -208,6 +208,8 @@ i18n:
208
208
 
209
209
  generation:
210
210
  targets: [${targetList}]
211
+ # extra_rules: # Optional: project-wide AI authoring conventions
212
+ # - "Generation hint strings may start with [common], [ios], [android], or [web] to indicate scope."
211
213
  # output_dir: # Optional: map targets to code directories
212
214
  # ios: "../ios-app/" # relative to this file
213
215
  # android: "../android-app/"
@@ -272,10 +274,14 @@ When the openuispec MCP server is configured, AI assistants should use these too
272
274
  | \`openuispec_spec_schema\` | Get the full JSON schema for a specific spec type — exact structure, required fields, allowed values. |
273
275
  | \`openuispec_prepare\` | **Before any UI code generation.** Returns spec context, platform config, and constraints. |
274
276
  | \`openuispec_read_specs\` | Load spec file contents — the authoritative source for tokens, screens, contracts. |
275
- | \`openuispec_check\` | After editing spec files. Validates schema + semantics + readiness. |
277
+ | \`openuispec_check\` | After editing spec files. Validates schema + semantics + readiness. Optional \`screens\`/\`contracts\` params scope the audit. |
276
278
  | \`openuispec_validate\` | Schema-only validation, optionally by group. |
277
279
  | \`openuispec_drift\` | Detect spec changes since last snapshot. |
278
280
  | \`openuispec_status\` | To understand cross-target state (baselines, drift, next steps). |
281
+ | \`openuispec_get_screen\` | Get a single screen spec by name — faster than \`read_specs\` for targeted edits. |
282
+ | \`openuispec_get_contract\` | Get a single contract spec, optionally filtered to one variant. |
283
+ | \`openuispec_get_tokens\` | Get tokens for a specific category (color, typography, spacing, etc.). |
284
+ | \`openuispec_get_locale\` | Get a single locale file, optionally filtered to specific keys. |
279
285
 
280
286
  ## CLI commands
281
287
 
@@ -345,6 +351,15 @@ Call these MCP tools directly. They return structured JSON with everything you n
345
351
  - Call \`openuispec_spec_schema\` with the specific type to get the full JSON schema.
346
352
  - Write the spec file following the schema exactly.
347
353
 
354
+ **Focused getters (prefer these for incremental edits over \`read_specs\`):**
355
+ - \`openuispec_get_screen(name)\` — single screen spec
356
+ - \`openuispec_get_contract(name, variant?)\` — single contract, optionally one variant
357
+ - \`openuispec_get_tokens(category)\` — single token category (color, typography, spacing, etc.)
358
+ - \`openuispec_get_locale(locale, keys?)\` — single locale file, optionally filtered keys
359
+ - \`openuispec_check(target, screens?, contracts?)\` — scoped audit for specific screens/contracts
360
+
361
+ Use \`read_specs\` for full-project generation; use focused getters when editing one screen or contract.
362
+
348
363
  **Other tools:**
349
364
  - \`openuispec_status\` — cross-target summary, good starting point
350
365
  - \`openuispec_drift\` with \`explain: true\` — property-level spec changes
@@ -501,12 +516,14 @@ const EXPECTED_MCP_CONFIG = {
501
516
  * MCP config files by agent:
502
517
  * .mcp.json — Claude Code (project scope)
503
518
  * .vscode/mcp.json — VS Code / Copilot Chat
519
+ * .gemini/settings.json — Gemini CLI (if .gemini/ exists)
504
520
  *
505
521
  * All use the same { mcpServers: { openuispec: { command, args } } } shape.
506
522
  */
507
523
  const JSON_MCP_PATHS = [
508
524
  ".mcp.json",
509
525
  join(".vscode", "mcp.json"),
526
+ join(".gemini", "settings.json"),
510
527
  ];
511
528
 
512
529
  /** Codex uses TOML: .codex/config.toml */
@@ -542,8 +559,9 @@ function configureMcp(cwd: string, showRestart: boolean, quiet: boolean = false)
542
559
  for (const relPath of JSON_MCP_PATHS) {
543
560
  const configPath = join(cwd, relPath);
544
561
 
545
- // .vscode/mcp.json: only write if .vscode/ already exists
546
- if (relPath.startsWith(".vscode") && !existsSync(join(cwd, ".vscode"))) continue;
562
+ // Optional dirs: only write config if the parent directory already exists
563
+ const optionalParent = [".vscode", ".gemini"].find((d) => relPath.startsWith(d));
564
+ if (optionalParent && !existsSync(join(cwd, optionalParent))) continue;
547
565
 
548
566
  try {
549
567
  let config: Record<string, any> = {};
@@ -0,0 +1,10 @@
1
+ {
2
+ "mcpServers": {
3
+ "openuispec": {
4
+ "command": "openuispec",
5
+ "args": [
6
+ "mcp"
7
+ ]
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,114 @@
1
+ <!-- openuispec-rules-start -->
2
+ <!-- openuispec-rules-version: 0.1.45 -->
3
+ # OpenUISpec — AI Assistant Rules
4
+ # ================================
5
+ # This project uses OpenUISpec to define UI as a semantic spec.
6
+ # Spec files are the single source of truth for all UI across platforms.
7
+ # Targets: "ios", "android", "web"
8
+
9
+ ## MANDATORY — UI work requires OpenUISpec tools
10
+
11
+ When the user's request involves UI — screens, navigation, layout, tokens, flows, localization,
12
+ or any visual/structural change — you MUST use the OpenUISpec tools before writing any code.
13
+
14
+ ### MCP Tools (use these when available)
15
+
16
+ Call these MCP tools directly. They return structured JSON with everything you need.
17
+
18
+ **Pre-generation:**
19
+ 1. Call `openuispec_prepare` with the target platform — returns spec context, platform config, constraints.
20
+ 2. Call `openuispec_read_specs` to load spec file contents. Use these as the AUTHORITATIVE source.
21
+ 3. If spec changes are needed, update spec files FIRST, then call `openuispec_check`.
22
+ 4. Generate or update the platform UI code based on the spec contents.
23
+
24
+ **Post-generation (EVERY TIME after writing UI code):**
25
+ 5. Call `openuispec_check` to validate spec integrity.
26
+ 6. Call `openuispec_read_specs` for the screens/contracts you just generated code for.
27
+ 7. Audit your generated code against the spec. For each screen, verify:
28
+ - Every field/action in the spec has a corresponding UI element
29
+ - Token values (colors, spacing, radii) match exactly — no approximations
30
+ - Contract `must_handle` states are all implemented (loading, error, empty, etc.)
31
+ - Adaptive breakpoints match the spec's `size_classes`
32
+ - Locale keys match `$t:` references
33
+ - Navigation targets match flow definitions
34
+ 8. Report any real gaps found and fix them before finishing.
35
+
36
+ **Creating new spec files:**
37
+ - Call `openuispec_spec_types` to discover available spec types.
38
+ - Call `openuispec_spec_schema` with the specific type to get the full JSON schema.
39
+ - Write the spec file following the schema exactly.
40
+
41
+ **Focused getters (prefer these for incremental edits over `read_specs`):**
42
+ - `openuispec_get_screen(name)` — single screen spec
43
+ - `openuispec_get_contract(name, variant?)` — single contract, optionally one variant
44
+ - `openuispec_get_tokens(category)` — single token category (color, typography, spacing, etc.)
45
+ - `openuispec_get_locale(locale, keys?)` — single locale file, optionally filtered keys
46
+ - `openuispec_check(target, screens?, contracts?)` — scoped audit for specific screens/contracts
47
+
48
+ Use `read_specs` for full-project generation; use focused getters when editing one screen or contract.
49
+
50
+ **Other tools:**
51
+ - `openuispec_status` — cross-target summary, good starting point
52
+ - `openuispec_drift` with `explain: true` — property-level spec changes
53
+ - `openuispec_validate` — schema-only validation by group
54
+
55
+ ### CLI fallback (when MCP is not available)
56
+
57
+ If MCP tools are not available, use these CLI commands with `--json` flag:
58
+ - `openuispec prepare --target <t> --json` — build AI-ready work bundle
59
+ - `openuispec check --target <t> --json` — composite validation
60
+ - `openuispec status --json` — cross-target status
61
+ - `openuispec drift --target <t> --explain --json` — semantic drift
62
+ - `openuispec validate [group...] --json` — schema validation
63
+
64
+ ### Other CLI commands
65
+ - `openuispec init` — scaffold a new spec project
66
+ - `openuispec drift --snapshot --target <t>` — snapshot current state (only after UI code is updated)
67
+ - `openuispec configure-target <t>` — configure target platform stack
68
+ - `openuispec update-rules` — update AI rules to match installed package version
69
+
70
+ ## Spec format reference
71
+
72
+ The spec format, schemas, and generation rules are in the installed `openuispec` package.
73
+ You MUST read the reference files before creating or editing spec files — do NOT guess the format.
74
+
75
+ **Find the package:** `node_modules/openuispec/` or run `npm root -g` → `<prefix>/openuispec/`.
76
+ **Online fallback:** `https://openuispec.rsteam.uz/llms-full.txt`
77
+
78
+ **Reference files (read in order):**
79
+ 1. `README.md` — schema tables, file format, root wrapper keys
80
+ 2. `spec/openuispec-v0.1.md` — full specification
81
+ 3. `examples/taskflow/openuispec/` — complete working example
82
+ 4. `schema/` — JSON Schemas for every file type
83
+
84
+ ## Spec location
85
+ - Spec root: `openuispec/` — read `openuispec/openuispec.yaml` first for actual paths.
86
+ - Default dirs: tokens/, screens/, flows/, contracts/, platform/, locales/
87
+
88
+ ## When to start from spec vs platform code
89
+
90
+ **Spec-first** (use `openuispec_prepare` or `openuispec prepare`):
91
+ - Screen structure, navigation, fields, actions, validation, data binding changes
92
+ - Token, variant, contract, flow, or localization changes
93
+ - Changes affecting multiple platforms
94
+ - Requests in product/UI terms
95
+
96
+ **Platform-first** (skip spec tools):
97
+ - Platform-specific polish (iOS-only, Android-only, web-only)
98
+ - Local bug fixes that don't alter shared semantic behavior
99
+
100
+ ## If spec directories are empty (first-time setup)
101
+
102
+ Read `spec/openuispec-v0.1.md` from the package first, then:
103
+ 1. Scan codebase for UI screens → create `openuispec/screens/<name>.yaml` as `status: stub`
104
+ 2. Extract tokens (colors, fonts, spacing) → `openuispec/tokens/`
105
+ 3. Create contract extensions → `openuispec/contracts/`
106
+ 4. Create locale files → `openuispec/locales/<locale>.json`
107
+ 5. Fill in `data_model`, `api.endpoints` in `openuispec/openuispec.yaml`
108
+
109
+ ## Rules
110
+ - Do not snapshot drift unless the UI code has also been updated.
111
+ - Do not modify generated UI without checking whether the spec must change first.
112
+ - Do not use `configure-target --defaults` as silent approval — ask the user to confirm.
113
+ - Always read spec format from the installed package, not from cached/memorized content.
114
+ <!-- openuispec-rules-end -->
@@ -0,0 +1,114 @@
1
+ <!-- openuispec-rules-start -->
2
+ <!-- openuispec-rules-version: 0.1.45 -->
3
+ # OpenUISpec — AI Assistant Rules
4
+ # ================================
5
+ # This project uses OpenUISpec to define UI as a semantic spec.
6
+ # Spec files are the single source of truth for all UI across platforms.
7
+ # Targets: "ios", "android", "web"
8
+
9
+ ## MANDATORY — UI work requires OpenUISpec tools
10
+
11
+ When the user's request involves UI — screens, navigation, layout, tokens, flows, localization,
12
+ or any visual/structural change — you MUST use the OpenUISpec tools before writing any code.
13
+
14
+ ### MCP Tools (use these when available)
15
+
16
+ Call these MCP tools directly. They return structured JSON with everything you need.
17
+
18
+ **Pre-generation:**
19
+ 1. Call `openuispec_prepare` with the target platform — returns spec context, platform config, constraints.
20
+ 2. Call `openuispec_read_specs` to load spec file contents. Use these as the AUTHORITATIVE source.
21
+ 3. If spec changes are needed, update spec files FIRST, then call `openuispec_check`.
22
+ 4. Generate or update the platform UI code based on the spec contents.
23
+
24
+ **Post-generation (EVERY TIME after writing UI code):**
25
+ 5. Call `openuispec_check` to validate spec integrity.
26
+ 6. Call `openuispec_read_specs` for the screens/contracts you just generated code for.
27
+ 7. Audit your generated code against the spec. For each screen, verify:
28
+ - Every field/action in the spec has a corresponding UI element
29
+ - Token values (colors, spacing, radii) match exactly — no approximations
30
+ - Contract `must_handle` states are all implemented (loading, error, empty, etc.)
31
+ - Adaptive breakpoints match the spec's `size_classes`
32
+ - Locale keys match `$t:` references
33
+ - Navigation targets match flow definitions
34
+ 8. Report any real gaps found and fix them before finishing.
35
+
36
+ **Creating new spec files:**
37
+ - Call `openuispec_spec_types` to discover available spec types.
38
+ - Call `openuispec_spec_schema` with the specific type to get the full JSON schema.
39
+ - Write the spec file following the schema exactly.
40
+
41
+ **Focused getters (prefer these for incremental edits over `read_specs`):**
42
+ - `openuispec_get_screen(name)` — single screen spec
43
+ - `openuispec_get_contract(name, variant?)` — single contract, optionally one variant
44
+ - `openuispec_get_tokens(category)` — single token category (color, typography, spacing, etc.)
45
+ - `openuispec_get_locale(locale, keys?)` — single locale file, optionally filtered keys
46
+ - `openuispec_check(target, screens?, contracts?)` — scoped audit for specific screens/contracts
47
+
48
+ Use `read_specs` for full-project generation; use focused getters when editing one screen or contract.
49
+
50
+ **Other tools:**
51
+ - `openuispec_status` — cross-target summary, good starting point
52
+ - `openuispec_drift` with `explain: true` — property-level spec changes
53
+ - `openuispec_validate` — schema-only validation by group
54
+
55
+ ### CLI fallback (when MCP is not available)
56
+
57
+ If MCP tools are not available, use these CLI commands with `--json` flag:
58
+ - `openuispec prepare --target <t> --json` — build AI-ready work bundle
59
+ - `openuispec check --target <t> --json` — composite validation
60
+ - `openuispec status --json` — cross-target status
61
+ - `openuispec drift --target <t> --explain --json` — semantic drift
62
+ - `openuispec validate [group...] --json` — schema validation
63
+
64
+ ### Other CLI commands
65
+ - `openuispec init` — scaffold a new spec project
66
+ - `openuispec drift --snapshot --target <t>` — snapshot current state (only after UI code is updated)
67
+ - `openuispec configure-target <t>` — configure target platform stack
68
+ - `openuispec update-rules` — update AI rules to match installed package version
69
+
70
+ ## Spec format reference
71
+
72
+ The spec format, schemas, and generation rules are in the installed `openuispec` package.
73
+ You MUST read the reference files before creating or editing spec files — do NOT guess the format.
74
+
75
+ **Find the package:** `node_modules/openuispec/` or run `npm root -g` → `<prefix>/openuispec/`.
76
+ **Online fallback:** `https://openuispec.rsteam.uz/llms-full.txt`
77
+
78
+ **Reference files (read in order):**
79
+ 1. `README.md` — schema tables, file format, root wrapper keys
80
+ 2. `spec/openuispec-v0.1.md` — full specification
81
+ 3. `examples/taskflow/openuispec/` — complete working example
82
+ 4. `schema/` — JSON Schemas for every file type
83
+
84
+ ## Spec location
85
+ - Spec root: `openuispec/` — read `openuispec/openuispec.yaml` first for actual paths.
86
+ - Default dirs: tokens/, screens/, flows/, contracts/, platform/, locales/
87
+
88
+ ## When to start from spec vs platform code
89
+
90
+ **Spec-first** (use `openuispec_prepare` or `openuispec prepare`):
91
+ - Screen structure, navigation, fields, actions, validation, data binding changes
92
+ - Token, variant, contract, flow, or localization changes
93
+ - Changes affecting multiple platforms
94
+ - Requests in product/UI terms
95
+
96
+ **Platform-first** (skip spec tools):
97
+ - Platform-specific polish (iOS-only, Android-only, web-only)
98
+ - Local bug fixes that don't alter shared semantic behavior
99
+
100
+ ## If spec directories are empty (first-time setup)
101
+
102
+ Read `spec/openuispec-v0.1.md` from the package first, then:
103
+ 1. Scan codebase for UI screens → create `openuispec/screens/<name>.yaml` as `status: stub`
104
+ 2. Extract tokens (colors, fonts, spacing) → `openuispec/tokens/`
105
+ 3. Create contract extensions → `openuispec/contracts/`
106
+ 4. Create locale files → `openuispec/locales/<locale>.json`
107
+ 5. Fill in `data_model`, `api.endpoints` in `openuispec/openuispec.yaml`
108
+
109
+ ## Rules
110
+ - Do not snapshot drift unless the UI code has also been updated.
111
+ - Do not modify generated UI without checking whether the spec must change first.
112
+ - Do not use `configure-target --defaults` as silent approval — ask the user to confirm.
113
+ - Always read spec format from the installed package, not from cached/memorized content.
114
+ <!-- openuispec-rules-end -->
@@ -0,0 +1,19 @@
1
+ # social-app
2
+
3
+ Test project for exercising the local [`openuispec`](../openuispec) checkout.
4
+
5
+ ## Structure
6
+
7
+ - `openuispec/` contains the spec scaffold.
8
+ - `AGENTS.md` and `CLAUDE.md` include the OpenUISpec assistant rules generated by the local CLI.
9
+
10
+ ## Commands
11
+
12
+ ```bash
13
+ npm run validate
14
+ npm run validate:semantic
15
+ npm run status
16
+ npm run openuispec -- init
17
+ ```
18
+
19
+ The scripts call the local `../openuispec` repo directly, so this project can be used without installing `openuispec` globally.
@@ -0,0 +1,92 @@
1
+ plugins {
2
+ alias(libs.plugins.android.application)
3
+ alias(libs.plugins.compose.compiler)
4
+ kotlin("plugin.serialization")
5
+ }
6
+
7
+ android {
8
+ namespace = "com.social.app"
9
+ compileSdk = 36
10
+
11
+ defaultConfig {
12
+ applicationId = "com.social.app"
13
+ minSdk = 26
14
+ targetSdk = 36
15
+ versionCode = 1
16
+ versionName = "1.0"
17
+
18
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
19
+ vectorDrawables {
20
+ useSupportLibrary = true
21
+ }
22
+ }
23
+
24
+ buildTypes {
25
+ release {
26
+ isMinifyEnabled = false
27
+ proguardFiles(
28
+ getDefaultProguardFile("proguard-android-optimize.txt"),
29
+ "proguard-rules.pro"
30
+ )
31
+ }
32
+ }
33
+ compileOptions {
34
+ sourceCompatibility = JavaVersion.VERSION_11
35
+ targetCompatibility = JavaVersion.VERSION_11
36
+ }
37
+ kotlin {
38
+ compilerOptions {
39
+ jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11)
40
+ }
41
+ }
42
+ buildFeatures {
43
+ compose = true
44
+ }
45
+ packaging {
46
+ resources {
47
+ excludes += "/META-INF/{AL2.0,LGPL2.1}"
48
+ }
49
+ }
50
+ }
51
+
52
+ dependencies {
53
+ implementation(libs.androidx.core.ktx)
54
+ implementation(libs.androidx.lifecycle.runtime.ktx)
55
+ implementation(libs.androidx.activity.compose)
56
+ implementation(platform(libs.androidx.compose.bom))
57
+ implementation(libs.androidx.ui)
58
+ implementation(libs.androidx.ui.graphics)
59
+ implementation(libs.androidx.ui.tooling.preview)
60
+ implementation(libs.androidx.material3)
61
+ implementation(libs.androidx.material.icons.extended)
62
+ implementation(libs.google.material)
63
+ implementation(libs.coil.compose)
64
+ implementation(libs.coil.network)
65
+
66
+ // Decompose
67
+ implementation(libs.decompose)
68
+ implementation(libs.decompose.extensions.compose)
69
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
70
+
71
+ // MVIKotlin
72
+ implementation(libs.mvikotlin)
73
+ implementation(libs.mvikotlin.main)
74
+ implementation(libs.mvikotlin.logging)
75
+ implementation("com.arkivanov.mvikotlin:mvikotlin-extensions-coroutines:4.3.0")
76
+
77
+ // Essenty
78
+ implementation(libs.essenty.lifecycle)
79
+ implementation(libs.essenty.instancekeeper)
80
+
81
+ // DataStore
82
+ implementation(libs.androidx.datastore.preferences)
83
+ implementation(libs.androidx.datastore.core)
84
+
85
+ testImplementation("junit:junit:4.13.2")
86
+ androidTestImplementation("androidx.test.ext:junit:1.2.1")
87
+ androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
88
+ androidTestImplementation(platform(libs.androidx.compose.bom))
89
+ androidTestImplementation("androidx.compose.ui:ui-test-junit4")
90
+ debugImplementation(libs.androidx.ui.tooling)
91
+ debugImplementation("androidx.compose.ui:ui-test-manifest")
92
+ }
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+
4
+ <uses-permission android:name="android.permission.INTERNET" />
5
+
6
+ <application
7
+ android:name=".SocialAppApplication"
8
+ android:allowBackup="true"
9
+ android:icon="@mipmap/ic_launcher"
10
+ android:label="@string/nav_home"
11
+ android:roundIcon="@mipmap/ic_launcher_round"
12
+ android:supportsRtl="true"
13
+ android:theme="@style/Theme.SocialApp">
14
+ <activity
15
+ android:name=".MainActivity"
16
+ android:exported="true"
17
+ android:label="@string/nav_home"
18
+ android:theme="@style/Theme.SocialApp">
19
+ <intent-filter>
20
+ <action android:name="android.intent.action.MAIN" />
21
+ <category android:name="android.intent.category.LAUNCHER" />
22
+ </intent-filter>
23
+ </activity>
24
+ </application>
25
+
26
+ </manifest>
@@ -0,0 +1,20 @@
1
+ package com.social.app
2
+
3
+ import android.content.Context
4
+ import com.arkivanov.decompose.ComponentContext
5
+ import com.arkivanov.mvikotlin.core.store.StoreFactory
6
+ import com.social.app.data.preferences.DataStorePreferencesRepository
7
+ import com.social.app.data.preferences.PreferencesRepository
8
+ import com.social.app.ui.navigation.DefaultRootComponent
9
+ import com.social.app.ui.navigation.RootComponent
10
+ import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
11
+ import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory
12
+
13
+ class AppContainer(
14
+ context: Context,
15
+ ) {
16
+ val preferencesRepository: PreferencesRepository = DataStorePreferencesRepository(context.applicationContext)
17
+ val storeFactory: StoreFactory = LoggingStoreFactory(DefaultStoreFactory())
18
+
19
+ fun createRootComponent(componentContext: ComponentContext): RootComponent = DefaultRootComponent(componentContext)
20
+ }
@@ -0,0 +1,35 @@
1
+ package com.social.app
2
+
3
+ import android.os.Bundle
4
+ import androidx.activity.ComponentActivity
5
+ import androidx.activity.compose.setContent
6
+ import androidx.activity.enableEdgeToEdge
7
+ import androidx.compose.runtime.collectAsState
8
+ import androidx.compose.runtime.getValue
9
+ import com.arkivanov.decompose.defaultComponentContext
10
+ import com.social.app.data.preferences.AppPreferences
11
+ import com.social.app.ui.MainShell
12
+ import com.social.app.ui.theme.SocialAppTheme
13
+
14
+ class MainActivity : ComponentActivity() {
15
+ override fun onCreate(savedInstanceState: Bundle?) {
16
+ super.onCreate(savedInstanceState)
17
+ val appContainer = (application as SocialAppApplication).appContainer
18
+ val root = appContainer.createRootComponent(defaultComponentContext())
19
+
20
+ enableEdgeToEdge()
21
+ setContent {
22
+ val preferences by appContainer.preferencesRepository.preferences.collectAsState(initial = AppPreferences())
23
+
24
+ SocialAppTheme(
25
+ themeMode = preferences.themeMode,
26
+ ) {
27
+ MainShell(
28
+ root = root,
29
+ preferencesRepository = appContainer.preferencesRepository,
30
+ storeFactory = appContainer.storeFactory,
31
+ )
32
+ }
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,13 @@
1
+ package com.social.app
2
+
3
+ import android.app.Application
4
+
5
+ class SocialAppApplication : Application() {
6
+ lateinit var appContainer: AppContainer
7
+ private set
8
+
9
+ override fun onCreate() {
10
+ super.onCreate()
11
+ appContainer = AppContainer(this)
12
+ }
13
+ }