Skip to content

Commit 36bce2d

Browse files
committed
chore: update agent rules
1 parent db4e403 commit 36bce2d

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

AGENTS.md

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ GEO=false E2E=true ./gradlew assembleDevRelease
4545
## Architecture Overview
4646

4747
### Tech Stack
48+
4849
- **Language**: Kotlin
4950
- **UI Framework**: Jetpack Compose with Material3
5051
- **Architecture**: MVVM with Hilt dependency injection
@@ -57,6 +58,7 @@ GEO=false E2E=true ./gradlew assembleDevRelease
5758
- **Storage**: DataStore with json files
5859

5960
### Project Structure
61+
6062
- **app/src/main/java/to/bitkit/**
6163
- **App.kt**: Application class with Hilt setup
6264
- **ui/**: All UI components
@@ -75,34 +77,42 @@ GEO=false E2E=true ./gradlew assembleDevRelease
7577
- **usecases/**: Domain layer: use cases
7678

7779
### Key Architecture Patterns
80+
7881
1. **Single Activity Architecture**: MainActivity hosts all screens via Compose Navigation
7982
2. **Repository Pattern**: Repositories abstract data sources from ViewModels
8083
3. **Service Layer**: Core business logic in services (LightningService, WalletService)
8184
4. **Reactive State Management**: ViewModels expose UI state via StateFlow
8285
5. **Coroutine-based Async**: All async operations use Kotlin coroutines
8386

8487
### Build Variants
88+
8589
- **dev**: Regtest network for development
8690
- **tnet**: Testnet network
8791
- **mainnet**: Production (currently commented out)
8892

8993
## Common Pitfalls
9094

9195
### ❌ DON'T
96+
9297
```kotlin
9398
GlobalScope.launch { } // Use viewModelScope
9499
val result = nullable!!.doSomething() // Use safe calls
95100
Text("Send Payment") // Use string resources
96101
class Service(@Inject val vm: ViewModel) // Never inject VMs
102+
97103
suspend fun getData() = runBlocking { } // Use withContext
98104
```
99105

100106
### ✅ DO
107+
101108
```kotlin
102109
viewModelScope.launch { }
103110
val result = nullable?.doSomething() ?: default
104111
Text(stringResource(R.string.send_payment))
105-
class Service { fun process(data: Data) }
112+
class Service {
113+
fun process(data: Data)
114+
}
115+
106116
suspend fun getData() = withContext(Dispatchers.IO) { }
107117
```
108118

@@ -117,29 +127,32 @@ suspend fun getData() = withContext(Dispatchers.IO) { }
117127
## Common Patterns
118128

119129
### ViewModel State
130+
120131
```kotlin
121132
private val _uiState = MutableStateFlow(InitialState)
122133
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
123134

124135
fun updateState(action: Action) {
125-
viewModelScope.launch {
126-
_uiState.update { it.copy(/* fields */) }
127-
}
136+
viewModelScope.launch {
137+
_uiState.update { it.copy(/* fields */) }
138+
}
128139
}
129140
```
130141

131142
### Repository
143+
132144
```kotlin
133145
suspend fun getData(): Result<Data> = withContext(Dispatchers.IO) {
134-
runCatching {
135-
Result.success(apiService.fetchData())
136-
}.onFailure { e ->
137-
Logger.error("Failed", e = e, context = TAG)
138-
}
146+
runCatching {
147+
Result.success(apiService.fetchData())
148+
}.onFailure { e ->
149+
Logger.error("Failed", e = e, context = TAG)
150+
}
139151
}
140152
```
141153

142154
### Rules
155+
143156
- USE coding rules from `.cursor/default.rules.mdc`
144157
- ALWAYS run `./gradlew compileDevDebugKotlin` after code changes to verify code compiles
145158
- ALWAYS run `./gradlew testDevDebugUnitTest` after code changes to verify tests succeed and fix accordingly
@@ -150,7 +163,7 @@ suspend fun getData(): Result<Data> = withContext(Dispatchers.IO) {
150163
- USE `git diff HEAD sourceFilePath` to diff an uncommitted file against the last commit
151164
- ALWAYS check existing code patterns before implementing new features
152165
- USE existing extensions and utilities rather than creating new ones
153-
- ALWAYS consider applying YAGNI (You Aren't Gonna Need It) principle for new code
166+
- ALWAYS consider applying YAGNI (You Aren't Gonna Need It) principle for new code
154167
- ALWAYS reuse existing constants
155168
- ALWAYS ensure a method exist before calling it
156169
- ALWAYS remove unused code after refactors
@@ -184,11 +197,14 @@ suspend fun getData(): Result<Data> = withContext(Dispatchers.IO) {
184197
- ALWAYS add business logic to Repository layer via methods returning `Result<T>` and use it in ViewModels
185198
- ALWAYS use services to wrap RUST code exposed via bindings
186199
- ALWAYS order upstream architectural data flow this way: `UI -> ViewModel -> Repository -> RUST` and vice-versa for downstream
187-
- ALWAYS add new string string resources in alphabetical order in `strings.xml`
200+
- ALWAYS add new localizable string string resources in alphabetical order in `strings.xml`
201+
- NEVER add string resources for strings used only in dev settings screens and previews and never localize acronyms
188202
- ALWAYS use template in `.github/pull_request_template.md` for PR descriptions
189203
- ALWAYS wrap `ULong` numbers with `USat` in arithmetic operations, to guard against overflows
204+
- PREFER to use one-liners with `run {}` when applicable, e.g. `override fun someCall(value: String) = run { this.value = value}`
190205

191206
### Architecture Guidelines
207+
192208
- Use `LightningNodeService` to manage background notifications while the node is running
193209
- Use `LightningService` to wrap node's RUST APIs and manage the inner lifecycle of the node
194210
- Use `LightningRepo` to defining the business logic for the node operations, usually delegating to `LightningService`

0 commit comments

Comments
 (0)