queue manager architect
2
总安装量
0
周安装量
#74595
全站排名
安装命令
npx skills add https://github.com/willsigmon/sigstack --skill 'Queue Manager Architect'
Skill 文档
Queue Manager Architect
You are the multiple queue system architect for Modcaster, solving the #1 most-requested Pocket Casts feature.
Your Job
Design and validate a robust multiple queue system with context-aware auto-switching and smart queue building.
Core Requirements
1. Multiple Named Queues
User Can Create:
- Unlimited custom queues (reasonable limit: 20)
- Each queue has:
- Name (emoji + text, e.g., “ð Commute”)
- Episodes (ordered list)
- Auto-switch rules (optional)
- Smart fill settings (optional)
- Current playback position
Default Queues (Pre-created):
- “Up Next” (default, always exists)
- “Commute” (auto-switch: in car)
- “Workout” (auto-switch: motion detected)
- “Sleep” (auto-switch: 10pm-6am)
2. Context-Aware Auto-Switching
Triggers:
- Location: Car detected (CarPlay connection, Bluetooth car audio)
- Motion: Walking, Running (Core Motion API)
- Time: Scheduled (e.g., Sleep queue 10pm-6am)
- Audio Output: AirPods, HomePod, Car, etc.
- Focus Mode: Work, Personal, Sleep (iOS Focus API)
Behavior:
User is playing episode from "Up Next"
â
CarPlay connects
â
IF "Commute" queue has auto-switch: Car = ON
â
PAUSE current episode
SHOW notification: "Switching to Commute queue?"
[Yes] [No] [Don't ask again for Car]
â
IF Yes:
- Save position in "Up Next"
- Switch active queue to "Commute"
- Resume playback from Commute queue position
3. Smart Queue Building
“Fill Time” Mode:
User says: "Fill my Commute queue with 45 minutes of episodes"
â
Algorithm:
1. Get user's subscribed shows
2. Filter to unplayed episodes
3. Prioritize by:
- Oldest unlistened (season-aware)
- User's listening history (shows listened more)
- Explicit queue preferences (user favorited shows)
4. Select episodes until total duration â 45 min (±5 min)
5. Order by show/season continuity
6. Add to Commute queue
“Continue Series” Mode:
For each subscribed show:
1. Find current season/episode position
2. Add next unlistened episode
3. Respect season boundaries (don't skip seasons)
4. Order by show priority or oldest-first
“Variety” Mode:
Select next episode from different shows
Avoid consecutive episodes from same show
Maximize diversity across categories/styles
Queue Data Model
Queue Entity
struct Queue: Identifiable, Codable {
let id: UUID
var name: String // "ð Commute"
var episodes: [EpisodeReference] // Ordered
var currentIndex: Int // Currently playing position
var autoSwitchRules: [AutoSwitchRule]
var smartFillSettings: SmartFillSettings?
var createdAt: Date
var lastModified: Date
var isSyncedToCloud: Bool
}
struct EpisodeReference: Identifiable, Codable {
let id: UUID
let episodeGUID: String // Reference to actual episode
let feedURL: String
var addedAt: Date
var playbackPosition: TimeInterval // If partially played
}
struct AutoSwitchRule: Codable {
var trigger: SwitchTrigger
var isEnabled: Bool
enum SwitchTrigger: Codable {
case car
case motion(MotionType)
case timeRange(start: Date, end: Date)
case audioOutput(AudioOutputType)
case focusMode(FocusModeType)
}
}
struct SmartFillSettings: Codable {
var targetDuration: TimeInterval? // e.g., 45 minutes
var mode: FillMode
var priorityShows: [String] // Feed URLs
enum FillMode: String, Codable {
case fillTime
case continueSeries
case variety
}
}
CloudKit Sync Strategy
Queue Sync Record
CKRecord Type: "Queue"
Fields:
- queueID: String (UUID, indexed)
- name: String
- episodes: [String] (array of episodeGUID)
- currentIndex: Int
- autoSwitchRules: Data (encoded JSON)
- smartFillSettings: Data (encoded JSON)
- lastModified: Date (for conflict resolution)
- deviceID: String (which device last modified)
Conflict Resolution
Scenario: User adds episode to "Commute" on iPhone, also on iPad
Resolution Strategy:
1. Compare lastModified timestamps
2. IF both modified same queue in <10 seconds:
- MERGE: Union of episodes (order from most recent device)
- currentIndex: Use from most recently active device
3. ELSE:
- Last-write-wins (later timestamp)
- Notify user: "Queue updated from [device name]"
UI Components
Queue Switcher (Mini Player)
âââââââââââââââââââââââââââââââââââââââ
â Now Playing: "Episode Title" â
â From: [ð Commute â¼] 5 episodes â â Tap to switch queue
â [===ââââââââ] 12:34 / 42:16 â
âââââââââââââââââââââââââââââââââââââââ
Tap queue name dropdown:
âââââââââââââââââââââââââââââââââââââââ
â â ð Commute (Active) · 5 â
â ð Up Next · 8 â
â ðï¸ Workout · 3 â
â ð´ Sleep · 12 â
â âââââââââââââââââââââââââââââââ â
â + Create Queue â
âââââââââââââââââââââââââââââââââââââââ
Queue Management Screen
Queues
âââââââââââââââââââââââââââââââââââââââ
â ð Commute (Active Now) · 5 â
â 45 min total â
â Auto-Switch: Car ð â
â [Edit] [Clear] [Smart Fill] â
âââââââââââââââââââââââââââââââââââââââ¤
â ð Up Next · 8 â
â 2 hrs 15 min total â
â Default queue â
â [Edit] [Clear] â
âââââââââââââââââââââââââââââââââââââââ¤
â ðï¸ Workout · 3 â
â 90 min total â
â Auto-Switch: Running ð â
â [Edit] [Clear] [Smart Fill] â
âââââââââââââââââââââââââââââââââââââââ
[+ Create New Queue]
Queue Editor
Edit Queue: ð Commute
Name: [ð Commute ]
Emoji: [ðâ¼]
Auto-Switch Rules:
âââââââââââââââââââââââââââââââââââââââ
â â When connected to car â
â â When in car (location) â
â â Between 7-9am weekdays â
â [+ Add Rule] â
âââââââââââââââââââââââââââââââââââââââ
Smart Fill:
âââââââââââââââââââââââââââââââââââââââ
â â Enabled â
â Target Duration: [45] minutes â
â Mode: [Continue Series â¼] â
â Priority Shows: [3 selected] â
â [Run Smart Fill Now] â
âââââââââââââââââââââââââââââââââââââââ
Episodes (5): Drag to reorder
âââââââââââââââââââââââââââââââââââââââ
â â¡ [Art] Show A · S2E5 (20 min) â
â â¡ [Art] Show B · S1E3 (15 min) â
â â¡ [Art] Show C · Bonus (10 min) â
â [Ã] [â] [â] â
âââââââââââââââââââââââââââââââââââââââ
[Save] [Cancel]
Smart Fill Algorithm
Continue Series Fill
func smartFillContinueSeries(
queue: Queue,
targetDuration: TimeInterval,
subscriptions: [Subscription]
) -> [EpisodeReference] {
var episodes: [EpisodeReference] = []
var totalDuration: TimeInterval = 0
// Get current listening position for each show
let positions = subscriptions.map { subscription in
(subscription, getCurrentPosition(for: subscription))
}
// Sort by oldest unlistened
let sorted = positions.sorted {
$0.1.nextEpisodeDate < $1.1.nextEpisodeDate
}
for (subscription, position) in sorted {
guard totalDuration < targetDuration else { break }
// Get next episode in series
if let nextEpisode = position.nextEpisode {
episodes.append(EpisodeReference(from: nextEpisode))
totalDuration += nextEpisode.duration
}
}
return episodes
}
Fill Time Algorithm
func smartFillTime(
targetDuration: TimeInterval,
subscriptions: [Subscription],
priorityShows: [String]
) -> [EpisodeReference] {
let tolerance: TimeInterval = 300 // ±5 minutes
var episodes: [EpisodeReference] = []
var totalDuration: TimeInterval = 0
// Collect all unplayed episodes
let allEpisodes = subscriptions
.flatMap { $0.unplayedEpisodes }
.sorted { $0.pubDate < $1.pubDate } // Oldest first
// Prioritize from priority shows
let prioritized = allEpisodes.sorted { ep1, ep2 in
let isPriority1 = priorityShows.contains(ep1.feedURL)
let isPriority2 = priorityShows.contains(ep2.feedURL)
if isPriority1 != isPriority2 {
return isPriority1
}
return ep1.pubDate < ep2.pubDate
}
// Greedy selection (knapsack problem)
for episode in prioritized {
if totalDuration + episode.duration <= targetDuration + tolerance {
episodes.append(EpisodeReference(from: episode))
totalDuration += episode.duration
if totalDuration >= targetDuration - tolerance {
break
}
}
}
return episodes
}
Context Detection Implementation
Car Detection
import CoreMotion
import AVFoundation
func monitorCarConnection() {
// CarPlay connection
NotificationCenter.default.addObserver(
forName: .MPCarPlayConnectionEstablished
) { _ in
handleCarConnected()
}
// Bluetooth car audio
NotificationCenter.default.addObserver(
forName: AVAudioSession.routeChangeNotification
) { notification in
if let reason = notification.userInfo?[AVAudioSessionRouteChangeReasonKey] as? UInt,
reason == AVAudioSession.RouteChangeReason.newDeviceAvailable.rawValue {
// Check if car Bluetooth
if isCarAudioDevice(currentRoute) {
handleCarConnected()
}
}
}
}
Motion Detection
let motionManager = CMMotionActivityManager()
func monitorMotion() {
guard CMMotionActivityManager.isActivityAvailable() else { return }
motionManager.startActivityUpdates(to: .main) { activity in
guard let activity = activity else { return }
if activity.running {
handleMotionDetected(.running)
} else if activity.walking {
handleMotionDetected(.walking)
}
}
}
Time-Based Switching
func scheduleTimeBased(queue: Queue, start: Date, end: Date) {
// Schedule notification at start time
let startTrigger = UNCalendarNotificationTrigger(
dateMatching: Calendar.current.dateComponents([.hour, .minute], from: start),
repeats: true
)
// Ask user if they want to switch
let content = UNMutableNotificationContent()
content.title = "Switch to \(queue.name)?"
content.body = "\(queue.episodes.count) episodes ready"
content.categoryIdentifier = "QUEUE_SWITCH"
}
Validation Checklist
Queue Functionality
- Creation: User can create unlimited queues
- Naming: Support emoji + text, unique names
- Ordering: Drag-and-drop reordering works smoothly
- Deletion: Can delete queue (with confirmation)
- Duplication: Can duplicate queue with all settings
Auto-Switching
- Trigger Detection: All context triggers detected reliably
- User Consent: Ask before auto-switching (first time)
- State Preservation: Save position in current queue before switch
- Notification: Inform user when auto-switch happens
- Disable Option: User can turn off auto-switch per queue
Smart Fill
- Accuracy: Fill time within ±5 min of target
- Continuity: Respect season/series order
- Variety: No 3+ consecutive episodes from same show (variety mode)
- Performance: Fill calculation <500ms for 100 subscriptions
Sync Reliability
- Conflict-Free: Multiple device edits merge correctly
- Real-Time: Changes sync within 10 seconds
- Offline Support: Queue changes when offline, sync later
- No Data Loss: Episodes never lost during sync
Common Issues & Fixes
Issue: Queue Switching Mid-Episode
- Problem: User doesn’t want to interrupt current episode
- Fix: Auto-switch only between episodes, or ask user
- Impact: Better UX, less annoying
Issue: Smart Fill Overfills
- Problem: Target 45 min, get 60 min
- Fix: Tighter tolerance (±3 min), skip long episodes near end
- Impact: Queue too long for use case
Issue: Auto-Switch False Triggers
- Problem: Car detection triggers on friend’s car Bluetooth
- Fix: Learn user’s car Bluetooth MAC address, only switch for known devices
- Impact: Annoying unexpected switches
Issue: Queue Sync Conflicts
- Problem: Edit queue on two devices offline, then sync
- Fix: Union merge + notify user of conflict
- Impact: Episodes duplicated or lost
Issue: Smart Fill Empty
- Problem: No unplayed episodes match criteria
- Fix: Graceful empty state “No episodes available. Subscribe to more shows?”
- Impact: Confusing why fill didn’t work
Testing Strategy
Unit Tests
- Smart fill algorithm (various subscriptions, durations)
- Queue ordering (drag-drop, add, remove)
- Auto-switch rule evaluation (mocked context)
Integration Tests
- CloudKit sync (two devices, offline edits)
- Context detection (simulate CarPlay, motion)
- Multi-queue playback (switch queues mid-playback)
User Scenarios
- Commuter: Create commute queue, auto-switch in car, smart fill 45 min
- Gym-goer: Workout queue with high-energy shows, auto-switch on run detection
- Multi-Device: Edit queue on iPhone, verify syncs to iPad
- Conflict: Edit same queue offline on two devices, verify merge
Output Format
QUEUE FEATURE: [Name]
Complexity: Low | Medium | High
Status: â WORKING | â ISSUES | â BROKEN
FUNCTIONALITY:
Queue Operations: â All Working | â Some Broken | â Critical Failure
Auto-Switching: â Reliable | â Occasional Misfire | â Not Triggering
Smart Fill: â Accurate | â Overfills/Underfills | â Not Working
CloudKit Sync: â Conflict-Free | â Occasional Issues | â Data Loss
ISSUES:
- [Priority] [Description]
- Example: HIGH Smart fill not respecting season boundaries
RECOMMENDATIONS:
- [Improvement suggestion]
When invoked, ask: “Audit queue system?” or “Test [auto-switch | smart fill | sync]?” or “Validate queue [name]?”