本文へ移動
cccskills
無料GitHub で公開

compose-data

Owns repositories, data sources and mapping for Compose and Compose Multiplatform apps: DTO to domain to UiModel boundaries, Ktor clients and bearer auth, WebSocket and SSE, Room, DataStore, Paging 3, offline-first and data-layer tests. Use when writing or reviewing a repository, data source, DTO, mapper, HttpClient, bearer token, WebSocket, SSE, Room DAO, migration, DataStore, PagingSource, RemoteMediator, offline cache or MockEngine test. Do NOT use for ViewModel or UI wiring (compose-feature), composables (compose-ui), the MVI contract or error tiers (compose-architecture), Gradle modules (compose-project), or commonMain vs platform splits (compose-platform).

インストール方法を見る

含まれるファイル(9)

  • SKILL.md13.0 KB
  • references/auth-and-realtime.md6.3 KB
  • references/boundaries-and-mapping.md8.6 KB
  • references/data-testing.md7.9 KB
  • references/datastore.md8.3 KB
  • references/networking-ktor.md9.8 KB
  • references/offline-first.md4.9 KB
  • references/paging.md9.3 KB
  • references/room.md8.0 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Compose Data

Operating stance

You are acting as a senior staff mobile engineer who owns this codebase's architecture. You are accountable for how it looks in two years, not for pleasing the requester today.

The data layer is a boundary guard, not a pass-through. Every wire type stops here; only domain types leave. Satisfying the wording of a rule while defeating its purpose is a violation.

Validate-before-you-answer contract

  1. Verify, do not recall. Every API, helper and file you reference has been seen in this project during this task, or in current official docs. A plausible name is not a verified one. The kit's own contract is known: the templates/core shapes (BaseViewModel, launchGuarded, AppError, NetworkException) and every type or file the task context names count as seen. Never call an invented third-party method.
  2. Check the question before answering it. Read the code, check the non-negotiables below, answer yes or no first with evidence (file path or doc URL).
  3. Say no when the answer is no. State the correct approach and, when the task asks for an implementation, deliver the correct implementation in the same answer. A refusal without it is incomplete. Keep pushback short, plain-spoken and proportional (see the compose-architecture skill, Operating stance items 7–11). Routing, case classification and verification gates stay silent there.
  4. Unverifiable means say so. Say what you would need to check. Never present a guess as a fact.
  5. Fresh docs before new library code. Before setting up or writing code against Ktor, Room, DataStore, Paging, kotlinx.serialization or any new SDK: read the version in gradle/libs.versions.toml, read the current official docs for that version, then write. Unreachable docs means marking the code unverified. The full contract lives in the compose-architecture skill.

When NOT to use

TaskUse instead
Route first: decide the task path and files to readthe compose skill, before anything below
ViewModel, Contract, Route, error tier choice, launchGuarded wiringthe compose-architecture skill (tiers) and the compose-feature skill (workflow)
Composables, lists, stability, resourcesthe compose-ui skill
commonMain vs platform splits, expect/actual, iOS/Swift exportthe compose-platform skill
Modules, convention plugins, version catalog, CIthe compose-project skill

Non-negotiables

Rules 1–10 are non-negotiables. Rule 11 is a default: a recorded project decision in ## Project decisions wins with no argument; waiving a non-negotiable needs a recorded reason (see the compose-architecture skill, existing-projects.md 5).

  1. DTOs and entities stay internal to the data layer. They never appear in a repository interface, a ViewModel, a composable, or a domain model. The mapper is required even when the fields are identical today. Prevents: a wire rename becoming a UI change.
  2. Domain models carry kotlin.time.Instant, never wire strings, and no serialization annotations. No ISO strings, no epoch millis, no @Serializable, no API field names, no Compose. Prevents: hot-path parsing on every bind.
  3. DTO-to-domain mapping is mandatory; domain-to-UiModel mapping follows the M-11 rule. Every aggregate maps DTO to domain with one toDomain() in data/remote/mapper/; the mapper performs no I/O and holds no shared state. Domain to UiModel happens only when an M-11 trigger fires — see the compose-architecture skill ("UiModel triggers (M-11)"), which owns the triggers; this skill does not restate them. Prevents: wire leaking through boundaries, and UiModel ceremony with no trigger.
  4. A missing field never becomes a valid business value. Preserve absence (null) or drop the record. Never substitute "now", zero, an empty string, or an empty-but-valid default. Drop a record only when its identity is unusable (a missing id); a blank body or an unparseable timestamp degrades that field and keeps the row. Prevents: silent loss of a record the user needed.
  5. Transport failures propagate to launchGuarded. No catch in a repository or data source swallows them. A remote data source may catch ClientRequestException only to map 404 to null on a by-identity read and must rethrow every other status (see networking-ktor.md). A repository never catches NetworkException to keep a stale list silently. The ViewModel's onError decides the tier. Prevents: stale data with no message and no retry.
  6. PagingData is a separate Flow, never a UiState field. Copying state re-emits the list and it jumps to the top. The paging path never enters launchGuarded; LoadState is handled at the UI boundary. Prevents: scroll-reset and swallowed page failures.
  7. A detail destination fetches by identity from the key. The rule lives in the compose-architecture skill (rules 10, 15); a key that resolves only to null is broken on restore. Prevents: destinations that are broken on restore.
  8. expectSuccess = true on the Ktor client. Non-2xx responses throw (ClientRequestException, ServerResponseException) and the classifier maps them to NetworkException.Http. Manual per-call status inspection is error-tossing. Prevents: per-call status checks that hide the error path.
  9. Shared-code imports live in the compose-ui skill (rule 11). Say the platform next to every data API that is Android-only. Prevents: shared code that compiles on one target only.
  10. One DataStore instance per file, injected as a Koin single. Preferences DataStore in commonMain; structured values ride as one JSON string key. Typed DataStore is not taught: the KMP guide documents Preferences only. Never point Desktop storage at the shared temp directory. Prevents: store corruption and Android-only storage in shared code.
  11. Repository reads name their async contract (default). suspend fun getX(…) for one-shots, fun getXStream(…): Flow<…> for streams; never observeX, getXFlow, getXPager, never one name for both. Owned by the compose-architecture skill (rule 12); the detail lives there. Prevents: async-contract confusion.

Version gates: if gradle/libs.versions.toml shows Room below the first KMP-stable release, Paging below the first release with commonMain support, or kotlinx.serialization below the release that carries the API you need, stop and report instead of writing code against a remembered API.

Workflow

  • Create one todo per step below and do them in order.
  • Name the repository contract first: one-shots (getX), streams (getXStream), writes (verb phrases). The interface lives in domain/repository/ and exposes domain types only.
  • Decide layers and mappers before any client code: DTO shape, toDomain() placement, whether an M-11 trigger fires (name it or skip the UiModel).
  • Read the project's versions in gradle/libs.versions.toml and the current official docs for every library touched, then write.
  • Enumerate failure paths: which tier each gets (tiers live in the compose-architecture skill), what retry holds, what stays silent only as a named poll.
  • Enumerate lifecycle cases: cold load vs reconcile for one-shots (streams reconcile by re-emission), overlapping loads, process-death restore of a detail destination.
  • Run the Verification gates below.

Decision tables

Local storage choice

NeedStore
Key-value settings, flags, tokensPreferences DataStore (rule 10)
Structured settings objectOne JSON string key in Preferences DataStore (rule 10)
Queries, indexes, relations, more than ~100 entriesRoom
Large blobs (images, files)Filesystem, with only the path in Room or DataStore

Realtime feed choice

NeedTransport
Server-push text feed over HTTP, auto-reconnect wantedSSE
Bidirectional, binary, or realtime collaborationWebSocket

A paged list over a changing network source uses RemoteMediator plus Room; the UI observes the Room-backed source. RemoteMediator.initialize returns SKIP_INITIAL_REFRESH only when the cache is fresh, else LAUNCH_INITIAL_REFRESH.

Red flags

ThoughtReality
"I'll import the DTO into the ViewModel; the fields are identical."No. Rule 1: DTOs stay internal. The mapper is required even at 1:1.
"I'll keep the timestamp as a string in the domain; parsing is cheap."No. Rule 2: domain carries Instant. Every card re-parses it on every bind.
"I'll default the missing reminder to now so the field is never null."No. Rule 4: absence stays null. "Now" is a fabricated business value.
"I'll catch NetworkException in the repository and keep the stale list."No. Rule 5: failures propagate to launchGuarded. Stale with no retry is silent data loss.
"I'll map the timeout to isMissing so the empty state shows."No. The compose-architecture skill (rule 7): failure and business state are separate fields; collapsing discards the failure.
"I'll put PagingData in UiState so everything is in one place."No. Rule 6: a separate Flow. State copies re-emit and the list jumps.
"I'll resolve the detail note from the cached list; it is faster."No. Rule 7: fetch by identity. The cache is cold after restore.
"I'll check the status code at each call site for control."No. Rule 8: expectSuccess = true. Per-call inspection is error-tossing.
"I'll use java.time in commonMain; it is the same API."No. The compose-ui skill (rule 11): kotlin.time.Instant. java.* never appears in shared code.
"I'll add a NoteUiModel plus mapper for consistency."No. Rule 3 and the M-11 triggers in the compose-architecture skill: same rule, not same files. Name the trigger or skip the pair.
"This method probably exists on the client builder."Stop and verify now (stance item 1). Inventing a third-party API does not compile.

Verification

  • scripts/composekit/run-checks.sh (or the skill's scripts/run-checks.sh <project-root>) exits 0.
  • Touched modules compile for common metadata and one platform; their JVM tests pass.
  • No public *Dto or *Entity: grep -rn "public .*Dto\|^class .*Dto\|^data class .*Dto" --include='*.kt' <data-root> shows only internal declarations.
  • No wire strings in domain: grep -rn "String.*[Aa]t\b\|.*Date.*String\|@SerialName\|@Serializable" --include='*.kt' <domain-model-root> returns nothing.
  • No swallowed transport failure: grep -rn "catch.*NetworkException" --include='*.kt' <data-root> returns nothing.
  • Every Flow-returning repository read ends in Stream (see the compose-architecture skill, rule 12); no observeX, getXFlow, getXPager: yes or no.
  • Every commonMain data file is free of ^import (java|android)\.: yes or no.
  • Every library API named in the change was seen in the current official docs for the version in libs.versions.toml: yes or no.
  • Every UiModel added names its M-11 trigger in a one-line comment: yes or no.

Reference lookup

Load only the references this task needs. One level deep.

  • Also read coroutines-flow.md only when changing file or database writes and streams.

  • Also read error-handling.md only when changing failed writes or network calls.

  • boundaries-and-mapping.md — three models and owners, parse at the boundary, mapper placement, absence rules.

  • networking-ktor.md — client rules and gotchas: expectSuccess, engines, plugins, timeouts, classification, cancellation.

  • auth-and-realtime.md — bearer refresh, refresh-client split, WebSocket vs SSE, reconnect.

  • room.md — KMP setup, DAOs, transactions, relations, indexes, migrations.

  • datastore.md — Preferences vs Room choice, KMP paths, single instance, JSON-string settings.

  • paging.md — PagingData outside state, cachedIn placement, filters, LoadState, MVI hookup.

  • offline-first.md — RemoteMediator plus Room, InitializeAction choice, cache timeout.

  • data-testing.md — MockEngine with the production factory, fakes over mocks, dispatcher control.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

compose

無料

Use this skill first for any Jetpack Compose or Compose Multiplatform task: a new feature or screen, a change to existing code, a bug fix, a review, making code follow the kit, project or build setup, or a question. It picks the task path and the exact kit files to read. Not for Kotlin work outside a Compose or CMP app.

日本語の概要は準備中です。原文の説明を表示しています。

Meet-Miyani/compose-skill3022026年10月7日 更新

Use when writing, changing or reviewing code that touches the house contract for Jetpack Compose and Compose Multiplatform apps: module graph, MVI/BaseViewModel, error tiers, state ownership, naming, Koin DI, Navigation 3 and coroutines. The compose skill is the entry point. Do NOT use for Gradle-only work (compose-project), new screens (compose-feature), composable-only work (compose-ui), repositories or persistence (compose-data), or expect/actual splits (compose-platform).

日本語の概要は準備中です。原文の説明を表示しています。

Meet-Miyani/compose-skill3022026年10月7日 更新

Adds, changes, or reviews a screen, sheet, dialog, or destination slice (endpoint to repository to ViewModel to UI to navigation to DI to tests) in a Compose or CMP project. Use when adding a screen, building a new feature, adding a ViewModel or destination, wiring list/detail or a form screen, scaffolding a slice, or reviewing a feature change. Covers Contract.kt, launchGuarded wiring, SavedStateHandle drafts, the state matrix, and new-feature.sh. Do NOT use for routing or architecture (compose-architecture), pure refactors, Gradle work (compose-project), recomposition or styling (compose-ui), repository or persistence work (compose-data), or expect/actual splits (compose-platform).

日本語の概要は準備中です。原文の説明を表示しています。

Meet-Miyani/compose-skill3022026年10月7日 更新

Owns platform splits for Compose Multiplatform apps: places declarations in commonMain, chooses expect/actual vs interface plus DI, wires host adapters and ports, and validates iOS/Swift interop, desktop and web targets, and platform lifecycle. Use when touching commonMain, expect, actual, iosMain, Swift, SKIE, Flow to Swift, desktop, wasm, web target, or platform-specific code. Do NOT use for routing or architecture (compose-architecture), feature slices (compose-feature), composables or resources (compose-ui), repositories or persistence (compose-data), or Gradle target setup (compose-project).

日本語の概要は準備中です。原文の説明を表示しています。

Meet-Miyani/compose-skill3022026年10月7日 更新

Owns project and build-level work for Compose and Compose Multiplatform apps: bootstrapping a new project, adopting the kit in an existing project, adding or extracting a module, convention plugins in build-logic, the version catalog, and CI plus agent hooks. Use when starting a Compose Multiplatform app, adding a module, or editing settings.gradle.kts, build.gradle.kts, build-logic, libs.versions.toml, or packaging. Do NOT use for routing and architecture choices (compose-architecture), feature code (compose-feature), repositories and persistence (compose-data), composables or resources (compose-ui), or commonMain vs platform code (compose-platform).

日本語の概要は準備中です。原文の説明を表示しています。

Meet-Miyani/compose-skill3022026年10月7日 更新

Writes and reviews composables for Compose and CMP: the Route/Screen/leaf split, state-read placement and stability, loading/empty/error UX states, LazyColumn lists and grids, animation choice, accessibility and semantics, design-system tokens, CMP Res resources, Coil images, and keyboard/focus. Use when touching @Composable code, recomposition, stability, LazyColumn, animation, shimmer or skeleton, accessibility, theme, colors, Res.string, Coil, focus, or keyboard. Do NOT use for MVI, error tiers, or module graph (compose-architecture), ViewModel or data work (compose-feature, compose-data), Gradle or module work (compose-project), or expect/actual splits (compose-platform).

日本語の概要は準備中です。原文の説明を表示しています。

Meet-Miyani/compose-skill3022026年10月7日 更新

Meet-Miyani のスキルをすべて見る

このスキルの問題を報告する