@leejungkiin/awkit 1.0.5 β†’ 1.0.7

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.
@@ -0,0 +1,312 @@
1
+ # πŸ”¨ Phase 3: Logic Build (Per Feature) β€” iOS
2
+
3
+ > **Zoom Level:** 3 β€” Code Implementation
4
+ > **Goal:** Code logic behind the APPROVED UI shell for ONE feature.
5
+ > **Input:** Approved Blueprint + Working SwiftUI Shell from Phase 2.
6
+ > **Output:** Feature fully wired β€” UI + logic connected.
7
+
8
+ ---
9
+
10
+ ## βœ… PREREQUISITES
11
+
12
+ Before writing ANY logic code, confirm:
13
+ - [ ] Phase 0 App Map: approved
14
+ - [ ] Phase 1 Architecture Blueprint: approved
15
+ - [ ] Phase 2 Contracts: approved for THIS feature
16
+ - [ ] Phase 2 UI Shell: approved, runs in Preview/Simulator
17
+
18
+ > ⚠️ If UI is not approved yet, STOP. Go back to Phase 2.
19
+
20
+ ---
21
+
22
+ ## πŸ“‹ Implementation Order
23
+
24
+ ### 3.1: Domain Layer
25
+
26
+ Implement from contracts defined in Phase 2:
27
+
28
+ 1. **Models** β€” structs (already drafted in 2.2, create actual files)
29
+ 2. **Repository protocols** β€” (already drafted in 2.3, create files)
30
+ 3. **UseCases** β€” implement execute() with repository calls
31
+
32
+ ```swift
33
+ struct LoginUseCase {
34
+ private let authRepo: AuthRepository
35
+
36
+ func execute(email: String, password: String) async throws -> User {
37
+ try await authRepo.login(email: email, password: password)
38
+ }
39
+ }
40
+ ```
41
+
42
+ ### 3.2: Data Layer
43
+
44
+ 1. **DTOs** β€” Codable structs matching API JSON
45
+ 2. **API Client** β€” async URLSession with proper error handling
46
+ 3. **SwiftData @Model** classes (if applicable)
47
+ 4. **Keychain / UserDefaults** wrappers (if applicable)
48
+ 5. **Repository implementation** β€” offline-first pattern
49
+
50
+ ```swift
51
+ final class AuthRepositoryImpl: AuthRepository {
52
+ private let apiClient: APIClient
53
+ private let tokenStore: TokenStore
54
+
55
+ func login(email: String, password: String) async throws -> User {
56
+ let dto = try await apiClient.request(
57
+ AuthEndpoint.login(email: email, password: password),
58
+ responseType: LoginResponseDTO.self
59
+ )
60
+ await tokenStore.save(dto.accessToken)
61
+ return dto.user.toDomain()
62
+ }
63
+
64
+ func isLoggedIn() -> Bool {
65
+ tokenStore.hasToken
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### 3.3: DI Container
71
+
72
+ ```swift
73
+ @MainActor
74
+ final class AppContainer {
75
+ // Singletons
76
+ lazy var apiClient = APIClient(baseURL: Config.apiBaseURL)
77
+ lazy var tokenStore = TokenStore()
78
+
79
+ // Repositories
80
+ lazy var authRepository: AuthRepository = AuthRepositoryImpl(
81
+ apiClient: apiClient,
82
+ tokenStore: tokenStore
83
+ )
84
+
85
+ // UseCases
86
+ func makeLoginUseCase() -> LoginUseCase {
87
+ LoginUseCase(authRepo: authRepository)
88
+ }
89
+
90
+ // ViewModels
91
+ func makeLoginViewModel() -> LoginViewModel {
92
+ LoginViewModel(loginUseCase: makeLoginUseCase())
93
+ }
94
+ }
95
+ ```
96
+
97
+ ### 3.4: ViewModel
98
+
99
+ Implement using ViewState + Events + Actions from Phase 2.6:
100
+
101
+ ```swift
102
+ @Observable
103
+ final class LoginViewModel {
104
+ var state = LoginViewState()
105
+
106
+ private let loginUseCase: LoginUseCase
107
+ private var onEvent: ((LoginEvent) -> Void)?
108
+
109
+ init(loginUseCase: LoginUseCase) {
110
+ self.loginUseCase = loginUseCase
111
+ }
112
+
113
+ func setEventHandler(_ handler: @escaping (LoginEvent) -> Void) {
114
+ self.onEvent = handler
115
+ }
116
+
117
+ func handle(_ action: LoginAction) {
118
+ switch action {
119
+ case .updateEmail(let email):
120
+ state.email = email
121
+ case .updatePassword(let password):
122
+ state.password = password
123
+ case .togglePasswordVisibility:
124
+ state.isPasswordVisible.toggle()
125
+ case .submit:
126
+ login()
127
+ }
128
+ }
129
+
130
+ private func login() {
131
+ state.isLoading = true
132
+ state.error = nil
133
+ Task {
134
+ do {
135
+ let _ = try await loginUseCase.execute(
136
+ email: state.email,
137
+ password: state.password
138
+ )
139
+ state.isLoading = false
140
+ onEvent?(.navigateToHome)
141
+ } catch {
142
+ state.isLoading = false
143
+ state.error = error.localizedDescription
144
+ }
145
+ }
146
+ }
147
+ }
148
+ ```
149
+
150
+ ### 3.5: Wire UI ↔ Logic ⭐ (NOT "code new UI")
151
+
152
+ > **This step does NOT create new UI.** The UI already exists from Phase 2.8.
153
+ > Only CONNECT the existing UI shell to the real ViewModel.
154
+
155
+ **Changes needed on the UI shell:**
156
+
157
+ ```swift
158
+ // Phase 2 code stays as the STATELESS "Content" view (for Preview):
159
+ struct LoginScreenContent: View {
160
+ var state: LoginViewState = .normal
161
+ var onAction: (LoginAction) -> Void = { _ in }
162
+
163
+ var body: some View {
164
+ // ... all UI code from Phase 2.8 β€” DO NOT MODIFY
165
+ }
166
+ }
167
+
168
+ // Previews still work:
169
+ #Preview("Normal") { LoginScreenContent(state: .normal) }
170
+ #Preview("Loading") { LoginScreenContent(state: .loading) }
171
+
172
+ // ADD a NEW wrapper that wires ViewModel:
173
+ struct LoginScreen: View {
174
+ @State private var viewModel: LoginViewModel
175
+ var onNavigateToHome: () -> Void
176
+
177
+ init(container: AppContainer, onNavigateToHome: @escaping () -> Void) {
178
+ _viewModel = State(initialValue: container.makeLoginViewModel())
179
+ self.onNavigateToHome = onNavigateToHome
180
+ }
181
+
182
+ var body: some View {
183
+ LoginScreenContent(
184
+ state: viewModel.state,
185
+ onAction: viewModel.handle
186
+ )
187
+ .onAppear {
188
+ viewModel.setEventHandler { event in
189
+ switch event {
190
+ case .navigateToHome:
191
+ onNavigateToHome()
192
+ case .showError(let msg):
193
+ // handle
194
+ break
195
+ }
196
+ }
197
+ }
198
+ }
199
+ }
200
+ ```
201
+
202
+ **Wire Checklist:**
203
+ - [ ] Wrapper view injects ViewModel from DI container
204
+ - [ ] State bindings: ViewModel.state β†’ Content view
205
+ - [ ] Action bindings: Content onAction β†’ ViewModel.handle()
206
+ - [ ] Event handling: navigation, alerts
207
+ - [ ] Previews still work (they use the stateless Content view)
208
+
209
+ ### 3.6: Integration Test ⭐
210
+
211
+ Verify UI + logic end-to-end:
212
+
213
+ ```markdown
214
+ ### πŸ§ͺ Integration: [Feature]
215
+
216
+ Functional:
217
+ - [ ] API calls succeed, data displays on UI
218
+ - [ ] Loading state shows/hides at right time
219
+ - [ ] Error state displays correct message
220
+ - [ ] Navigation works as expected
221
+ - [ ] Form validation works
222
+
223
+ Data:
224
+ - [ ] Request format matches original app
225
+ - [ ] Response parses correctly
226
+ - [ ] Token/session stored properly
227
+ - [ ] Crypto output matches original (if applicable)
228
+
229
+ Edge Cases:
230
+ - [ ] Empty input handling
231
+ - [ ] Network error handling
232
+ - [ ] Back navigation
233
+ - [ ] App backgrounding/foregrounding
234
+ ```
235
+
236
+ ---
237
+
238
+ ## πŸ”’ CRYPTO UTILS (Special Handling)
239
+
240
+ If the feature involves encryption/hashing:
241
+
242
+ 1. Read disassembly carefully β€” exact algorithm, padding, encoding
243
+ 2. Implement in Swift β€” preserve exact input/output
244
+ 3. Unit test IMMEDIATELY with known pairs
245
+
246
+ ```swift
247
+ import CryptoKit
248
+ import CommonCrypto
249
+
250
+ enum CryptoUtils {
251
+ static func md5Hash(_ input: String) -> String {
252
+ let data = Data(input.utf8)
253
+ var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
254
+ data.withUnsafeBytes { CC_MD5($0.baseAddress, CC_LONG(data.count), &digest) }
255
+ return digest.map { String(format: "%02x", $0) }.joined()
256
+ }
257
+ }
258
+
259
+ // MANDATORY test
260
+ final class CryptoUtilsTests: XCTestCase {
261
+ func testMD5MatchesOriginal() {
262
+ XCTAssertEqual("expected_hash", CryptoUtils.md5Hash("known_input"))
263
+ }
264
+ }
265
+ ```
266
+
267
+ > ⚠️ Crypto functions MUST produce identical output. Any mismatch breaks server communication.
268
+
269
+ ---
270
+
271
+ ## βœ… Checkpoint
272
+
273
+ ```markdown
274
+ ## βœ… Feature Complete: [Feature Name]
275
+
276
+ ### Files created:
277
+ - Domain/Models/User.swift
278
+ - Domain/Repositories/AuthRepository.swift
279
+ - Domain/UseCases/LoginUseCase.swift
280
+ - Data/Network/Endpoints/AuthEndpoint.swift
281
+ - Data/Network/DTOs/LoginRequestDTO.swift, LoginResponseDTO.swift
282
+ - Data/Repositories/AuthRepositoryImpl.swift
283
+ - DI/AppContainer.swift (updated)
284
+ - Presentation/Screens/Auth/LoginViewModel.swift
285
+ - Presentation/Screens/Auth/LoginScreen.swift ← wired (from Phase 2)
286
+
287
+ ### Tests:
288
+ - [ ] Crypto utils verified (if applicable)
289
+ - [ ] API contract matches original
290
+ - [ ] UI + Logic e2e works
291
+
292
+ ### ⏭️ Next Feature: [Name]
293
+ β†’ Return to Phase 2 (Blueprint + UI Design)
294
+ ```
295
+
296
+ ---
297
+
298
+ ## πŸ”„ Feature Loop
299
+
300
+ ```
301
+ Phase 2 (Blueprint + UI for Feature X) β†’ GATE β†’ Phase 3 (Logic for X) β†’ Checkpoint
302
+ ↓
303
+ Phase 2 (Blueprint + UI for Feature Y) β†’ GATE β†’ Phase 3 (Logic for Y) β†’ Checkpoint
304
+ ↓
305
+ ... (repeat for all features from Architecture Build Order)
306
+ ↓
307
+ Phase 4: Final Parity Check & Quality Gate
308
+ ```
309
+
310
+ ---
311
+
312
+ *Phase 3: Logic Build β€” Wire logic behind approved UI*
@@ -1,170 +1,210 @@
1
1
  ---
2
- description: πŸ”¨ RE Android Phase 2+3 β€” Per-feature Blueprint β†’ Implementation β†’ Parity Check
2
+ description: πŸ”¨ RE Android Phase 2+3+4 β€” Blueprint + UI Shell β†’ Logic Build β†’ Final Parity (UI-First)
3
3
  parent: reverse-android
4
4
  ---
5
5
 
6
- # /re-android-build β€” Blueprint & Build (Per Feature)
6
+ # /re-android-build β€” Blueprint + UI + Build (Per Feature)
7
7
 
8
- > **Parent:** [`/reverse-android`](reverse-android.md) β†’ Phase 2+3
8
+ > **Parent:** [`/reverse-android`](reverse-android.md) β†’ Phase 2+3+4
9
9
  > **Prerequisite:** Completed Architecture from [`/re-android-design`](reverse-android-design.md)
10
- > **Skill:** `smali-to-kotlin` β†’ `phase-2-blueprint.md` + `phase-3-build.md`
10
+ > **Skill:** `smali-to-kotlin` β†’ `phase-2-blueprint-ui.md` + `phase-3-logic-build.md`
11
11
 
12
12
  ---
13
13
 
14
- ## πŸ”„ Feature Loop
14
+ ## πŸ”„ Feature Loop (UI-First)
15
15
 
16
16
  ```
17
17
  For each feature (from Architecture Build Order):
18
- Phase 2: Blueprint (Zoom 2 β€” signatures only)
19
- ↓ [User approves]
20
- Phase 3: Implementation (Zoom 3 β€” full code)
21
- ↓ [Checkpoint]
18
+ Phase 2: Blueprint + UI (contracts + visual shell)
19
+ ↓ 🚦 GATE: User approves UI + contracts
20
+ Phase 3: Logic Build (domain β†’ data β†’ wire)
21
+ ↓ πŸ“Š CHECKPOINT
22
22
  β†’ Next feature
23
23
  ```
24
24
 
25
25
  ---
26
26
 
27
- ## πŸ“ Phase 2: Feature Blueprint (Zoom 2)
27
+ ## πŸ“πŸŽ¨ Phase 2: Blueprint + UI Design
28
28
 
29
- > **Output:** Contracts, interfaces, state design. **Signatures only, no bodies.**
29
+ > **Output:** Approved contracts + Working Compose UI shell with mock data.
30
30
 
31
- ### 2.1: Deep Smali Reading
31
+ ### Part A: Contracts (signatures only)
32
32
 
33
- Read Smali files for the chosen feature. Extract:
34
- - Class hierarchy, fields, method signatures
35
- - String constants (URLs, keys, messages)
36
- - Control flow β†’ business rules (document, don't code)
37
-
38
- ### 2.2: Contracts
39
-
40
- Define for this feature:
33
+ #### 2.1: Deep Smali Reading
34
+ Read Smali files for the chosen feature. Extract class hierarchy, fields, method signatures,
35
+ string constants, control flow. See `smali-reading-guide.md`.
41
36
 
37
+ #### 2.2–2.5: Define Contracts
42
38
  ```kotlin
43
- // Domain Model
44
- data class [Model](val field1: Type, ...)
39
+ // 2.2 Domain Model
40
+ data class [Model](val field: Type, ...)
45
41
 
46
- // Repository Interface
42
+ // 2.3 Repository Interface
47
43
  interface [Feature]Repository {
48
44
  suspend fun [method](...): Result<[Type]>
49
- fun [stream](): Flow<[Type]>
50
45
  }
51
46
 
52
- // API Interface
47
+ // 2.4 API Interface
53
48
  interface [Feature]Api {
54
49
  @[METHOD]("[endpoint]")
55
50
  suspend fun [method](...): [Response]
56
51
  }
57
52
 
58
- // UseCase
53
+ // 2.5 UseCase
59
54
  class [Action]UseCase(repo: [Feature]Repository) {
60
55
  suspend operator fun invoke(...): Result<[Type]> // TODO()
61
56
  }
62
57
  ```
63
58
 
64
- ### 2.3: UI State Design
65
-
59
+ #### 2.6: UI State Design
66
60
  ```kotlin
67
61
  data class [Screen]UiState(
68
62
  val field: Type = default,
69
63
  val isLoading: Boolean = false,
70
64
  val error: String? = null
71
65
  )
72
-
73
66
  sealed interface [Screen]Event { /* navigation, snackbar */ }
74
67
  sealed interface [Screen]Action { /* user interactions */ }
75
68
  ```
76
69
 
77
- ### 2.4: Wireframe + File List
70
+ ### Part B: UI Visual Shell
71
+
72
+ #### 2.7: Resource Extraction ⭐ (BEFORE UI code!)
73
+
74
+ ```bash
75
+ # Only resources for THIS screen
76
+ grep -o '@drawable/[a-z_]*' [apktool_dir]/res/layout/activity_[screen].xml | sort -u
77
+ grep -o '@color/[a-z_]*' [apktool_dir]/res/layout/activity_[screen].xml | sort -u
78
+ ```
78
79
 
79
- ASCII wireframe + list of files to create.
80
+ Copy ONLY needed resources. Verify they compile.
80
81
 
81
- ### βœ… Blueprint Gate
82
+ #### 2.8: UI Implementation ⭐ (Visual shell with mock data)
82
83
 
84
+ - Use UiState from 2.6 with hardcoded defaults
85
+ - Use REAL resources from 2.7
86
+ - Create `[Screen]Content` composable (stateless)
87
+ - Match visual parity with original app
88
+ - NO ViewModel connection, NO real API calls
89
+
90
+ ```kotlin
91
+ @Composable
92
+ fun [Screen]Content(
93
+ uiState: [Screen]UiState = [Screen]UiState(), // Mock
94
+ onAction: ([Screen]Action) -> Unit = {} // No-op
95
+ ) {
96
+ // Full Compose UI matching original app
97
+ }
98
+
99
+ @Preview @Composable
100
+ private fun NormalPreview() { AppTheme { [Screen]Content() } }
101
+
102
+ @Preview @Composable
103
+ private fun LoadingPreview() { AppTheme { [Screen]Content([Screen]UiState(isLoading = true)) } }
104
+
105
+ @Preview @Composable
106
+ private fun ErrorPreview() { AppTheme { [Screen]Content([Screen]UiState(error = "Error")) } }
83
107
  ```
84
- "πŸ“ Blueprint cho [Feature] xong. Anh xem OK khΓ΄ng? β†’ Em bαΊ―t Δ‘αΊ§u code."
108
+
109
+ #### 2.9: Visual Parity Check ⭐
110
+
111
+ Compare with original app:
112
+ - [ ] Layout structure matches
113
+ - [ ] Colors, typography, spacing correct
114
+ - [ ] Icons/images positioned correctly
115
+ - [ ] All states: normal, loading, error, empty
116
+
117
+ ### 🚦 UI + Contracts Gate (MANDATORY)
118
+
119
+ ```
120
+ "πŸ“πŸŽ¨ Blueprint + UI cho [Feature] xong:
121
+ πŸ“ Contracts: [N] models, [N] repos, [N] use cases, [N] APIs
122
+ 🎨 UI: [Screen] with [N] state previews
123
+ πŸ“Έ Visual Parity: [OK / needs adjustment]
124
+
125
+ β†’ βœ… Approve β†’ Phase 3 (Logic Build)
126
+ β†’ 🎨 Adjust UI β†’ fix then re-check
127
+ β†’ πŸ“ Adjust contracts β†’ revise"
85
128
  ```
86
129
 
130
+ > ⚠️ **DO NOT proceed to Phase 3 without user approval.**
131
+
87
132
  ---
88
133
 
89
- ## πŸ”¨ Phase 3: Implementation (Zoom 3)
134
+ ## πŸ”¨ Phase 3: Logic Build
90
135
 
91
- > **Output:** Full production-quality Kotlin code for THIS feature only.
136
+ > **Output:** Full production-quality Kotlin code. Wire logic to EXISTING UI.
92
137
 
93
138
  ### 3.1: Domain Layer
94
-
95
- - Models (data classes from Blueprint)
96
- - Repository interfaces (from Blueprint)
97
- - UseCases (implement invoke with repo calls)
139
+ Models + Repository interfaces + UseCases (implement invoke with repo calls)
98
140
 
99
141
  ### 3.2: Data Layer
100
-
101
- - DTOs (@Serializable)
102
- - Retrofit API interface
103
- - Room entities + DAOs (if applicable)
104
- - Repository implementation (offline-first)
142
+ DTOs + Retrofit API + Room (if applicable) + Repository implementation
105
143
 
106
144
  ### 3.3: DI Module
107
-
108
- - Hilt @Module with @Binds for repository
145
+ Hilt @Module with @Binds for repository
109
146
 
110
147
  ### 3.4: ViewModel
148
+ @HiltViewModel with StateFlow + SharedFlow, implements onAction()
111
149
 
112
- - @HiltViewModel with StateFlow + SharedFlow
113
- - Implement onAction() handler from Blueprint actions
114
-
115
- ### 3.5: Compose Screen
150
+ ### 3.5: Wire UI ↔ Logic ⭐ (NOT "code new UI")
116
151
 
117
- - Collect state with collectAsStateWithLifecycle()
118
- - UI from wireframe
119
- - LaunchedEffect for events
152
+ The UI already exists from Phase 2.8. Only CONNECT it:
120
153
 
121
- ### 3.6: Resource Extraction (On-Demand only)
122
-
123
- ```bash
124
- # Only resources for THIS screen
125
- grep -o '@drawable/[a-z_]*' [apktool_dir]/res/layout/activity_[screen].xml | sort -u
154
+ ```kotlin
155
+ // Keep stateless Content composable from Phase 2 (for Preview):
156
+ // [Screen]Content(uiState, onAction) β€” DO NOT MODIFY
157
+
158
+ // ADD wrapper that wires ViewModel:
159
+ @Composable
160
+ fun [Screen](
161
+ viewModel: [Screen]ViewModel = hiltViewModel(),
162
+ onNavigate: () -> Unit
163
+ ) {
164
+ val uiState by viewModel.uiState.collectAsStateWithLifecycle()
165
+ LaunchedEffect(Unit) {
166
+ viewModel.events.collect { event -> /* handle navigation */ }
167
+ }
168
+ [Screen]Content(uiState = uiState, onAction = viewModel::onAction)
169
+ }
126
170
  ```
127
171
 
128
- ### πŸ”’ Crypto Utils (Special)
172
+ ### 3.6: Integration Test ⭐
173
+ - [ ] API calls succeed, data displays
174
+ - [ ] Loading/error states work
175
+ - [ ] Navigation correct
176
+ - [ ] Crypto output matches (if applicable)
129
177
 
130
- If feature involves crypto/hashing:
131
- 1. Read Smali carefully (exact algorithm)
132
- 2. Implement in Kotlin
133
- 3. Unit test IMMEDIATELY with known pairs
134
-
135
- > ⚠️ Crypto MUST produce identical output to original app.
178
+ ### πŸ”’ Crypto Utils (Special)
179
+ If crypto involved: implement + unit test IMMEDIATELY with known pairs.
180
+ > ⚠️ MUST produce identical output.
136
181
 
137
182
  ### βœ… Feature Checkpoint
138
183
 
139
184
  ```markdown
140
185
  ## βœ… Feature Complete: [Name]
141
-
142
- ### Files created: [list]
143
- ### Resources extracted: [only needed]
144
- ### Tests: [crypto verified? API matches?]
145
-
146
- ### ⏭️ Next Feature: [Name]
147
- β†’ Return to Phase 2 (Blueprint) for next feature
186
+ Files: [list] | Resources: [count] | Tests: [status]
187
+ ⏭️ Next Feature: [Name] β†’ Return to Phase 2
148
188
  ```
149
189
 
150
190
  ---
151
191
 
152
- ## βœ… Final Parity Check (After ALL features)
192
+ ## βœ… Phase 4: Final Parity Check (After ALL features)
153
193
 
154
194
  ### Checklist
155
195
  - [ ] API Parity β€” all endpoints match (headers, body, encoding)
156
196
  - [ ] Data Parity β€” crypto/hash output identical
157
197
  - [ ] UI Parity β€” screen-by-screen comparison
158
198
  - [ ] Edge Cases β€” empty states, errors, offline, lifecycle
159
- - [ ] Build & Test: `./gradlew assembleDebug && ./gradlew test && ./gradlew lint`
199
+ - [ ] Build: `./gradlew assembleDebug && ./gradlew test && ./gradlew lint`
160
200
 
161
201
  ### πŸŽ‰ Final Summary
162
202
 
163
203
  ```markdown
164
204
  ## βœ… Reverse Engineering Complete!
165
- - Screens: [count] | Features: [count]
166
- - Libs reused: [count] | Replaced: [count]
167
- - Tests: [pass/fail] | Lint: [pass/warnings]
205
+ - Screens: [N] | Features: [N]
206
+ - Libs reused: [N] | Replaced: [N]
207
+ - Tests: [pass/fail] | Lint: [warnings]
168
208
 
169
209
  ⏭️ Next: /test β†’ /deploy β†’ /code-janitor
170
210
  ```
@@ -175,8 +215,8 @@ If feature involves crypto/hashing:
175
215
 
176
216
  - **Parent:** [`/reverse-android`](reverse-android.md)
177
217
  - **Previous:** [`/re-android-design`](reverse-android-design.md) (Phase 1)
178
- - **Skill:** `smali-to-kotlin` β†’ `phase-2-blueprint.md` + `phase-3-build.md`
218
+ - **Skill:** `smali-to-kotlin` β†’ `phase-2-blueprint-ui.md` + `phase-3-logic-build.md`
179
219
 
180
220
  ---
181
221
 
182
- *re-android-build v3.0.0 β€” Phase 2+3: Blueprint & Build*
222
+ *re-android-build v4.0.0 β€” UI-First Blueprint + Build*
@@ -84,16 +84,19 @@ app/src/main/java/[package]/
84
84
  └── util/
85
85
  ```
86
86
 
87
- ## πŸ”’ Step 6: Build Order
87
+ ## πŸ”’ Step 6: Build Order (UI-First) ⭐
88
88
 
89
89
  | # | Phase | Scope | Complexity |
90
90
  |---|-------|-------|-----------|
91
- | 1 | 🟒 Setup | Project + DI + Theme | Low |
92
- | 2 | 🟒 Models | Domain data classes | Low |
93
- | 3 | 🟑 Data | API + Room + DataStore | Medium |
94
- | 4 | 🟑 Utils | Crypto, formatters | Medium |
95
- | 5 | πŸ”΄ Features | Per-feature Blueprintβ†’Build | High |
96
- | N | πŸ”΄ Final | Parity check | High |
91
+ | 1 | 🟒 Foundation | Project + DI skeleton + Theme/Design System | Low |
92
+ | 2 | 🟒 Navigation | Routes, tab bar, NavGraph | Low |
93
+ | 3 | πŸ”΅ Per Feature | Blueprint (contracts) + UI Shell (visual) | Medium |
94
+ | 4 | 🚦 UI Gate | User approves UI before logic | β€” |
95
+ | 5 | 🟑 Per Feature | Logic Build (Domain β†’ Data β†’ VM β†’ Wire UI) | High |
96
+ | 6 | πŸ“¦ SDKs | Third-party SDK + Native libs integration | Medium |
97
+ | N | πŸ”΄ Final | Full Parity Check | High |
98
+
99
+ > **UI-First:** Design and approve UI before coding logic for each feature.
97
100
 
98
101
  ## πŸ”§ Step 7: Tech Stack Confirmation
99
102