@getrheo/rheo-skill 2.2.0 → 2.3.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @getrheo/rheo-skill
2
2
 
3
- Current release: **`2.1.0`** on npm. Public source: [getrheo/rheo-skill](https://github.com/getrheo/rheo-skill) (mirrored from this private monorepo via `pnpm extract:oss-repos`).
3
+ Current release: **`2.3.0`** on npm (`PLATFORM_SDK_VERSION` in `scripts/publish-package-registry.mjs`). Public source: [getrheo/rheo-skill](https://github.com/getrheo/rheo-skill) (mirrored from this private monorepo via `pnpm extract:oss-repos`).
4
4
 
5
5
  Source and build tooling for the **`rheo`** agent skill — a single, self-contained
6
6
  skill with two sub-skills:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getrheo/rheo-skill",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "type": "module",
5
5
  "description": "Rheo agent skill — SDK install guidance and flow manifest import tooling.",
6
6
  "main": "./src/index.ts",
@@ -9,8 +9,8 @@
9
9
  ".": "./src/index.ts"
10
10
  },
11
11
  "dependencies": {
12
- "@getrheo/contracts": "2.2.0",
13
- "@getrheo/flow-runtime": "2.2.0",
12
+ "@getrheo/contracts": "2.3.0",
13
+ "@getrheo/flow-runtime": "2.3.0",
14
14
  "zod": "^3.23.8"
15
15
  },
16
16
  "devDependencies": {
package/rheo/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: rheo
3
3
  description: Work with Rheo, the headless onboarding/paywall flow engine for mobile apps. Use when a user wants to install or wire the Rheo SDK (React Native, Expo, or SwiftUI), follow Rheo SDK best practices, configure integrations (RevenueCat, AppsFlyer), wire auth/permissions/terminal callbacks, OR import/migrate an existing mobile flow into a compliant Rheo FlowManifest and validate it. Routes to the `rheo-best-practices` and `rheo-flow-import` sub-skills.
4
4
  compatibility: Requires Node.js 20+. rheo-flow-import scripts are fully self-contained (no install step). Internet access fetches the latest Manifest Agent Profile; a bundled fallback works offline.
5
5
  metadata:
6
- rheo-version: "2.2.0"
6
+ rheo-version: "2.3.0"
7
7
  manifest-schema-version: "7"
8
8
  ---
9
9
 
@@ -26,6 +26,7 @@ Every layer `kind` accepted by the manifest:
26
26
  - `multiple_choice`
27
27
  - `text_input`
28
28
  - `scale_input`
29
+ - `wheel_picker`
29
30
  - `oauth_provider`
30
31
  - `oauth_login`
31
32
  - `email_password_auth`
@@ -95,7 +96,7 @@ Valid `permissionKey` values for `request_os_permission`:
95
96
 
96
97
  ## Inputs and auth
97
98
 
98
- - `text_input` types: `plain`, `email`, `phone`, `url`, `multiline`.
99
+ - `text_input` types: `plain`, `email`, `phone`, `url`, `number`, `multiline`.
99
100
  - `text_input` classification: `safe`, `sensitive`.
100
101
  - `oauth_login` preset providers: `github`, `google`, `apple`.
101
102
  - `email_password_auth` modes: `sign_in`, `sign_up` (sign_up requires email + password + confirm fields).
@@ -62,7 +62,7 @@ the scaffold expands into a real layer. `id` is always optional. `style` and
62
62
  { "kind": "text", "text": "Welcome to Rheo", "style": { "color": "#FFFFFF" } }
63
63
  { "kind": "text", "text": { "default": "Hi", "translations": { "es": "Hola" } } }
64
64
  { "kind": "image", "mediaAssetId": "00000000-0000-0000-0000-000000000101", "alt": "Hero" }
65
- { "kind": "icon", "iconName": "sparkles-outline" } // family defaults to ionicons
65
+ { "kind": "icon", "iconName": "sparkles-outline" } // family defaults to ionicons; size defaults to 24×24
66
66
  { "kind": "lottie", "mediaAssetId": "…", "loop": true, "autoPlay": true }
67
67
  { "kind": "video", "mediaAssetId": "…", "autoPlay": false } // needs a play_media button
68
68
  ```
@@ -96,18 +96,21 @@ Action shorthands: `"none"`, `"continue"`, `"skip"`, `"end_flow"`,
96
96
  ### Stacks (layout)
97
97
 
98
98
  ```jsonc
99
- { "kind": "stack", "direction": "vertical", "align": "center", "gap": 12,
99
+ { "kind": "stack", "direction": "vertical", "align": "center", "distribution": "center", "gap": 12,
100
100
  "style": { "padding": { "t": 24, "r": 16, "b": 24, "l": 16 } },
101
101
  "children": [ { "kind": "text", "text": "Centered hero copy" } ] }
102
102
  ```
103
103
 
104
+ Use `distribution` for main-axis packing (`start` \| `center` \| `end` \| `between` \| `around`). Legacy flow-spec `justify` is accepted by the scaffold and rewritten to `distribution`, but prefer writing `distribution` directly.
105
+
104
106
  Card chrome (border/shadow/background/radius) goes on a wrapping stack's `style`.
105
107
 
106
108
  ### Choices
107
109
 
108
110
  You provide `options`; the scaffold builds the option `stack` children,
109
111
  `optionBindings`, and `branching`. `optionId` defaults to a slug of the label.
110
- Map unselected chrome to `style` and selected chrome to `selectedStyle` per option.
112
+ Map unselected chrome to `style` and selected chrome to `selectedStyle` per option
113
+ (bake padding/radius/background/border into `style` — do not omit default chrome).
111
114
 
112
115
  ```jsonc
113
116
  {
@@ -136,11 +139,13 @@ option, set `branching: { "enabled": true, "conditions": [{ "choiceId": "male",
136
139
  "inputType": "plain", "required": true, "classification": "safe" }
137
140
  { "kind": "scale_input", "fieldKey": "fitness_level", "min": 1, "max": 5, "step": 1,
138
141
  "minLabel": "Beginner", "maxLabel": "Pro" }
142
+ { "kind": "wheel_picker", "fieldKey": "birth_year", "mode": "date", "datePart": "year",
143
+ "minYear": 1950, "maxYear": 2010, "defaultValue": "1990" }
139
144
  { "kind": "checkbox", "fieldKey": "accept_terms", "blocking": true }
140
145
  ```
141
146
 
142
147
  Use **at most one** input layer per screen, and add a `continue` button on
143
- screens with `text_input`, `multiple_choice`, or `scale_input`.
148
+ screens with `text_input`, `multiple_choice`, `scale_input`, or `wheel_picker`.
144
149
 
145
150
  ### Auth
146
151
 
@@ -68,7 +68,7 @@ If the user has not named an entry point, stop after question 1 and wait for an
68
68
  - Bundle every slide image; every asset referenced in the carousel must appear in `rheo-import.assets.json`.
69
69
  - Do not collapse multi-slide routes into one static screen with a single image.
70
70
  11. Map layout, alignment, borders, and shadows:
71
- - Parent vertical stacks that center content need `align: "center"` (and `justify: "center"` when appropriate).
71
+ - Parent vertical stacks that center content need `align: "center"` (and `distribution: "center"` when appropriate).
72
72
  - Hero images belong inside centered stacks, not as lone siblings in an unaligned vertical stack.
73
73
  - Card rows (rating, testimonials, why-it-works cards) use wrapping stacks with `style.background`, `style.radius`, `style.padding`, `style.border`, and `style.shadow` from source.
74
74
  12. Map custom fonts from audit findings ([font-import.md](font-import.md)):
@@ -43,7 +43,7 @@ Before zipping, read [layer-schema-pitfalls.md](layer-schema-pitfalls.md) and ru
43
43
 
44
44
  ## Layer Kinds
45
45
 
46
- Use only: `stack`, `text`, `image`, `lottie`, `video`, `icon`, `button`, `back_button`, `progress`, `loader`, `counter`, `single_choice`, `multiple_choice`, `text_input`, `scale_input`, `oauth_provider`, `oauth_login`, `email_password_auth`, `email_password_field`, `email_password_submit`, `carousel`, `hyperlink`, `checkbox`.
46
+ Use only: `stack`, `text`, `image`, `lottie`, `video`, `icon`, `button`, `back_button`, `progress`, `loader`, `counter`, `single_choice`, `multiple_choice`, `text_input`, `scale_input`, `wheel_picker`, `oauth_provider`, `oauth_login`, `email_password_auth`, `email_password_field`, `email_password_submit`, `carousel`, `hyperlink`, `checkbox`.
47
47
 
48
48
  ## Rules
49
49
 
@@ -58,10 +58,14 @@ Use only: `stack`, `text`, `image`, `lottie`, `video`, `icon`, `button`, `back_b
58
58
  - In-screen pagers → `kind: "carousel"` with one slide per page; swipe-only; bundle every slide asset. See carousel-import.md in references.
59
59
  - Center images with parent stack `align: "center"`; map card borders/shadows to wrapping stacks.
60
60
  - Custom fonts: bundle files in `rheo-import.fonts.json` only (never `rheo-import.assets.json`), `manifest.theme.fontFamily`. See `font-import.md`.
61
- - Choice options: each option stack uses `style` (default) and `selectedStyle` (selected).
61
+ - Choice options: each option stack bakes default chrome into `style` and selected overrides into `selectedStyle` (optional `selectedStyleBreakpoints`).
62
+ - Stack packing: `distribution` — never `justify`. Width fill parent is `"full"` — never width `"fill"`.
63
+ - `text_input.fieldStyle` is typography only; chrome on outer `style`.
64
+ - `wheel_picker`: scroll wheel / date parts; `itemStyle` / `selectedItemStyle` typography only; branch later via `dec_*` with string predicates.
65
+ - Icons default to 24×24 unless source specifies another size.
62
66
  - Publish gates: explicit `style.color` on all text (including button labels), Continue on manual-submit screens, valid entry/completion path. Run `scripts/audit-publish-manifest.mjs` before finishing.
63
67
  - Black-and-white fallback is acceptable only when the audit finds no style/token evidence and the user confirms no theme source.
64
- - Use at most one input layer kind per screen.
68
+ - Use at most one input layer kind per screen (`single_choice`, `multiple_choice`, `text_input`, `scale_input`, `wheel_picker`).
65
69
  - Non-reserved `sdk.*` decision keys must be listed in `sdkAttributeKeys`.
66
70
  - RevenueCat paywalls are external surface nodes and always need `fallback`.
67
71
  - Emit complete graph edges for imported flows.
@@ -23,7 +23,7 @@ See [layer-schema-pitfalls.md](layer-schema-pitfalls.md) for common id mistakes
23
23
 
24
24
  ## Layer Kinds
25
25
 
26
- Allowed kinds: `stack`, `text`, `image`, `lottie`, `video`, `icon`, `button`, `back_button`, `progress`, `loader`, `counter`, `single_choice`, `multiple_choice`, `text_input`, `scale_input`, `oauth_provider`, `oauth_login`, `email_password_auth`, `email_password_field`, `email_password_submit`, `carousel`, `hyperlink`, `checkbox`.
26
+ Allowed kinds: `stack`, `text`, `image`, `lottie`, `video`, `icon`, `button`, `back_button`, `progress`, `loader`, `counter`, `single_choice`, `multiple_choice`, `text_input`, `scale_input`, `wheel_picker`, `oauth_provider`, `oauth_login`, `email_password_auth`, `email_password_field`, `email_password_submit`, `carousel`, `hyperlink`, `checkbox`.
27
27
 
28
28
  ## Regions
29
29
 
@@ -62,21 +62,29 @@ Map clear brand values into `manifest.theme` and layer styles. Set `style.color`
62
62
  ## Layout
63
63
 
64
64
  - Center images: parent stack `align: "center"`.
65
+ - Main-axis packing: stack / button `distribution` (not `justify`).
65
66
  - Card chrome: wrapping stacks with `border`, `shadow`, `background`, `radius`, `padding`.
67
+ - Do not invent image `radius` unless the source has rounded corners.
66
68
 
67
69
  ## Explicit Sizing
68
70
 
69
- Set `style.width` and `style.height` on every layer — do not omit them. `width` accepts `"full"`, `"auto"`, a fraction (`"1/2"`, `"1/3"`, `"2/3"`, `"1/4"`, `"3/4"`), or a pixel number; `height` accepts `"fill"`, `"auto"`, or a pixel number. Use these per-kind defaults unless the design requires otherwise:
71
+ Set `style.width` and `style.height` on every layer — do not omit them. `width` accepts `"full"` (**never** `"fill"` on width), `"auto"`, a fraction (`"1/2"`, `"1/3"`, `"2/3"`, `"1/4"`, `"3/4"`), or a pixel number; `height` accepts `"fill"`, `"auto"`, or a pixel number. Optional clamps: `minWidth` / `maxWidth` / `minHeight` / `maxHeight`. Use these per-kind defaults unless the design requires otherwise:
70
72
 
71
73
  | Layer kinds | `width` | `height` |
72
74
  |-------------|---------|----------|
73
- | `stack`, `text_input`, `scale_input`, `oauth_login`, `email_password_auth`, `email_password_field`, `progress`, `loader` | `"full"` | `"fill"` |
75
+ | `stack`, `text_input`, `scale_input`, `wheel_picker`, `oauth_login`, `email_password_auth`, `email_password_field`, `progress`, `loader` | `"full"` | `"fill"` |
74
76
  | `button`, `back_button`, `oauth_provider`, `email_password_submit`, `checkbox`, `single_choice`, `multiple_choice` | `"full"` | `"auto"` |
75
- | `text`, `counter`, `icon`, `hyperlink` | `"auto"` | `"auto"` |
77
+ | `text`, `counter`, `hyperlink` | `"auto"` | `"auto"` |
78
+ | `icon` | `24` | `24` |
76
79
  | `image`, `lottie`, `video` | `"full"` | number (e.g. `160`) |
77
80
  | `carousel` | — (no outer `style` sizing) | — |
78
81
 
79
- Dashboard import backfills these defaults automatically, but emitting them explicitly produces higher-fidelity first drafts.
82
+ Stack packing uses **`distribution`** (`start` \| `center` \| `end` \| `between` \| `around`). Never emit legacy `justify`.
83
+
84
+ `text_input.fieldStyle` is typography only; outer chrome stays on `style` / `styleBreakpoints`.
85
+ `wheel_picker.itemStyle` / `selectedItemStyle` are row typography only; outer chrome stays on `style` / `styleBreakpoints`.
86
+
87
+ Dashboard import backfills sizing defaults automatically, but emitting them explicitly produces higher-fidelity first drafts.
80
88
 
81
89
  ## Container Layers (Required `children`)
82
90
 
@@ -159,9 +167,10 @@ Full template: [layer-schema-pitfalls.md](layer-schema-pitfalls.md#single_choice
159
167
 
160
168
  ## Inputs
161
169
 
162
- - Use at most one input layer kind per screen.
170
+ - Use at most one input layer kind per screen (`single_choice`, `multiple_choice`, `text_input`, `scale_input`, `wheel_picker`).
163
171
  - Use stable snake_case `fieldKey` values.
164
172
  - Mark text input classification as `safe` or `sensitive`.
173
+ - `wheel_picker` captures a string (options or date part); no layer branching — use `dec_*` with string predicates.
165
174
 
166
175
  ## Decisions
167
176
 
@@ -194,4 +203,4 @@ When source screens use i18n ([localization-import.md](localization-import.md)):
194
203
  - Avoid orphaned screens unless intentionally parked for later editing.
195
204
  - Run `scripts/audit-publish-manifest.mjs` before finishing — it enforces dashboard **Publish** rules (see [publish-gates.md](publish-gates.md)).
196
205
  - Every `text` and `icon` layer needs explicit `style.color` (including nested button label text).
197
- - Screens with `text_input`, `multiple_choice`, or `scale_input` need a `continue` button.
206
+ - Screens with `text_input`, `multiple_choice`, `scale_input`, or `wheel_picker` need a `continue` button.
@@ -26,7 +26,7 @@ These mirror `apps/web/src/features/builder/validateFlow.ts` and API `preflightP
26
26
  | **Choice input shape** | `single_choice` / `multiple_choice` missing `optionBindings` or `branching`, using `"options"` instead of `children`, or `fieldKey` not snake_case. |
27
27
  | **Container `children`** | `back_button`, `button`, or `hyperlink` emitted without a `children` array (or with label text on the parent instead of nested `text` children). Crashes import on Indie plans during motion strip; fails Zod validation. |
28
28
  | **Text/icon `style.color`** | Body text or **button label** (nested text child) left without `style.color` — native does not inherit CSS colors. |
29
- | **Continue button** | `text_input`, `multiple_choice`, or `scale_input` without a `button` with `action.kind: "continue"`. |
29
+ | **Continue button** | `text_input`, `multiple_choice`, `scale_input`, or `wheel_picker` without a `button` with `action.kind: "continue"`. |
30
30
  | **One input per screen** | Multiple inputs, or OAuth/email-password combined with inputs. |
31
31
  | **fieldKey** | Missing or non–snake_case on input layers. |
32
32
  | **Graph targets** | `go_to_step`, choice `goTo`, loader/lottie/video `onComplete` (screen mode), permission outcomes, and fallbacks point at missing `scr_*` / `dec_*` / `surf_*` ids. |
@@ -38,7 +38,7 @@ Ask the user to confirm the entry file if it is not obvious; do not guess.
38
38
  | `react-native-video` / `expo-video` | `video` |
39
39
  | `<Pressable>`/`<TouchableOpacity>` acting as CTA | `button` (label = nested `text` child) |
40
40
  | Header back chevron / close (`<HeaderBackButton>`, a back `Pressable` in a top bar) | `back_button` in `regions.header`, `icon.family: "ionicons"`, no `action` |
41
- | `<View style={{ flexDirection, alignItems, gap }}>` | `stack` (`direction`, `align`, `justify`, `gap`) |
41
+ | `<View style={{ flexDirection, alignItems, gap }}>` | `stack` (`direction`, `align`, `distribution`, `gap`) |
42
42
  | Vector icons (`react-native-vector-icons`, `@expo/vector-icons` Ionicons) | `icon` (`family: "ionicons"`) |
43
43
  | External `Linking.openURL(...)` / `<A href>` | `hyperlink` |
44
44
  | Progress bar / step dots tied to step index | `progress` (header) |
@@ -55,6 +55,7 @@ Hero images that render through wrapper components (`<Illustration>`, `<Logo>`,
55
55
  - `<TextInput>` collecting a value → `text_input` with a snake_case `fieldKey`;
56
56
  mark password/email/PII as `classification: "sensitive"`.
57
57
  - Sliders / rating rows → `scale_input`. Consent toggles → `checkbox`.
58
+ - Native scroll wheels / `Picker` / year-month-day selectors → `wheel_picker` (not `single_choice`).
58
59
  - Screens with a manual-submit input need a `continue` button.
59
60
 
60
61
  ## Theme, colors, gradients, fonts
@@ -36,7 +36,7 @@ Ask the user to confirm the entry view/coordinator if it is not obvious.
36
36
  | `VideoPlayer` / `AVPlayer` | `video` |
37
37
  | `Button { … } label: { … }` acting as CTA | `button` (label = nested `text` child) |
38
38
  | Toolbar back/close (`.toolbar { ToolbarItem(placement: .navigationBarLeading) }`, a chevron `Button`) | `back_button` in `regions.header`, `icon.family: "ionicons"`, no `action` |
39
- | `VStack`/`HStack`/`ZStack` with `spacing`, `alignment` | `stack` (`direction`, `align`, `justify`, `gap`) |
39
+ | `VStack`/`HStack`/`ZStack` with `spacing`, `alignment` | `stack` (`direction`, `align`, `distribution`, `gap`) |
40
40
  | SF Symbol `Image(systemName:)` | `icon` — **remap to a valid `ionicons` name** (SF Symbols are not allowed on `icon`) |
41
41
  | `Link(destination:)` / `openURL` | `hyperlink` |
42
42
  | `ProgressView(value:)` / step dots | `progress` (header) |
@@ -53,6 +53,7 @@ real asset — follow the struct to its `Image("…")` to find the asset name.
53
53
  - `TextField`/`SecureField` → `text_input` with a snake_case `fieldKey`
54
54
  (`SecureField` / email / PII → `classification: "sensitive"`).
55
55
  - `Slider` / star rating → `scale_input`. `Toggle` consent → `checkbox`.
56
+ - `Picker` / `WheelPicker` / date-part wheels → `wheel_picker` (not `single_choice`).
56
57
  - Manual-submit input screens need a `continue` button.
57
58
 
58
59
  ## Theme, colors, gradients, fonts