Parent
#39 — PRD: AI Radio — Host-driven Channel experience with chat timeline
What to build
Define the core cross-cutting data shapes that all Radio context modules depend on. These live in @flow/shared (or a new @flow/radio package) and must be stable before other slices start.
The canonical shapes from the PRD:
type SegmentKind = 'track' | 'interlude'
interface TrackSegment {
kind: 'track'
track: Track
}
interface InterlSegment {
kind: 'interlude'
script: string // pushed to chat at playback start
audioUrl: string // pre-synthesised TTS URL
}
type Segment = TrackSegment | InterlSegment
type Programme = Segment[]
type ChatMessage =
| { type: 'interlude'; script: string; timestamp: number }
| { type: 'now-playing'; track: Track; timestamp: number }
| { type: 'user-turn'; text: string; timestamp: number }
| { type: 'host-turn'; text: string; timestamp: number }
interface ChannelStyle {
genreHints?: string[]
energyLevel?: 'low' | 'medium' | 'high'
tempoRange?: { min: number; max: number }
moodTags?: string[]
}
interface Channel {
id: string
name: string
descriptor: string
style: ChannelStyle
}
type InterventionKind = 'track-request' | 'mood-change' | 'free-instruction'
interface Intervention {
kind: InterventionKind
text: string
}
No runtime logic — types and interfaces only. Export everything from a single entry point.
Acceptance criteria
Blocked by
None — can start immediately
Parent
#39 — PRD: AI Radio — Host-driven Channel experience with chat timeline
What to build
Define the core cross-cutting data shapes that all Radio context modules depend on. These live in
@flow/shared(or a new@flow/radiopackage) and must be stable before other slices start.The canonical shapes from the PRD:
No runtime logic — types and interfaces only. Export everything from a single entry point.
Acceptance criteria
Segment,Programme,TrackSegment,InterlSegmenttypes are exported and usable from other packagesChatMessageunion type is exportedChannel,ChannelStyletypes are exportedInterventionandInterventionKindtypes are exportedBlocked by
None — can start immediately