User Story
As a mobile-app engineer, I want the core Conversation / Session / Message data classes defined so that subsequent tickets (repository interface, fake repository, UI state) have a typed schema to build against.
Context
Foundational Phase 1 scaffolding. Mirrors the schema that pyrycode CLI's conversations.json (Phase 3) and Discord-side (Phase 2) will share — same entity shape across all consumers. The data/ package does not yet exist in the repo; this ticket creates it.
Per repo CLAUDE.md (Don't section): the data layer must stay portable (Compose Multiplatform is a walk-back trigger). See Technical Notes.
Spec
// app/src/main/java/de/pyryco/mobile/data/model/
data class Conversation(
val id: String,
val name: String?, // null for discussions; user-set for channels
val cwd: String,
val currentSessionId: String,
val sessionHistory: List<String>,
val isPromoted: Boolean, // false = discussion, true = channel
val lastUsedAt: Instant,
)
data class Session(
val id: String,
val conversationId: String,
val claudeSessionUuid: String,
val startedAt: Instant,
val endedAt: Instant?,
)
data class Message(
val id: String,
val sessionId: String,
val role: Role,
val content: String,
val timestamp: Instant,
val isStreaming: Boolean,
)
enum class Role { User, Assistant, Tool }
Acceptance Criteria
Technical Notes
- Use
kotlinx.datetime.Instant, not java.time.Instant — CLAUDE.md requires the data layer to remain portable for a potential Compose Multiplatform walk-back. The version catalog (gradle/libs.versions.toml) does not yet declare kotlinx-datetime; the architect should add it.
- File layout (one-class-per-file vs. co-locating
Role in Message.kt) is an architect call — the AC fixes the package and the type shapes, not the file count.
Out of Scope
ConversationRepository interface and FakeConversationRepository (next ticket).
- Persistence (DataStore / Room).
- Serialization for the Phase 4 wire protocol — these types stay annotation-free for now.
Size Estimate
XS — ~40 lines of production code (4 small declarations in one package), plus paired unit tests. No cross-package coordination; no consumers wired in this ticket.
User Story
As a mobile-app engineer, I want the core
Conversation/Session/Messagedata classes defined so that subsequent tickets (repository interface, fake repository, UI state) have a typed schema to build against.Context
Foundational Phase 1 scaffolding. Mirrors the schema that pyrycode CLI's
conversations.json(Phase 3) and Discord-side (Phase 2) will share — same entity shape across all consumers. Thedata/package does not yet exist in the repo; this ticket creates it.Per repo CLAUDE.md (
Don'tsection): the data layer must stay portable (Compose Multiplatform is a walk-back trigger). See Technical Notes.Spec
Acceptance Criteria
Conversation,Session,Message, andRoleare declared in packagede.pyryco.mobile.data.modelwith the exact field names, types, and nullability shown in the Spec.data classtypes asserts that two instances with identical fields areequals, thathashCodematches, and thatcopy()produces a new instance with the requested field overridden and all others preserved.Rolehas exactly the valuesUser,Assistant,Tool(e.g. viaRole.values().toList())../gradlew assembleDebugpasses../gradlew testpasses.Technical Notes
kotlinx.datetime.Instant, notjava.time.Instant— CLAUDE.md requires the data layer to remain portable for a potential Compose Multiplatform walk-back. The version catalog (gradle/libs.versions.toml) does not yet declarekotlinx-datetime; the architect should add it.RoleinMessage.kt) is an architect call — the AC fixes the package and the type shapes, not the file count.Out of Scope
ConversationRepositoryinterface andFakeConversationRepository(next ticket).Size Estimate
XS — ~40 lines of production code (4 small declarations in one package), plus paired unit tests. No cross-package coordination; no consumers wired in this ticket.