3.1 KiB
Yattee Development Guide for AI Agents
Deployment Targets
iOS: 18.0+ | macOS: 15.0+ | tvOS: 18.0+
This project targets the latest OS versions only - use newest APIs freely without availability checks.
Build & Test Commands
Build: xcodebuild -scheme Yattee -configuration Debug
Test (all): xcodebuild test -scheme Yattee -destination 'platform=macOS'
Test (single): xcodebuild test -scheme Yattee -destination 'platform=macOS' -only-testing:YatteeTests/TestSuiteName/testMethodName
Lint: periphery scan (config: .periphery.yml)
Code Style
Language: Swift 5.0+ with strict concurrency (Swift 6 mode enabled)
UI: SwiftUI with @Observable macro for view models (not ObservableObject)
Concurrency: Use actor for services, @MainActor for UI-related code, async/await everywhere
Testing: Swift Testing framework (@Test, @Suite, #expect) - NOT XCTest
Imports & Organization
Import order: Foundation first, then SwiftUI, then @testable imports
File headers: Include // FileName.swift, // Yattee, and brief comment describing purpose
MARK comments: Use // MARK: - Section Name to organize code sections
Sendable: All models, errors, and actors must conform to Sendable
Types & Naming
Models: Immutable structs with Codable, Hashable, Sendable conformance
Services: Use actor for thread-safe services, final class for @Observable view models
Enums: Use associated values for typed errors (see APIError.swift)
Optionals: Prefer guard-let unwrapping; use if let for simple cases
Naming: camelCase for variables/functions, PascalCase for types, clear descriptive names
Error Handling
Errors: Define typed enum errors conforming to Error, LocalizedError, Equatable, Sendable
Async throws: All async network/IO operations should throw typed errors
Logging: Use LoggingService.shared for all logging (see HTTPClient.swift for patterns)
User feedback: Provide localized error descriptions via errorDescription
Testing & Debugging
Add logging/visual clues (borders, backgrounds) when debugging issues - then ask user for results
If first fix doesn't work: Add debug code before second attempt to understand the issue better
UI Testing (Ruby/RSpec with AXe CLI)
Run UI tests: ./bin/ui-test --skip-build --keep-simulator
Run single spec: SKIP_BUILD=1 KEEP_SIMULATOR=1 bundle exec rspec spec/ui/smoke/search_spec.rb
Accessibility labels vs identifiers: On iOS 26+, .accessibilityIdentifier() doesn't work reliably on Group, ScrollView, and some container views (AXUniqueId comes back empty). Use .accessibilityLabel() instead, which maps to AXLabel and can be detected via AXe's text_visible?() method.
iOS 26 TabView search: The search field is integrated into the bottom tab bar with Tab(role: .search). Typing \n doesn't submit - use hardware key press via press_return (AXe key 40).
ScrollView children: Video rows inside LazyVStack/ScrollView aren't exposed in the accessibility tree. Use coordinate-based tapping instead.