@sun-asterisk/sungen 3.2.2-beta.11 → 3.2.2-beta.13

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 (146) hide show
  1. package/dist/capabilities/discover.d.ts.map +1 -1
  2. package/dist/capabilities/discover.js +26 -3
  3. package/dist/capabilities/discover.js.map +1 -1
  4. package/dist/cli/commands/add-flow.d.ts.map +1 -1
  5. package/dist/cli/commands/add-flow.js +2 -0
  6. package/dist/cli/commands/add-flow.js.map +1 -1
  7. package/dist/cli/commands/add.d.ts.map +1 -1
  8. package/dist/cli/commands/add.js +4 -0
  9. package/dist/cli/commands/add.js.map +1 -1
  10. package/dist/cli/commands/capability.d.ts.map +1 -1
  11. package/dist/cli/commands/capability.js +61 -0
  12. package/dist/cli/commands/capability.js.map +1 -1
  13. package/dist/cli/commands/delivery.d.ts.map +1 -1
  14. package/dist/cli/commands/delivery.js +89 -2
  15. package/dist/cli/commands/delivery.js.map +1 -1
  16. package/dist/cli/commands/generate.d.ts.map +1 -1
  17. package/dist/cli/commands/generate.js +2 -1
  18. package/dist/cli/commands/generate.js.map +1 -1
  19. package/dist/cli/commands/init.d.ts.map +1 -1
  20. package/dist/cli/commands/init.js +27 -2
  21. package/dist/cli/commands/init.js.map +1 -1
  22. package/dist/dashboard/snapshot-builder.d.ts.map +1 -1
  23. package/dist/dashboard/snapshot-builder.js +10 -1
  24. package/dist/dashboard/snapshot-builder.js.map +1 -1
  25. package/dist/exporters/csv-exporter.d.ts.map +1 -1
  26. package/dist/exporters/csv-exporter.js +3 -1
  27. package/dist/exporters/csv-exporter.js.map +1 -1
  28. package/dist/exporters/json-exporter.js +3 -1
  29. package/dist/exporters/json-exporter.js.map +1 -1
  30. package/dist/exporters/mobile-app-id.d.ts +22 -0
  31. package/dist/exporters/mobile-app-id.d.ts.map +1 -0
  32. package/dist/exporters/mobile-app-id.js +37 -0
  33. package/dist/exporters/mobile-app-id.js.map +1 -0
  34. package/dist/exporters/spec-parser.d.ts.map +1 -1
  35. package/dist/exporters/spec-parser.js +6 -2
  36. package/dist/exporters/spec-parser.js.map +1 -1
  37. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +3 -0
  38. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  39. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/scroll-action.hbs +7 -4
  40. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/toggle-action.hbs +20 -3
  41. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/checked-assertion.hbs +4 -1
  42. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/not-checked-assertion.hbs +4 -1
  43. package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +3 -0
  44. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  45. package/dist/generators/test-generator/code-generator.js +38 -3
  46. package/dist/generators/test-generator/code-generator.js.map +1 -1
  47. package/dist/generators/test-generator/template-engine.d.ts +3 -0
  48. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  49. package/dist/generators/test-generator/template-engine.js +11 -1
  50. package/dist/generators/test-generator/template-engine.js.map +1 -1
  51. package/dist/generators/test-generator/utils/selector-resolver.d.ts +11 -1
  52. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  53. package/dist/generators/test-generator/utils/selector-resolver.js +33 -0
  54. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  55. package/dist/harness/audit.js +1 -1
  56. package/dist/harness/audit.js.map +1 -1
  57. package/dist/harness/catalog/universal-viewpoints.yaml +15 -0
  58. package/dist/harness/journey.d.ts.map +1 -1
  59. package/dist/harness/journey.js +22 -11
  60. package/dist/harness/journey.js.map +1 -1
  61. package/dist/harness/sensors.d.ts +1 -1
  62. package/dist/harness/sensors.d.ts.map +1 -1
  63. package/dist/harness/sensors.js +32 -9
  64. package/dist/harness/sensors.js.map +1 -1
  65. package/dist/orchestrator/flow-manager.d.ts +11 -0
  66. package/dist/orchestrator/flow-manager.d.ts.map +1 -1
  67. package/dist/orchestrator/flow-manager.js +147 -29
  68. package/dist/orchestrator/flow-manager.js.map +1 -1
  69. package/dist/orchestrator/mobile-runtime-scaffolder.d.ts +59 -0
  70. package/dist/orchestrator/mobile-runtime-scaffolder.d.ts.map +1 -0
  71. package/dist/orchestrator/mobile-runtime-scaffolder.js +298 -0
  72. package/dist/orchestrator/mobile-runtime-scaffolder.js.map +1 -0
  73. package/dist/orchestrator/project-initializer.d.ts +25 -7
  74. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  75. package/dist/orchestrator/project-initializer.js +115 -62
  76. package/dist/orchestrator/project-initializer.js.map +1 -1
  77. package/dist/orchestrator/screen-manager.d.ts +30 -0
  78. package/dist/orchestrator/screen-manager.d.ts.map +1 -1
  79. package/dist/orchestrator/screen-manager.js +205 -22
  80. package/dist/orchestrator/screen-manager.js.map +1 -1
  81. package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-flow.md +32 -4
  82. package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +51 -10
  83. package/dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +11 -1
  84. package/dist/orchestrator/templates/ai-instructions/claude-cmd-delivery.md +6 -0
  85. package/dist/orchestrator/templates/ai-instructions/claude-cmd-locale.md +25 -4
  86. package/dist/orchestrator/templates/ai-instructions/claude-cmd-review.md +7 -0
  87. package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +38 -4
  88. package/dist/orchestrator/templates/ai-instructions/claude-skill-delivery.md +2 -0
  89. package/dist/orchestrator/templates/ai-instructions/claude-skill-locale.md +106 -9
  90. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-flow.md +33 -3
  91. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +50 -9
  92. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +8 -1
  93. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +6 -0
  94. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-locale.md +25 -4
  95. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-review.md +7 -0
  96. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +38 -4
  97. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +2 -0
  98. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-locale.md +106 -9
  99. package/package.json +3 -3
  100. package/src/capabilities/discover.ts +29 -3
  101. package/src/cli/commands/add-flow.ts +2 -0
  102. package/src/cli/commands/add.ts +4 -0
  103. package/src/cli/commands/capability.ts +64 -1
  104. package/src/cli/commands/delivery.ts +89 -2
  105. package/src/cli/commands/generate.ts +2 -1
  106. package/src/cli/commands/init.ts +38 -3
  107. package/src/dashboard/snapshot-builder.ts +10 -1
  108. package/src/exporters/csv-exporter.ts +3 -1
  109. package/src/exporters/json-exporter.ts +3 -1
  110. package/src/exporters/mobile-app-id.ts +34 -0
  111. package/src/exporters/spec-parser.ts +6 -2
  112. package/src/generators/test-generator/adapters/adapter-interface.ts +3 -0
  113. package/src/generators/test-generator/adapters/appium/templates/steps/actions/scroll-action.hbs +7 -4
  114. package/src/generators/test-generator/adapters/appium/templates/steps/actions/toggle-action.hbs +20 -3
  115. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/checked-assertion.hbs +4 -1
  116. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/not-checked-assertion.hbs +4 -1
  117. package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +3 -0
  118. package/src/generators/test-generator/code-generator.ts +39 -3
  119. package/src/generators/test-generator/template-engine.ts +14 -1
  120. package/src/generators/test-generator/utils/selector-resolver.ts +51 -1
  121. package/src/harness/audit.ts +1 -1
  122. package/src/harness/catalog/universal-viewpoints.yaml +15 -0
  123. package/src/harness/journey.ts +21 -9
  124. package/src/harness/sensors.ts +25 -8
  125. package/src/orchestrator/flow-manager.ts +165 -29
  126. package/src/orchestrator/mobile-runtime-scaffolder.ts +277 -0
  127. package/src/orchestrator/project-initializer.ts +127 -64
  128. package/src/orchestrator/screen-manager.ts +237 -22
  129. package/src/orchestrator/templates/ai-instructions/claude-cmd-add-flow.md +32 -4
  130. package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +51 -10
  131. package/src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +11 -1
  132. package/src/orchestrator/templates/ai-instructions/claude-cmd-delivery.md +6 -0
  133. package/src/orchestrator/templates/ai-instructions/claude-cmd-locale.md +25 -4
  134. package/src/orchestrator/templates/ai-instructions/claude-cmd-review.md +7 -0
  135. package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +38 -4
  136. package/src/orchestrator/templates/ai-instructions/claude-skill-delivery.md +2 -0
  137. package/src/orchestrator/templates/ai-instructions/claude-skill-locale.md +106 -9
  138. package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-flow.md +33 -3
  139. package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +50 -9
  140. package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +8 -1
  141. package/src/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +6 -0
  142. package/src/orchestrator/templates/ai-instructions/copilot-cmd-locale.md +25 -4
  143. package/src/orchestrator/templates/ai-instructions/copilot-cmd-review.md +7 -0
  144. package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +38 -4
  145. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +2 -0
  146. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-locale.md +106 -9
@@ -1,30 +1,48 @@
1
1
  ---
2
2
  name: add-flow
3
3
  description: 'Add a new Sungen flow — scaffolds directories for E2E cross-screen testing, helps fill spec.md, and can capture visuals via the capture skills'
4
- argument-hint: [flow-name] [--path <start-url>]
5
- allowed-tools: Read, Grep, Bash, Glob, Edit, Write, AskUserQuestion, mcp__playwright__browser_navigate, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_snapshot, mcp__figma__get_design_context, mcp__figma__get_variable_defs, mcp__figma__get_screenshot
4
+ argument-hint: "[flow-name] [--path <start-url>] [--reach <steps>]"
5
+ allowed-tools: Read, Grep, Bash, Glob, Edit, Write, AskUserQuestion, mcp__playwright__browser_navigate, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_snapshot, mcp__figma__get_design_context, mcp__figma__get_variable_defs, mcp__figma__get_screenshot, mcp__appium-mcp__select_device, mcp__appium-mcp__appium_session_management, mcp__appium-mcp__generate_locators, mcp__appium-mcp__appium_get_page_source, mcp__appium-mcp__appium_find_element, mcp__appium-mcp__appium_gesture, mcp__appium-mcp__appium_screenshot
6
6
  ---
7
7
 
8
8
  You are adding a new Sungen flow for E2E cross-screen test generation.
9
9
 
10
+ ## Platform detection (do this FIRST)
11
+
12
+ Read `qa/capabilities.yaml` and check the `platform` field.
13
+
14
+ - If `platform: mobile` → follow the **mobile path** in each step below.
15
+ - If `platform: web` or field absent → follow the **web path** (all steps unchanged).
16
+
10
17
  ## Parameters
11
18
 
12
19
  Parse from `$ARGUMENTS`:
13
20
  - **flow** — flow name (e.g., `award-submission`, `user-onboarding`)
14
- - **--path \<url\>** — starting page URL path (default: `/login`)
21
+ - **--path \<url\>** — starting page URL path for web (default: `/login`); or app entry for mobile (`<appPackage>`)
22
+ - **--reach \<steps\>** — (mobile only) navigation recipe for the flow's first screen: `>`-separated nav steps from app launch. Ignored (with warning) on web projects.
15
23
  - **--description \<text\>** — flow description (optional)
16
24
 
17
25
  If **flow** is missing, ask: "What is the flow name? (e.g., `award-submission`, `user-onboarding`)"
18
- If **path** is missing, ask: "What is the starting URL path? (e.g., `/login`)"
26
+ If **path** is missing:
27
+ - **Web** → ask: "What is the starting URL path? (e.g., `/login`)"
28
+ - **Mobile** → read `wdio.conf.ts` and propose the app entry (package alone). Use `AskUserQuestion` to confirm before scaffolding.
19
29
 
20
30
  ## Steps
21
31
 
22
32
  ### 1. Scaffold the flow
23
33
 
34
+ **Web:**
24
35
  ```bash
25
36
  sungen add-flow --flow <name> --path <path>
26
37
  ```
27
38
 
39
+ **Mobile (when `platform: mobile` in `qa/capabilities.yaml`):**
40
+ ```bash
41
+ sungen add-flow --flow <name> [--reach "tap [My Page] tab > tap [Settings] row"]
42
+ # --reach is the navigation recipe for the flow's first screen → scaffolded into the Background.
43
+ # Directories are always qa/flows/<name>/ (never qa/mobile/).
44
+ ```
45
+
28
46
  This creates:
29
47
  ```
30
48
  qa/flows/<name>/
@@ -47,6 +65,16 @@ Record the screen list — you will need it for:
47
65
 
48
66
  ### 2. Capture visual source
49
67
 
68
+ **Mobile path (when `platform: mobile` in `qa/capabilities.yaml`):**
69
+
70
+ Use `AskUserQuestion`: *"Capture a live screen via Appium MCP now?"*
71
+ - **Yes, capture now (Recommended)** — invoke the `sungen-capture-mobile` skill (Appium MCP) for the first screen of the flow. It replays the Background nav recipe, scans the locator tree, and saves a screenshot to `requirements/ui/`. Repeat for each screen in the flow as needed.
72
+ - **Skip** — user will capture later via `/sungen:run-test` or manually.
73
+
74
+ Do NOT invoke `sungen-capture` (web/Figma) for a mobile project. Use `sungen-capture-mobile` only.
75
+
76
+ **Web path:**
77
+
50
78
  Use `AskUserQuestion`: *"Pick a visual source for this flow's screens:"*
51
79
  - **Figma designs** (Recommended for pre-launch) — invoke `sungen-capture` skill (mode figma-mcp) for each screen
52
80
  - **Live page scan** (dev/staging is up) — invoke `sungen-capture` skill (mode live) for each screen URL
@@ -1,25 +1,38 @@
1
1
  ---
2
2
  name: add-screen
3
3
  description: 'Add a new Sungen screen or a sub-feature to an existing one — scaffolds directories, helps fill spec.md, and can capture visuals from Figma (pre-launch) or live page via the capture skills'
4
- argument-hint: "[screen-name] [url-path] [--feature <name>] [--figma <url>]"
5
- allowed-tools: Read, Grep, Bash, Glob, Edit, Write, AskUserQuestion, mcp__playwright__browser_navigate, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_snapshot, mcp__figma__get_design_context, mcp__figma__get_variable_defs, mcp__figma__get_screenshot
4
+ argument-hint: "[screen-name] [url-path] [--feature <name>] [--figma <url>] [--reach <steps>] [--platform android|ios]"
5
+ allowed-tools: Read, Grep, Bash, Glob, Edit, Write, AskUserQuestion, mcp__playwright__browser_navigate, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_snapshot, mcp__figma__get_design_context, mcp__figma__get_variable_defs, mcp__figma__get_screenshot, mcp__appium-mcp__select_device, mcp__appium-mcp__appium_session_management, mcp__appium-mcp__generate_locators, mcp__appium-mcp__appium_get_page_source, mcp__appium-mcp__appium_find_element, mcp__appium-mcp__appium_gesture, mcp__appium-mcp__appium_screenshot
6
6
  ---
7
7
 
8
8
  You are adding a new Sungen screen for test generation, or extending an existing screen with an additional `.feature` file (sub-feature).
9
9
 
10
+ ## Platform detection (do this FIRST)
11
+
12
+ Read `qa/capabilities.yaml` and check the `platform` field.
13
+
14
+ - If `platform: mobile` → follow the **mobile path** in each step below.
15
+ - If `platform: web` or field absent → follow the **web path** (all steps unchanged).
16
+
10
17
  ## Parameters
11
18
 
12
19
  Parse from `$ARGUMENTS`:
13
20
  - **screen** — screen name (e.g., `login`, `dashboard`, `settings`)
14
- - **path** — URL path (e.g., `/login`, `/dashboard`, `/settings`) - optional when `--figma` is provided or when adding a sub-feature to an existing screen
21
+ - **path** — URL path for web (e.g., `/login`), or app entry for mobile (`<appPackage>` / `<iosBundleId>` / dual-id `"<pkg> | <bundleId>"`). Optional when `--figma` is provided or when adding a sub-feature.
22
+ - **`--reach <steps>`** — (mobile only) navigation recipe: `>`-separated nav steps from app launch to this screen, e.g. `"tap [My Page] tab > tap [Settings] row"`. Scaffolded into the Background. Ignored (with a warning) on web projects.
23
+ - **`--platform android|ios`** — (mobile only, optional) emit `@platform:android` or `@platform:ios` on the stub for OS-specific screens. Omit for cross-platform mobile. Does NOT affect directory routing.
15
24
  - **`--feature <name>`** — sub-feature name to add to an existing screen (e.g., `modal`, `filter`, `create-flow`). Creates `<screen>-<feature>.feature` + matching `selectors/<screen>-<feature>.yaml` + `test-data/<screen>-<feature>.yaml` without touching the screen's other files. Use this when one screen has multiple `.feature` files (e.g. main listing + modal + filter panel).
16
- - **`--figma <url>`** — Figma share URL (optional)
25
+ - **`--figma <url>`** — Figma share URL (optional, web only)
17
26
  - **`--refresh`** — bypass Figma cache and re-fetch (optional, use with `--figma`)
18
27
  - **`--scale <n>`** — PNG export scale factor, default 2 (optional)
19
28
  - **`--hi-res`** — export at 4× scale, shorthand for `--scale 4` (optional)
20
29
 
21
30
  If **screen** is missing, ask: "What is the screen name? (e.g., `login`, `dashboard`)"
22
- If **path** is missing and **`--feature`** is NOT used and `--figma` was NOT provided, ask: "What is the URL path? (e.g., `/login`, `/dashboard`)"
31
+ If **path** is missing and **`--feature`** is NOT used and `--figma` was NOT provided:
32
+ - **Web** → ask: "What is the URL path? (e.g., `/login`, `/dashboard`)"
33
+ - **Mobile** → read `wdio.conf.ts` at the repo root and derive a proposal from `APP_PACKAGE` (Android) and `IOS_BUNDLE_ID` (iOS). Propose the package alone for mobile-android/mobile-ios, or the dual-id `"<pkg> | <bundleId>"` for cross-platform. Use `AskUserQuestion` to confirm before scaffolding.
34
+
35
+ After confirming the app entry for a mobile project, ask: "After the app launches, what taps reach this screen? e.g. `tap [My Page] tab > tap [Account Settings] row` — leave blank if this IS the launcher/home screen." Pass the answer as `--reach "..."`.
23
36
 
24
37
  **Mode detection** — before invoking the CLI, check whether `qa/screens/<screen>/` already exists:
25
38
  - Screen does NOT exist → fresh screen creation (need `--path` unless `--figma` provided)
@@ -30,11 +43,24 @@ If **path** is missing and **`--feature`** is NOT used and `--figma` was NOT pro
30
43
 
31
44
  ### 1. Scaffold the screen (or sub-feature)
32
45
 
33
- **Standard path (no `--figma`, no `--feature`):**
46
+ **Web — standard path (no `--figma`, no `--feature`):**
34
47
  ```bash
35
48
  sungen add --screen <screen> --path <path>
36
49
  ```
37
50
 
51
+ **Mobile path (when `platform: mobile` in `qa/capabilities.yaml`):**
52
+ ```bash
53
+ sungen add --screen <screen> \
54
+ --path "<appPackage>[ | <iosBundleId>]" \
55
+ [--reach "tap [My Page] tab > tap [Account Settings] row"] \
56
+ [--platform android|ios]
57
+ # --path is the app entry (package alone; launch activity auto-detected).
58
+ # --reach is the navigation recipe → scaffolded into the Background.
59
+ # Omit --reach when the screen IS the launcher/home screen.
60
+ # --platform android|ios is optional: emits @platform:android/ios for OS-specific screens only.
61
+ # Directories are always qa/screens/<screen>/ (never qa/mobile/).
62
+ ```
63
+
38
64
  **Sub-feature mode (`--feature <name>` provided):**
39
65
  ```bash
40
66
  sungen add --screen <screen> --feature <name> [--path <path>]
@@ -43,7 +69,7 @@ sungen add --screen <screen> --feature <name> [--path <path>]
43
69
  # --path is optional — defaults to /<screen> when omitted. Pass --path only if the sub-feature lives at a different URL.
44
70
  ```
45
71
 
46
- **Figma branch (when `--figma <url>` is in `$ARGUMENTS`):**
72
+ **Figma branch (when `--figma <url>` is in `$ARGUMENTS`, web only):**
47
73
 
48
74
  Invoke the `sungen-capture` skill (mode figma-pat) by running:
49
75
  ```bash
@@ -86,6 +112,16 @@ After `sungen add --figma` succeeds, the envelope of `spec_figma.md` is determin
86
112
 
87
113
  ### 2. Capture visual source
88
114
 
115
+ **Mobile path (when `platform: mobile` in `qa/capabilities.yaml`):**
116
+
117
+ Use `AskUserQuestion`: *"Capture a live screen via Appium MCP now?"*
118
+ - **Yes, capture now (Recommended)** — invoke the `sungen-capture-mobile` skill (Appium MCP). It replays the Background nav recipe to reach this screen, scans the locator tree, and saves a screenshot to `requirements/ui/`.
119
+ - **Skip** — user will capture later via `/sungen:run-test` or manually.
120
+
121
+ Do NOT invoke `sungen-capture` (web/Figma) for a mobile project. Use `sungen-capture-mobile` only.
122
+
123
+ **Web path:**
124
+
89
125
  **If Figma branch (Step 1) already downloaded PNGs** → visuals already exist. Use `AskUserQuestion` to offer:
90
126
  - **Continue** — Figma visuals are enough (Recommended)
91
127
  - **Also capture live page** — supplement Figma with real page scan (invoke `sungen-capture` skill (mode live))
@@ -120,12 +156,17 @@ If user picks `/sungen:create-test`, **you MUST use the Skill tool** to invoke i
120
156
 
121
157
  ```
122
158
  sungen add --screen <name>
123
- [-p, --path <path>] URL route (e.g., /awards). Required for capture; defaults to /<screen> when omitted.
159
+ [-p, --path <path>] Web: URL route (e.g., /awards). Mobile: app entry (<appPackage> or dual-id).
160
+ Required for capture; defaults to /<screen> when omitted on web.
124
161
  [-f, --feature <name>] Add a sub-feature .feature file to an existing screen.
125
162
  Output filename = <screen>-<feature>.{feature,yaml,yaml}.
126
- [-c, --capture] Auto-capture a live screenshot to requirements/ui/ (needs --path).
163
+ [-c, --capture] Auto-capture a live screenshot to requirements/ui/ (web only, needs --path).
127
164
  [-d, --description <text>] Screen description (used in spec.md stub).
128
- [--figma <url>] Figma share URL generates spec_figma.md + ui/*.png.
165
+ [--reach <steps>] Mobile navigation recipe: ">"-separated steps from app launch to this screen.
166
+ Scaffolded into the Background. Ignored (with warning) on web projects.
167
+ [--platform android|ios] Mobile only: emit @platform:android/ios tag for OS-specific screens.
168
+ Does NOT affect directory routing.
169
+ [--figma <url>] Figma share URL — generates spec_figma.md + ui/*.png (web only).
129
170
  [--refresh] Bypass Figma cache (use with --figma).
130
171
  [--scale <n>] PNG export scale (default 2).
131
172
  [--hi-res] Shorthand for --scale 4.
@@ -13,6 +13,13 @@ If `spec_figma.md` exists OR the user provides a Figma URL for the PAT flow:
13
13
 
14
14
  ---
15
15
 
16
+ ## Platform detection (do this FIRST)
17
+
18
+ Read `qa/capabilities.yaml` and check the `platform` field.
19
+
20
+ - If `platform: mobile` → this is a **mobile project**. When generating scenarios, use mobile gesture vocabulary and selector patterns from the `sungen-mobile-gestures` and `sungen-capture-mobile` skills (tap, swipe, long-press, etc. instead of click/hover; `[accessibility-id]` selectors instead of CSS/role). Mobile-specific steps (permission dialogs, clipboard, geolocation) are valid — do not flag them as invalid Gherkin. The `@platform` tag is not required on individual scenarios (one project = one platform). Visual capture via the `sungen-capture-mobile` skill (Appium MCP live capture) is preferred over web-based capture.
21
+ - If `platform: web` or field absent → **web path**, proceed as normal below.
22
+
16
23
  ## Role
17
24
 
18
25
  You are a **Senior QA Engineer** specialized in test case design. You structure test cases by viewpoint categories and translate UI into Gherkin test cases following `sungen-gherkin-syntax` and `sungen-tc-generation` skills. **Tier 1 (critical+high) first** — expand coverage later. Focus on **Gherkin scenarios and test data only** — selectors are handled during `/sungen:run-test`.
@@ -112,7 +119,10 @@ If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the d
112
119
  - `sungen manifest --screen <name>` — fingerprints for next-run change detection. On a **re-run**, start the whole command by `sungen manifest --screen <name> --diff` and only regenerate scenarios whose spec section changed (keep/regenerate/retire).
113
120
  - **Ledger each phase** (so `sungen trace` can map the whole process): pick one `runId` at the start (e.g. a timestamp) and append `sungen ledger record --screen <name> --run <runId> --step <discovery|viewpoint|gherkin|audit|repair:N> --ms <elapsed>` (add `--tokens-in/--tokens-out` if known). The `--run` id groups this invocation so `trace`/`ledger report` show THIS run, not a mix of past runs. Do this for **every** phase, not just repair.
114
121
 
115
- 6. **Converge — show the trace.** Run `sungen trace --screen <name>` and present to the user: the process map (phases + repair rounds), bottlenecks, and the **HUMAN-LOOP FOCUS** (@manual scenarios they must verify) + audit score & gate status & residual/cross-screen gaps. Then use `AskUserQuestion` to offer next steps based on which tier was just generated:
122
+ 6. **Converge — show the journey board first, then the trace.**
123
+ - **Board (the human-facing review surface — do this first).** Run `sungen journey --screen <name>` and present the board to the user verbatim-in-spirit: **📍 you-are-here** (current phase), the **obligation checklist** ("what must still be true" — each ✅ satisfied / ⏳ needs-work / 🚫 waived), and **especially the 🔎 Review queue** — every item carries an IDE-jumpable **anchor** 〔`VP-id · file:line`〕. This is what answers *"review what, review where, what's doubtful"*: read each queued item aloud with its anchor so the user knows exactly which scenario/line to look at. End with the board's **→ Next**.
124
+ - **Trace (the process detail).** Then run `sungen trace --screen <name>` for the process map (phases + repair rounds), bottlenecks, and audit score & gate status & residual/cross-screen gaps.
125
+ - Then use `AskUserQuestion` to offer next steps based on which tier was just generated:
116
126
 
117
127
  > The harness gate + reviewer already ran above — you do **not** need `/sungen:review` as a next step (it's the independent checkpoint for hand/prompt-authored or pre-delivery cases). Recommend `run-test` or expanding coverage.
118
128
 
@@ -19,6 +19,10 @@ If `--env` is passed but no value follows, ask the user which locale to use.
19
19
 
20
20
  ## Steps
21
21
 
22
+ ### 0. Sign-off gate (per screen — the deliver boundary)
23
+
24
+ Delivery is the **last phase**, and its boundary requires a human sign-off (S5). For each screen/flow being delivered, run `sungen gate --screen <name> --phase deliver` (exit 2 = HALT). On **HALT** it means the screen is **not signed off yet** (or an obligation is still open): present `sungen journey --screen <name>` — the **🔎 Review queue** with its anchors 〔`VP-id · file:line`〕 — so the user can review *what / where*, then either resolve the items or, when satisfied, sign off with `sungen journey --screen <name> --signoff --by "<name>"`. Do **not** export a screen past a deliver HALT without a sign-off. (Skip this gate only if the user explicitly asks for a draft/preview export.)
25
+
22
26
  ### 1. Invoke the CLI
23
27
 
24
28
  Run via Bash (single command, no extra parsing). Prefer the local `./bin/sungen.js` when it exists — the sungen monorepo ships local-only features the global npm package doesn't have yet (multi-sheet locale aggregation, `.<env>` filename suffix, locale-aware step rendering). Fall back to `npx sungen` in downstream projects.
@@ -41,6 +45,8 @@ The CLI handles:
41
45
  - Generating CSV/XLSX at `qa/deliverables/<name>-testcases[.<env>].csv` / `.xlsx`
42
46
  - Printing summary table
43
47
 
48
+ **Mobile projects (`platform: mobile`):** a plain `delivery <name>` (no `SUNGEN_ENV`) auto-emits one deliverable PER OS — `<name>-testcases.android.{csv,xlsx}` + `<name>-testcases.ios.{csv,xlsx}` (from each `<name>-test-result.<os>.json`) — and writes **NO** base `<name>-testcases.{csv,xlsx}` (a stale base pair is removed). The **Test Environment** column shows only that OS's app id (Android package vs iOS bundle id), never the combined dual-id `Path:`. `SUNGEN_ENV=android|ios` still targets a single OS.
49
+
44
50
  ### 2. Handle pre-flight failures (if CLI exits non-zero)
45
51
 
46
52
  If the CLI exits with blocking issues, it will have already printed a clear table showing exactly what's missing per screen.
@@ -1,7 +1,7 @@
1
1
  ---
2
- description: 'Bootstrap i18n for a screen/flow — audit selectors, detect locale switch mechanism via Playwright, generate test-data overlay so `sungen:run-test --env <locale>` works.'
2
+ description: 'Bootstrap i18n for a screen/flow — audit selectors, detect locale switch mechanism via Playwright (web) or device locale (mobile), generate test-data overlay so `sungen:run-test --env <locale>` works.'
3
3
  argument-hint: "<name> <locale> [--base-locale <code>] [--offline]"
4
- allowed-tools: Read, Grep, Bash, Glob, Edit, Write, AskUserQuestion, mcp__playwright__browser_navigate, mcp__playwright__browser_snapshot, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_wait_for, mcp__playwright__browser_evaluate, mcp__playwright__browser_click, mcp__playwright__browser_storage_state, mcp__playwright__browser_set_storage_state
4
+ allowed-tools: Read, Grep, Bash, Glob, Edit, Write, AskUserQuestion, mcp__playwright__browser_navigate, mcp__playwright__browser_snapshot, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_wait_for, mcp__playwright__browser_evaluate, mcp__playwright__browser_click, mcp__playwright__browser_storage_state, mcp__playwright__browser_set_storage_state, mcp__appium-mcp__select_device, mcp__appium-mcp__appium_session_management, mcp__appium-mcp__appium_get_page_source, mcp__appium-mcp__appium_screenshot, mcp__appium-mcp__generate_locators
5
5
  ---
6
6
 
7
7
  ## Role
@@ -14,10 +14,31 @@ Parse from `$ARGUMENTS`:
14
14
  - **name** — screen or flow name (e.g. `home`, `awards`, `kudo-to-display-on-kudos`). If missing → AskUserQuestion.
15
15
  - **locale** — target locale code (e.g. `en`, `ja`, `en-US`, `staging-ja`). If missing → AskUserQuestion. This becomes the suffix in `test-data/<feature>.<locale>.yaml` and `SUNGEN_ENV=<locale>` at run time.
16
16
  - **`--base-locale <code>`** — optional. The locale of existing `test-data/<feature>.yaml`. Default `vi`. Used only for reporting/UX — files never get renamed.
17
- - **`--offline`** — force OFFLINE mode (skip Playwright capture). Useful when you know the live page can't be reached or when prepping a test-only template.
17
+ - **`--offline`** — force OFFLINE mode (skip live capture). Useful when you know the live page/device can't be reached or when prepping a test-only template.
18
18
 
19
19
  Reject if name == locale (common typo).
20
20
 
21
+ ## Platform detection (do this FIRST)
22
+
23
+ Read `qa/capabilities.yaml` and check the `platform` field.
24
+
25
+ - If `platform: mobile` → switch to the **mobile path** (below).
26
+ - If `platform: web` or field absent → follow the **web path** (existing behavior, unchanged).
27
+
28
+ ### Mobile path
29
+
30
+ When `platform: mobile`:
31
+
32
+ - **Live capture**: use **Appium MCP** (`select_device` → `appium_session_management(create)` with device at base locale → `appium_get_page_source` / `appium_screenshot`) — NOT Playwright browser tools.
33
+ - **Locale-switch mechanism**: **device locale** — `appium:language` / `appium:locale` caps + `noReset:false` (set by wdio `resolveLocaleCaps` at runtime). There is no URL prefix, query param, or browser-storage injection on mobile.
34
+ - **Phases skipped for mobile**: 3.5 (browser storage diff), 3.6 (storage verification), 6d (Pages URL update), 6f (locale-config.json / locale-fixture). These are web-only; wdio `resolveLocaleCaps` handles runtime locale on mobile automatically — no fixture files needed.
35
+ - **OFFLINE mode** (when device unreachable or `--offline` flag): scaffold overlay template + let user fill manually. Same as web offline mode.
36
+ - **Hand-off**: print `SUNGEN_ENV=<locale> npm run test:mobile`. Include note: "If the device locale code differs from the overlay env name, set `SUNGEN_LOCALE=<code>` — wdio `resolveLocaleCaps` reads it as an override."
37
+ - **Phase 6 (mobile) writes only**: 6a selectors `{{var}}`, 6b base `test-data/<feature>.yaml`, 6c overlay `test-data/<feature>.<locale>.yaml`. No 6d or 6f.
38
+ - **Compile**: `sungen generate --screen <name>` (appium adapter auto-selected in a mobile project).
39
+
40
+ Stop here for mobile — do not continue to the web path.
41
+
21
42
  ## Auto-detect context
22
43
 
23
44
  Same as `/sungen:run-test`:
@@ -25,7 +46,7 @@ Same as `/sungen:run-test`:
25
46
  - Else `qa/screens/<name>/` exists → screen mode (base path: `qa/screens/<name>/`)
26
47
  - Neither exists → tell user and stop
27
48
 
28
- ## Steps
49
+ ## Steps (web)
29
50
 
30
51
  The `sungen-locale` skill defines 7 phases. Execute them in order:
31
52
 
@@ -5,6 +5,13 @@ argument-hint: [screen-name]
5
5
  allowed-tools: Read, Grep, Glob, Bash, Edit, Write, AskUserQuestion
6
6
  ---
7
7
 
8
+ ## Platform detection (do this FIRST)
9
+
10
+ Read `qa/capabilities.yaml` and check the `platform` field.
11
+
12
+ - If `platform: mobile` → this is a **mobile project**. When reviewing scenarios, apply the **mobile viewpoint**: mobile-specific steps (tap, swipe, long-press, permission dialogs, clipboard, geolocation) are valid — do not flag them as incorrect or web-incompatible. Judge selector references against mobile accessibility patterns (`[accessibility-id]`, content-desc, etc.), not CSS/role. Load `sungen-mobile-gestures` for the canonical mobile step vocabulary. All other harness steps (audit, script-check, scorecard) run unchanged.
13
+ - If `platform: web` or field absent → **web path**, proceed as normal below.
14
+
8
15
  ## Role
9
16
 
10
17
  You are an **independent QA Reviewer** running in a **fresh context** — you did not author these tests. You do **not** invent a parallel score; you run the **harness** and present its signals as a human scorecard. Skills: `sungen-tc-review` (presentation rubric), `sungen-viewpoint`, `sungen-gherkin-syntax`.
@@ -1,13 +1,47 @@
1
1
  ---
2
2
  name: run-test
3
3
  description: 'Generate selectors + auth state via Playwright MCP, compile, and run Playwright tests — auto-fixes selectors on failure'
4
- argument-hint: "[screen-name] [--env <locale>]"
5
- allowed-tools: Read, Grep, Bash, Glob, Edit, Write, AskUserQuestion, mcp__playwright__browser_navigate, mcp__playwright__browser_snapshot, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_wait_for, mcp__playwright__browser_evaluate, mcp__playwright__browser_run_code, mcp__playwright__browser_storage_state, mcp__playwright__browser_set_storage_state
4
+ argument-hint: "[screen-name] [--env <locale>] [--ios|--android|--both]"
5
+ allowed-tools: Read, Grep, Bash, Glob, Edit, Write, AskUserQuestion, mcp__playwright__browser_navigate, mcp__playwright__browser_snapshot, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_wait_for, mcp__playwright__browser_evaluate, mcp__playwright__browser_run_code, mcp__playwright__browser_storage_state, mcp__playwright__browser_set_storage_state, mcp__appium-mcp__select_device, mcp__appium-mcp__appium_session_management, mcp__appium-mcp__generate_locators, mcp__appium-mcp__appium_get_page_source, mcp__appium-mcp__appium_find_element, mcp__appium-mcp__appium_gesture, mcp__appium-mcp__appium_screenshot, mcp__appium-mcp__appium_set_value
6
6
  ---
7
7
 
8
8
  ## Role
9
9
 
10
- You are a **Senior Developer**. Use `sungen-selector-fix`, `sungen-selector-keys`, and `sungen-error-mapping` skills.
10
+ You are a **Senior Developer**.
11
+ - **Web screens/flows** → use `sungen-selector-fix`, `sungen-selector-keys`, and `sungen-error-mapping` skills (Playwright MCP + `npx playwright test`).
12
+ - **Mobile screens** (`platform: mobile` in `qa/capabilities.yaml`) → use `sungen-selector-fix-mobile`, `sungen-capture-mobile`, `sungen-mobile-gestures`, `sungen-selector-keys` (Appium MCP + `npm run test:mobile`).
13
+
14
+ ## Platform detection (do this FIRST)
15
+
16
+ Read `qa/capabilities.yaml` and check the `platform` field.
17
+
18
+ - If `platform: mobile` → switch to the **mobile path** (below).
19
+ - If `platform: web` or field absent → follow the **web path** (all steps below, unchanged).
20
+
21
+ ### Mobile path
22
+
23
+ When `platform: mobile`:
24
+
25
+ - **Selectors**: use **Appium MCP** (`select_device` → `appium_session_management(create)` → `generate_locators`), per the `sungen-selector-fix-mobile` skill. Also load `sungen-capture-mobile` and `sungen-mobile-gestures`.
26
+ - **Auth**: web Phase 0.5 (`storageState`) does not exist on mobile. When the feature has `@auth:<role>`, check `specs/.auth-mobile/<role>.json`; if missing, run the guided auth-contract builder (Phase 0.5 in `sungen-selector-fix-mobile`) BEFORE Phase 1.
27
+ - **Compile**: `[ -x ./bin/sungen.js ] && ./bin/sungen.js generate --screen <name> --framework appium || npx sungen generate --screen <name> --framework appium`
28
+ - **OS selection**: parse the target OS from `$ARGUMENTS` — `--ios`, `--android`, or `--both`
29
+ (alias: `--platform <android|ios|both>`) → set `MOBILE_PLATFORM=<value>`. Default to `android` when no flag is given.
30
+ - **Run**: WebdriverIO, not Playwright. Scope one spec with `SUNGEN_SPECS`; prefix the parsed `MOBILE_PLATFORM`:
31
+ ```bash
32
+ # Android (default — no flag, or --android)
33
+ SUNGEN_SPECS='./specs/generated/<name>/<name>.spec.ts' npm run test:mobile
34
+ # iOS only (--ios)
35
+ SUNGEN_SPECS='./specs/generated/<name>/<name>.spec.ts' MOBILE_PLATFORM=ios npm run test:mobile
36
+ # both OSes (--both)
37
+ SUNGEN_SPECS='./specs/generated/<name>/<name>.spec.ts' MOBILE_PLATFORM=both npm run test:mobile
38
+ ```
39
+ `wdio.conf.ts` auto-selects `@wdio/globals` specs and auto-starts Appium. iOS needs a booted Simulator and `IOS_BUNDLE_ID`/`IOS_UDID` env vars.
40
+ - **Results**: the wdio reporter writes `<name>-test-result.<android|ios>[.<env>].json` — one file per capability, so a both-OS run keeps both outcomes.
41
+ - **Skip** the "Playwright command guidelines" section below — it applies to web only.
42
+ - The phased waves (smoke → priority → full → regression), attempt budgets, and next-steps mirror the web flow — follow the `sungen-selector-fix-mobile` skill for the mobile equivalents.
43
+
44
+ Stop here for mobile — do not continue to the web path.
11
45
 
12
46
  > ⛔ **Source of truth — the live page is NOT the oracle; `.feature`/`test-data`/`spec.md` are.** Auto-fix is for **selector-resolution** failures (wrong locator → fix `selectors.yaml`). An **assertion-value** failure where the app contradicts the spec is a **CANDIDATE BUG → report it, let it FAIL** — never loosen the rule, weaken the assertion, edit the expected value/`.feature`, or hand-edit the generated `.spec.ts` to make it pass. See `sungen-error-mapping` § "Source of truth". (A `password > 8` test that fails on 6 chars is a bug to report, not a `>= 6` edit.)
13
47
 
@@ -103,7 +137,7 @@ If the unit is **api-first**, skip every selector/capture phase (an API test has
103
137
  8. **Phase 4 — Regression**: One final full run. Report results. No more fix loops.
104
138
  9. **Integrity check & trace (always run after the final run).**
105
139
  - `sungen script-check --screen <name>` — verify the generated spec is a **1:1** of the Gherkin (every non-@manual scenario ↔ one `test()`, no drift). If it reports **DRIFT** (spec hand-edited or stale), re-run `sungen generate --screen <name>` so the spec matches the feature, then re-run — **never hand-edit the generated spec** (auto-fix must edit `selectors.yaml`, not the `.spec.ts`).
106
- - `sungen ledger record --screen <name> --step run --ms <elapsed>` (record this run), then `sungen trace --screen <name>` — show the process map + bottlenecks + **HUMAN-LOOP FOCUS** (the @manual scenarios the QA must verify) to the user.
140
+ - `sungen ledger record --screen <name> --step run --ms <elapsed>` (record this run), then **present the journey board** — `sungen journey --screen <name>` — as the human-facing close-out: **📍 you-are-here**, the **obligation checklist** (now including automation), and **especially the 🔎 Review queue** with its per-item anchors 〔`VP-id · file:line`〕 (*review what / where*) plus any **candidate bugs left FAILING by the source-of-truth rule** (#387). Then `sungen trace --screen <name>` for the process map + bottlenecks. The board's **→ Next** tells the user whether they can sign off & deliver.
107
141
  - **Phase gate (boundary — do NOT skip).** `sungen gate --screen <name> --phase run` (exit 2 = HALT): the run-boundary obligations (incl. automation) must be **satisfied or explicitly waived**. On **HALT**, classify per `sungen-error-mapping` § Source of truth (#387): a **selector-resolution** failure → fix `selectors.yaml` + re-run; an **assertion-vs-spec** failure → **report it as a candidate bug / leave it FAIL** (never weaken the assertion or edit the expected to pass); a genuinely-accepted gap → `sungen journey --screen <name> --waive <OB> --reason "..."`. Do **not** declare the run "done" past a HALT without a fix, a reported bug, or a reasoned waiver.
108
142
  10. **Capability-pending offer (consent-gated).** If `sungen audit --screen <name>` reports `AUTOMATION-READY-PENDING` (or the run shows `@requires:<cap>` tests skipped "requires …"), these are **automation-ready** scenarios waiting on an opt-in driver. Use `AskUserQuestion` to offer: *"N scenario(s) are automation-ready — enable `<cap>` to run them? (`sungen capability add <cap>`)"*. **Only on the user's yes** run `sungen capability add <cap>` then re-run those specs; on no, leave them skipped (they are NOT failures and NOT manual). **Never auto-install.**
109
143
 
@@ -53,6 +53,8 @@ Source modules: `src/exporters/*.ts`
53
53
 
54
54
  The CLI reads the **per-target result file first** (co-located with `.spec.ts`), then falls back to the global `test-results/results.json`. Per-target is preferred because the global file gets OVERWRITTEN each time Playwright runs, losing results from earlier targets.
55
55
 
56
+ **Mobile (per-OS deliverables):** an Appium run writes one result file per capability — `<name>-test-result.<android|ios>[.<env>].json`. For a mobile project (`platform: mobile`), a plain `sungen delivery <name>` (no `SUNGEN_ENV`) **auto-emits one deliverable PER OS** — `<name>-testcases.android.{csv,xlsx}` + `<name>-testcases.ios.{csv,xlsx}` — and does **NOT** write a base `<name>-testcases.{csv,xlsx}` (android/ios are separate platform runs, not locales of one run, so a base aggregate would be empty/misleading; a stale base pair is removed). The Appium spec (mocha `describe()/it()`) is recognized as compiled (issue #391), so each per-OS CSV shows real Passed/Failed with `@manual` rows as N/A. `SUNGEN_ENV=android|ios sungen delivery <name>` still works to target a single OS. The **Test Environment** column is OS-precise: it shows only that OS's app id from the dual-id `Path:` — the Android **package** (`com.kngroup.media.converter`) on android, the iOS **bundle id** (`com.kngroup.media.converter.dev`) on ios — never the combined dual-id.
57
+
56
58
  ---
57
59
 
58
60
  ## Column mapping (handled by CLI)
@@ -30,7 +30,88 @@ Try: browser_navigate(baseURL)
30
30
 
31
31
  Announce which mode is being used before Phase 1.
32
32
 
33
- ## Phase 1 — Audit selectors (always, no MCP)
33
+ ---
34
+
35
+ ## Mobile (Appium) variant
36
+
37
+ > **When to use:** `qa/capabilities.yaml` has `platform: mobile`. The command reads this file and dispatches here. The web phases below still apply for web projects.
38
+
39
+ ### Mechanism overview
40
+
41
+ | Web | Mobile |
42
+ |---|---|
43
+ | Switch via URL prefix / query param / UI switcher; persist via cookie / localStorage | Switch via **device locale** (`appium:language` / `appium:locale` caps + `noReset:false`) — wdio `resolveLocaleCaps` drives this at runtime |
44
+ | Capture via Playwright MCP `browser_snapshot` | Capture via **Appium MCP** (`select_device` → `appium_session_management` → `appium_get_page_source` / `appium_screenshot`) |
45
+ | Phase 6 writes selectors + test-data + Pages `{{base_path}}` + `locale-config.json` + `locale-fixture.ts` | Phase 6 writes **only** selectors + test-data (6a/6b/6c). No 6d, no 6f. |
46
+ | Handoff: `SUNGEN_ENV=<locale> npx playwright test` | Handoff: `SUNGEN_ENV=<locale> npm run test:mobile` |
47
+
48
+ ### Mobile Phase 1 — Audit selectors (same as web, no MCP)
49
+
50
+ Identical to the web Phase 1 below. Read the screen's `selectors/<feature>.yaml` and list every entry with hardcoded `name` or `value` text. Multi-source text rules for mobile: Android elements expose text via `@text` first, then `@content-desc`; iOS exposes via `@label` first, then `@value`. Treat both as potential locale-dependent candidates.
51
+
52
+ ### Mobile Phase 2 — Capture base locale (LIVE only)
53
+
54
+ 1. `select_device` — choose the connected device (or emulator/simulator).
55
+ 2. `appium_session_management(create)` with the app at the **base locale** (do not set `appium:language` / `appium:locale` — use the device's current locale, which should match the base test-data locale).
56
+ 3. Navigate to the target screen using the Background navigation recipe from the `.feature` file (same as `sungen-capture-mobile` does).
57
+ 4. `appium_get_page_source` + `appium_screenshot` — capture the accessibility tree and visual state.
58
+ 5. For each Phase-1 candidate: verify the hardcoded text appears in the page source (check `@text`, `@content-desc`, `@label`, `@value` attributes). Drop stale candidates that don't appear.
59
+
60
+ Save state as `baseLocale = { pageSource, screenshot }`.
61
+
62
+ ### Mobile Phase 3 — Switch locale (LIVE only) — device locale
63
+
64
+ There is **no URL prefix, query param, or browser storage injection on mobile**. The locale switch mechanism is always **device locale**:
65
+
66
+ 1. Close the current Appium session: `appium_session_management(delete)`.
67
+ 2. Relaunch with `appium:language` set to the language code (e.g. `ja`) and `appium:locale` set to the region code (e.g. `JP`), plus `appium:noReset: false` — this forces the app to re-run its first-launch locale detection from the OS locale, clearing any cached in-app override.
68
+ 3. Navigate to the target screen again (same Background recipe).
69
+ 4. `appium_get_page_source` + `appium_screenshot` — capture target-locale state.
70
+ 5. Compare a known Phase-1 candidate text between base and target snapshots — confirm text differs.
71
+
72
+ **Optional in-app language picker**: if the app has a Settings screen with a language selector, that can be used as an alternative to relaunching. Default is device locale (above). Only use in-app picker if the user confirms it or if `noReset: false` is known ineffective for this app (see risk note in phase spec).
73
+
74
+ ### Mobile Phases 3.5 / 3.6 — N/A on mobile (web-only)
75
+
76
+ **Skip entirely.** Phases 3.5 (browser storage diff) and 3.6 (storage verification via `addInitScript`) are Playwright / browser-only. On mobile, runtime locale is driven by `wdio resolveLocaleCaps()` reading `SUNGEN_LOCALE || SUNGEN_ENV` and setting `appium:language` / `appium:locale` caps automatically — no fixture injection needed.
77
+
78
+ ### Mobile Phase 4 — Diff base ↔ target (LIVE only)
79
+
80
+ Same logic as web Phase 4 — pair each surviving candidate with its translated text from the target-locale page source. Match by element type + position in the accessibility tree. Mark unmatched candidates as "needs manual".
81
+
82
+ ### Mobile Phase 5 — Confirm proposal
83
+
84
+ Same as web Phase 5. Present the proposal table; ask user to confirm / edit / cancel.
85
+
86
+ ### Mobile Phase 6 — Apply files
87
+
88
+ Write **only these three outputs**:
89
+
90
+ **6a. Update `selectors/<feature>.yaml`** — replace hardcoded `name`/`value` with `{{varName}}`. (Same as web 6a.)
91
+
92
+ **6b. Update `test-data/<feature>.yaml`** — append new keys under `# === i18n: <screen> ===`. (Same as web 6b.)
93
+
94
+ **6c. Create `test-data/<feature>.<locale>.yaml`** — overlay with only changed keys. Comment header: `# Run with: SUNGEN_ENV=<locale> npm run test:mobile`. (Same as web 6c but different run command.)
95
+
96
+ **6d — SKIP (web-only)**: no Pages `{{base_path}}` changes. Mobile has no URL prefix routing.
97
+
98
+ **6f — SKIP (web-only)**: no `locale-config.json` / `locale-fixture.ts`. wdio `resolveLocaleCaps` handles device locale at runtime — no Playwright context fixture needed.
99
+
100
+ **6e. Compile**: `sungen generate --screen <name>` (or `--flow`). The appium adapter is auto-selected in a mobile project.
101
+
102
+ ### Mobile Phase 7 — Hand off
103
+
104
+ Print summary (same fields as web Phase 7), then suggest:
105
+
106
+ ```
107
+ SUNGEN_ENV=<locale> npm run test:mobile
108
+ ```
109
+
110
+ Add note: *"If the device locale code differs from the overlay env name (e.g. `SUNGEN_ENV=staging-ja` but the device needs `ja`), set `SUNGEN_LOCALE=ja` — wdio `resolveLocaleCaps` reads `SUNGEN_LOCALE` as an override."*
111
+
112
+ ---
113
+
114
+ ## Phase 1 — Audit selectors (web + mobile, always, no MCP)
34
115
 
35
116
  For each `.feature` file under the screen, read the matching `selectors/<feature>.yaml`. List every entry whose `name` or `value` field contains literal text WITHOUT `{{…}}` AND is not a CSS/href selector.
36
117
 
@@ -54,7 +135,9 @@ nav kudos | name | Sun* Kudos | brand — skip
54
135
 
55
136
  If there are zero candidates and no `{{var}}` either, the screen has no localizable text → tell user and stop.
56
137
 
57
- ## Phase 2 — Capture base locale (LIVE only)
138
+ ## Phase 2 — Capture base locale (web, LIVE only)
139
+
140
+ > **Mobile**: see "Mobile Phase 2" in the Mobile (Appium) variant section above.
58
141
 
59
142
  1. Read `playwright.config.ts` for `baseURL`. Read `Path:` from `.feature` for the entry-point path.
60
143
  2. If the screen has `@auth:<role>` tags, load `specs/.auth/<role>.json` via `browser_set_storage_state` first.
@@ -69,7 +152,9 @@ Save state to memory as `baseLocale = { url, snapshot, storage }`.
69
152
 
70
153
  If page redirects to `/login` (auth blocker) → stop. Print: *"Auth blocked — cannot capture live page. Fall back to OFFLINE mode by re-running once auth works, or pick `Offline-only` next time."*
71
154
 
72
- ## Phase 3 — Switch locale (LIVE only) — detect mechanism + storage delta
155
+ ## Phase 3 — Switch locale (web, LIVE only) — detect mechanism + storage delta
156
+
157
+ > **Mobile**: see "Mobile Phase 3" in the Mobile (Appium) variant section above. Phases 3.5 and 3.6 are web-only — skip on mobile.
73
158
 
74
159
  Goal: identify (a) HOW to switch the app to the target locale, and (b) WHAT app-side storage state ends up holding the locale preference so a fresh BrowserContext can be primed identically without driving the UI.
75
160
 
@@ -161,7 +246,9 @@ If verification fails / can't run → drop confidence by one tier, ask user.
161
246
 
162
247
  Save mechanism + verified storage delta to memory for use in Phase 6.
163
248
 
164
- ## Phase 4 — Diff base ↔ target (LIVE only)
249
+ ## Phase 4 — Diff base ↔ target (LIVE only, web + mobile)
250
+
251
+ > **Mobile**: use Appium page-source snapshots instead of Playwright snapshots. Logic is identical.
165
252
 
166
253
  For each candidate from Phase 1 that survived Phase 2:
167
254
  - Find the SAME element in the target-locale snapshot (match by `role`+position, by `aria-label` if available, by neighbor structure)
@@ -196,7 +283,9 @@ If user wants to edit a row → fall through to a per-row prompt asking for `var
196
283
 
197
284
  In OFFLINE mode this phase is the same table but `target text` column is blank — user fills via subsequent prompts or by editing the overlay file after the skill finishes.
198
285
 
199
- ## Phase 6 — Apply changes (always, after confirmation)
286
+ ## Phase 6 — Apply changes (web, always, after confirmation)
287
+
288
+ > **Mobile**: follow "Mobile Phase 6" in the Mobile (Appium) variant section — only 6a/6b/6c apply. Skip 6d and 6f entirely.
200
289
 
201
290
  For each confirmed row:
202
291
 
@@ -224,7 +313,7 @@ nav_about: 'About SAA 2025'
224
313
  nav_awards: 'Awards Info'
225
314
  ```
226
315
 
227
- **6d. (URL/query mechanism only) Update Pages selectors**
316
+ **6d. (web, URL/query mechanism only) Update Pages selectors**
228
317
 
229
318
  If Phase 3 detected URL prefix:
230
319
 
@@ -251,7 +340,9 @@ If Phase 3 detected query param: similar but with `query_suffix: ''` / `query_su
251
340
 
252
341
  If Phase 3 detected UI switcher: do NOT modify Pages. Instead, write the storage delta from Phase 3.5 into `specs/generated/locale-config.json` (sibling of `specs/generated/base.ts` + `specs/generated/locale-fixture.ts`) (see 6f below).
253
342
 
254
- **6f. Storage injection config — `specs/generated/locale-config.json` (sibling of `specs/generated/base.ts` + `specs/generated/locale-fixture.ts`)**
343
+ **6f. (web-only) Storage injection config — `specs/generated/locale-config.json` (sibling of `specs/generated/base.ts` + `specs/generated/locale-fixture.ts`)**
344
+
345
+ > **Mobile**: skip 6f entirely. wdio `resolveLocaleCaps` sets the device locale via Appium caps — no Playwright fixture needed.
255
346
 
256
347
  Always write `specs/generated/locale-config.json` (sibling of `specs/generated/base.ts` + `specs/generated/locale-fixture.ts`) with the verified storage delta from Phase 3.5/3.6. This file is consumed by `specs/locale-fixture.ts` (auto-generated alongside `specs/base.ts`) — the fixture wraps Playwright's context, calls `addInitScript` to seed sessionStorage / localStorage, and `addCookies` for any cookies, BEFORE the first page navigation. Without this file, `SUNGEN_ENV=<locale>` only swaps test-data overlay — the browser would still boot in base locale.
257
348
 
@@ -290,15 +381,21 @@ Print summary:
290
381
  - N selectors converted to `{{var}}`
291
382
  - M base keys added to `test-data/<feature>.yaml`
292
383
  - K overlay keys written to `test-data/<feature>.<locale>.yaml`
293
- - Pages selectors updated: yes/no
294
- - Locale-switching mechanism: URL prefix `/en` / query `?lang=en` / UI switcher / manual
384
+ - Pages selectors updated: yes/no (web only; N/A on mobile)
385
+ - Locale-switching mechanism: URL prefix `/en` / query `?lang=en` / UI switcher / manual (web) | device locale via `appium:language`/`appium:locale` (mobile)
295
386
 
296
387
  Suggest:
297
388
 
298
389
  ```
390
+ # web
299
391
  /sungen:run-test <name> --env <locale>
392
+
393
+ # mobile
394
+ SUNGEN_ENV=<locale> npm run test:mobile
300
395
  ```
301
396
 
397
+ > **Mobile note**: if the device locale code differs from the overlay env name (e.g. `SUNGEN_ENV=staging-ja` but device needs `ja`), set `SUNGEN_LOCALE=ja` — wdio `resolveLocaleCaps` reads it as an override.
398
+
302
399
  ## Multi-feature screens
303
400
 
304
401
  If the screen has multiple `.feature` files (e.g. `home.feature` + `home-modal.feature`), repeat Phase 1 → Phase 6 for each feature file with its own selectors + test-data pair. Phase 2 + 3 (live capture + locale switch detection) run **once per screen** — the mechanism is the same. Phase 4 (text diff) runs per feature because each has its own scope of UI.