with one click
network-retrofit
// Trigger: API & Networking. Implementing Retrofit services, Moshi adapters, DTO mapping, and synchronous execution patterns.
// Trigger: API & Networking. Implementing Retrofit services, Moshi adapters, DTO mapping, and synchronous execution patterns.
Test-driven development with red-green-refactor loop. MUST be triggered during ANY coding session involving feature implementation or bug fixes or specifications.
Evaluates skills based on discoverability, agent-friendliness, and consumption efficiency. Returns a Letter Grade (A+ to F) and actionable coaching.
Validating agent skills against the agentskills.io specification and generating compliance reports.
Trigger: Data Flow & Modules. Implementing Repositories, managing cross-module boundaries, and handling async work with Coroutines.
Trigger: Pre-Commit/Final Review. Validating code against Serenity’s 'Golden Standards' for architecture, security, performance, and testing before merging.
Trigger: Presenter Logic. Managing Moxy MVP state, Presenter lifecycle, and view delegation without @InjectPresenter.
| name | network-retrofit |
| description | Trigger: API & Networking. Implementing Retrofit services, Moshi adapters, DTO mapping, and synchronous execution patterns. |
Use Retrofit 2 interfaces for all network calls. Group related endpoints.
interface UsersService {
@GET("Users/{userId}")
suspend fun getUser(@Path("userId") userId: String): UserDTO
}
While we use suspend functions, the underlying implementation often uses a custom extension to handle Retrofit Call objects synchronously within a coroutine context for better error handling.
executeOrThrow Extensionprivate fun <T> Call<T>.executeOrThrow(): T {
val response = execute()
if (response.isSuccessful) {
return response.body() ?: throw IOException("Response was null")
}
throw IOException("Request failed with code ${response.code()} and message ${response.message()}")
}
Standard for JSON parsing. Use @Json for explicit mapping.
@JsonClass(generateAdapter = true)
data class UserDTO(
@Json(name = "Name") val name: String,
@Json(name = "Id") val id: String
)
For non-standard types like LocalDateTime.
class LocalDateTimeAdapter {
@FromJson
fun fromJson(json: String): LocalDateTime = LocalDateTime.parse(json)
@ToJson
fun toJson(value: LocalDateTime): String = value.toString()
}
Decouple the application from API schemas by mapping DTOs to domain models immediately.
class UserRepository(private val service: UsersService) {
suspend fun getUser(id: String): User = withContext(Dispatchers.IO) {
val dto = service.getUser(id)
dto.toDomain()
}
}