Files
hiha-arvio/spec.md
Ismo Vuorinen 7639eb1cfc docs: document code coverage limitation and remove test counts
Coverage Documentation:
- Remove 95% coverage threshold enforcement from test workflow
- Change to informational coverage display only
- Document in spec.md why coverage can't be enforced on Linux runners
- Explain that full coverage requires macOS runners with all target frameworks

README Maintenance:
- Remove hardcoded test counts (189 tests) that become outdated quickly
- Change to generic "comprehensive test suite" description
- Remove specific test count breakdowns by layer
2025-11-19 01:02:55 +02:00

21 KiB

Hiha-Arvio Application Specification

Version: 1.0 Date: 2025-11-18 Status: Draft

1. Introduction

This document specifies the requirements for Hiha-Arvio (Sleeve Estimate), a cross-platform mobile and web application that generates semi-random time estimates based on physical shake input.

1.1 Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

1.2 Scope

This specification covers:

  • Functional requirements for shake detection and estimate generation
  • Data persistence and history management
  • User interface requirements
  • Platform-specific implementations
  • Testing and quality requirements

2. Platform Requirements

2.1 Technology Stack

The application MUST be implemented using the following technologies:

  • Framework: .NET 8 Multi-platform App UI (MAUI)
  • Language: C# 12 with nullable reference types enabled
  • Minimum iOS version: iOS 15.0
  • Minimum macOS version: macOS 12.0 (Monterey)
  • Web target: Blazor WebAssembly

2.2 Supported Platforms

The application MUST support the following platforms in order of priority:

  1. iOS (PRIMARY) - Native iOS application
  2. Web (SECONDARY) - Browser-based via Blazor WebAssembly
  3. macOS (TERTIARY) - Native macOS application

The application MAY support additional platforms (Android, Windows) in future releases.

3. Functional Requirements

3.1 Shake Detection

3.1.1 Mobile Platforms (iOS)

The application MUST:

  • Monitor device accelerometer data using Microsoft.Maui.Devices.Sensors.Accelerometer
  • Calculate shake magnitude as sqrt(x² + y² + z²) for each accelerometer reading
  • Detect shake start when magnitude exceeds 2.5g threshold
  • Track peak magnitude during entire shake session
  • Detect shake end when magnitude remains below threshold for 500 milliseconds continuous
  • Normalize shake intensity to range [0.0, 1.0] based on peak magnitude relative to maximum observed

The application SHOULD:

  • Request motion sensor permissions on first launch
  • Pause accelerometer monitoring when app is backgrounded
  • Provide haptic feedback when shake is detected

3.1.2 Desktop Platforms (Web, macOS)

The application MUST:

  • Monitor mouse movement delta (Δx, Δy) over a 200-millisecond sliding window
  • Calculate mouse velocity as sqrt(Δx² + Δy²) / Δt
  • Detect "shake" when velocity exceeds platform-appropriate threshold
  • Normalize shake intensity based on velocity relative to maximum observed

The application SHOULD:

  • Display visual boundaries for the shake detection zone
  • Provide alternative keyboard shortcut (Cmd+Shift+S on macOS) for manual shake trigger

The application MAY:

  • Support Device Orientation API for mobile web browsers as alternative input method

3.2 Estimate Generation

3.2.1 Estimation Modes

The application MUST support three estimation modes:

  1. Work Mode - Project and work-related time estimates
  2. Generic Mode - General-purpose duration estimates
  3. Humorous Mode - Absurd and exaggerated estimates (easter egg)

The application MUST:

  • Provide user interface toggle between Work Mode and Generic Mode
  • Keep Humorous Mode hidden (no UI control)
  • Activate Humorous Mode automatically when shake duration exceeds 15 seconds
  • Persist user's mode selection (Work/Generic) across app sessions

3.2.2 Estimate Pools

The application MUST maintain the following estimate pools:

Work Mode Estimates:

  • Gentle shake pool: "2 hours", "4 hours", "1 day", "2 days", "3 days", "5 days", "1 week"
  • Hard shake pool: "15 minutes", "30 minutes", "1 hour", "2 hours", "1 day", "3 days", "1 week", "2 weeks", "1 month", "3 months", "6 months", "1 year"

Generic Mode Estimates:

  • Gentle shake pool: "1 minute", "5 minutes", "10 minutes", "15 minutes", "30 minutes", "1 hour", "2 hours", "3 hours"
  • Hard shake pool: "30 seconds", "1 minute", "5 minutes", "15 minutes", "30 minutes", "1 hour", "2 hours", "6 hours", "12 hours", "1 day", "3 days", "1 week", "2 weeks", "1 month"

Humorous Mode Estimates:

  • "5 minutes", "tomorrow", "eventually", "next quarter", "when hell freezes over", "3 lifetimes", "Tuesday", "never", "your retirement"

The application MAY expand these pools in future versions.

3.2.3 Estimate Selection Algorithm

The application MUST implement the following algorithm:

FUNCTION GenerateEstimate(intensity: double, duration: TimeSpan, mode: EstimateMode):
  1. IF duration > 15 seconds THEN
       SET mode = Humorous

  2. SELECT estimate_pool based on current mode

  3. CALCULATE range_bounds:
     IF intensity < 0.3 THEN
       range = first 20% of estimate_pool
     ELSE IF intensity < 0.7 THEN
       range = first 50% of estimate_pool
     ELSE
       range = entire estimate_pool

  4. SELECT random estimate from range using cryptographically secure RNG

  5. RETURN EstimateResult with:
       - Selected estimate text
       - Current timestamp
       - Active mode
       - Normalized intensity
       - Shake duration

The application MUST use cryptographically secure random number generation for estimate selection to ensure unpredictability.

3.3 History Management

3.3.1 Storage Requirements

The application MUST:

  • Persist the last 10 estimate results (REQUIRED minimum)
  • Store each estimate with complete metadata: timestamp, estimate text, mode, intensity, duration
  • Save estimates immediately after generation
  • Load history on application startup
  • Automatically prune oldest estimates when count exceeds maximum (10)

The application SHOULD:

  • Store history in SQLite database using sqlite-net-pcl library
  • Create timestamp index for efficient queries
  • Perform all database operations asynchronously

The application MAY:

  • Allow users to configure maximum history size (future enhancement)
  • Export history to CSV or JSON format (future enhancement)

3.3.2 Settings Persistence

The application MUST:

  • Persist user's selected mode (Work/Generic) across sessions
  • Load saved settings on application startup
  • Use platform-native Preferences API for settings storage

3.4 User Interface

3.4.1 Main Page

The application MUST display:

  • Large shake detection zone occupying at least 80% of screen height
  • Current estimate result with large, readable typography
  • Mode toggle control labeled "Work Estimates ⟷ Generic Time"
  • Navigation icons for Settings and History pages

The application MUST provide visual feedback:

  • Subtle pulsing animation (scale 1.0 → 1.05 → 1.0) during active shake
  • Smooth fade-in animation for estimate reveal (200-300ms duration)
  • No visual timer or indicator for 15-second easter egg

The application MUST NOT:

  • Display loading spinners or progress bars during shake
  • Show shake intensity meter or real-time feedback
  • Reveal the existence of Humorous Mode in UI

3.4.2 History Page

The application MUST display for each history entry:

  • Estimate text (large, bold typography)
  • Relative timestamp (e.g., "2 minutes ago", "1 hour ago")
  • Mode badge indicating Work/Generic/Humorous with color coding
  • Visual intensity indicator (e.g., filled dots representing intensity level)

The application MUST:

  • Display estimates in reverse chronological order (newest first)
  • Show empty state message when history is empty: "No estimates yet. Give it a shake!"
  • Support pull-to-refresh gesture for reloading

The application SHOULD:

  • Limit visible history to 10 most recent entries
  • Provide smooth scrolling for list navigation

3.4.3 Settings Page

The application MUST provide:

  • Mode toggle control (mirroring Main Page toggle)
  • Application version information
  • About section with attribution

The application MAY provide:

  • Sensitivity adjustment controls (future enhancement)
  • Maximum history size configuration (future enhancement)
  • Reset/clear history button (future enhancement)

3.4.4 Accessibility

The application MUST:

  • Support full keyboard navigation on desktop platforms
  • Provide VoiceOver/TalkBack descriptions for all interactive elements
  • Maintain minimum touch target size of 44x44 points
  • Meet WCAG 2.1 Level AA contrast ratio requirements (4.5:1 for normal text)

The application SHOULD:

  • Support Dynamic Type on iOS
  • Respect user's reduced motion preferences
  • Provide alternative text for all icons

4. Architecture Requirements

4.1 Design Pattern

The application MUST implement Model-View-ViewModel (MVVM) pattern with strict separation:

  • Models MUST be plain data objects with no business logic
  • ViewModels MUST contain all presentation logic and be fully testable without UI
  • Views MUST be thin, containing only data binding and minimal presentation code
  • Services MUST encapsulate all business logic and infrastructure concerns

4.2 Dependency Injection

The application MUST:

  • Use dependency injection for all service dependencies
  • Register all services in MauiProgram.cs startup configuration
  • Define service interfaces in Services/Interfaces/ directory
  • Inject dependencies via constructor injection

The application MUST NOT:

  • Use service locator pattern
  • Create service instances with new keyword in ViewModels
  • Use static dependencies

4.3 Data Models

The application MUST define the following models:

public class EstimateResult
{
    public Guid Id { get; set; }                      // REQUIRED
    public DateTimeOffset Timestamp { get; set; }     // REQUIRED
    public string EstimateText { get; set; }          // REQUIRED
    public EstimateMode Mode { get; set; }            // REQUIRED
    public double ShakeIntensity { get; set; }        // REQUIRED, range [0.0, 1.0]
    public TimeSpan ShakeDuration { get; set; }       // REQUIRED
}

public enum EstimateMode
{
    Work,      // REQUIRED
    Generic,   // REQUIRED
    Humorous   // REQUIRED
}

public class ShakeData
{
    public double Intensity { get; set; }    // REQUIRED, range [0.0, 1.0]
    public TimeSpan Duration { get; set; }   // REQUIRED
    public bool IsShaking { get; set; }      // REQUIRED
}

public class AppSettings
{
    public EstimateMode SelectedMode { get; set; }  // REQUIRED, default: Work
    public int MaxHistorySize { get; set; }         // REQUIRED, default: 10
}

4.4 Service Interfaces

The application MUST implement the following service contracts:

public interface IAccelerometerService
{
    IObservable<AccelerometerData> DataStream { get; }  // REQUIRED
    void Start();                                        // REQUIRED
    void Stop();                                         // REQUIRED
}

public interface IShakeDetectionService
{
    IObservable<ShakeData> ShakeStream { get; }  // REQUIRED
    void StartMonitoring();                       // REQUIRED
    void StopMonitoring();                        // REQUIRED
}

public interface IEstimateService
{
    EstimateResult GenerateEstimate(              // REQUIRED
        double intensity,
        TimeSpan duration,
        EstimateMode mode
    );
}

public interface IStorageService
{
    Task SaveSettings(AppSettings settings);                    // REQUIRED
    Task<AppSettings> LoadSettings();                           // REQUIRED
    Task SaveEstimate(EstimateResult result);                   // REQUIRED
    Task<List<EstimateResult>> GetHistory(int count = 10);     // REQUIRED
    Task ClearHistory();                                        // REQUIRED
}

5. Testing Requirements

5.1 Code Coverage

The application MUST achieve minimum 95% code coverage across all projects when measured with all target frameworks.

The application MUST measure coverage using:

  • Coverlet for .NET code coverage collection
  • ReportGenerator for coverage report generation

Multi-Target Framework Limitation:

Due to the multi-target framework architecture (net8.0, net8.0-ios, net8.0-maccatalyst), coverage enforcement has the following constraints:

  • Ubuntu CI runners: Can only measure coverage for net8.0 target (~10-20% of codebase)

    • Platform-specific code (iOS/macOS) is excluded from net8.0 builds
    • Coverage threshold enforcement is disabled on Linux runners
    • Coverage reports are generated for informational purposes only
  • macOS CI runners: Can measure full coverage across all target frameworks

    • However, this is significantly more expensive ($0.08/min vs $0.008/min)
    • Full coverage measurement should be performed locally during development

The application SHOULD provide coverage reports in CI but MUST NOT enforce thresholds on partial builds.

5.2 Unit Testing

The application MUST provide unit tests for:

  • All service implementations (EstimateService, ShakeDetectionService, StorageService)
  • All ViewModels (MainViewModel, SettingsViewModel)
  • All public methods in models (if containing logic)
  • All estimate selection algorithm branches

The application MUST use:

  • xUnit as testing framework
  • NSubstitute for mocking dependencies
  • FluentAssertions for assertion syntax

The application MUST:

  • Mock all external dependencies (file system, database, sensors)
  • Use test data builders for complex object creation
  • Seed random number generators for deterministic tests
  • Test all edge cases (null inputs, boundary values, invalid states)

5.3 Integration Testing

The application MUST provide integration tests for:

  • Complete data flow from shake detection through estimate generation to storage
  • ViewModel and multiple service interactions
  • Database operations with actual SQLite instance

The application SHOULD:

  • Use in-memory SQLite for faster test execution
  • Parallelize integration tests where possible

5.4 UI Testing

The application SHOULD provide UI automation tests for:

  • Critical user path: Shake → View estimate → Check history
  • Mode toggle functionality
  • History page display and navigation

The application MAY use Appium WebDriver for cross-platform UI testing.

6. Quality Requirements

6.1 Code Quality

The application MUST:

  • Enable nullable reference types across all projects
  • Treat all compiler warnings as errors
  • Pass all enabled code analysis rules (StyleCop, built-in analyzers)
  • Follow EditorConfig formatting rules

The application MUST NOT:

  • Suppress warnings without documented justification
  • Disable code analysis rules without review
  • Commit code with compiler errors

6.2 Performance

The application MUST:

  • Respond to shake detection within 100 milliseconds
  • Display estimate result within 200 milliseconds after shake stop
  • Load history page within 500 milliseconds
  • Complete all database operations asynchronously

The application SHOULD:

  • Minimize memory allocations during shake detection loop
  • Cache estimate pools in memory
  • Use lazy loading for history page

6.3 Error Handling

The application MUST:

  • Handle sensor unavailability gracefully (show user-friendly message)
  • Catch and log all exceptions in services
  • Prevent crash from any single component failure
  • Validate all user inputs

The application SHOULD:

  • Implement retry logic for transient database errors
  • Log errors to platform-specific logging systems

7. Platform-Specific Requirements

7.1 iOS Requirements

The application MUST:

  • Target iOS 15.0 or higher
  • Request motion sensor permissions via Info.plist NSMotionUsageDescription
  • Pause sensor monitoring when app enters background
  • Support iOS dark mode
  • Follow iOS Human Interface Guidelines

The application SHOULD:

  • Provide haptic feedback on shake detection
  • Support iPad multitasking and split view

7.2 Web Requirements

The application MUST:

  • Support modern browsers: Chrome 90+, Safari 14+, Firefox 88+, Edge 90+
  • Implement responsive design for mobile and desktop viewports
  • Function without server-side dependencies (static hosting)

The application SHOULD:

  • Provide Progressive Web App (PWA) manifest for home screen install
  • Cache application assets for offline functionality
  • Support touch gestures on mobile browsers

The application MAY:

  • Use Device Orientation API for mobile browser shake detection

7.3 macOS Requirements

The application MUST:

  • Target macOS 12.0 (Monterey) or higher
  • Follow macOS Human Interface Guidelines
  • Support native window chrome and menu bar
  • Implement keyboard shortcut Cmd+Shift+S for shake trigger

The application SHOULD:

  • Support macOS dark mode and accent colors
  • Integrate with macOS accessibility features

8. Security Requirements

The application MUST:

  • Use cryptographically secure random number generation (System.Security.Cryptography.RandomNumberGenerator)
  • Store all data locally on device (no cloud transmission)
  • Request minimum required permissions

The application MUST NOT:

  • Transmit any user data to external servers
  • Store sensitive personal information
  • Access device sensors without explicit permission

9. Build and Deployment Requirements

9.1 Build Configuration

The application MUST:

  • Define separate build configurations for Debug, Release, and Testing
  • Enable code optimization for Release builds
  • Include debug symbols for all builds
  • Version assemblies using semantic versioning (SemVer)

9.2 Continuous Integration

The application MUST:

  • Execute automated builds on every commit
  • Run all unit and integration tests in CI pipeline
  • Enforce code coverage thresholds (≥95%)
  • Generate coverage reports for each build

The application SHOULD:

  • Use GitHub Actions for CI/CD automation
  • Cache NuGet packages for faster builds
  • Parallelize test execution

9.3 Release Process

The application MUST:

  • Follow phased release approach: iOS → Web → macOS
  • Increment version number for each release
  • Tag releases in version control
  • Generate release notes from commit history

10. Documentation Requirements

The application MUST provide:

  • README.md with build instructions and prerequisites
  • Architecture decision records (ADR) for significant technical choices
  • API documentation for all public interfaces (XML comments)
  • User guide covering all features

The application SHOULD provide:

  • Contribution guidelines for external contributors
  • Code style guide referencing EditorConfig rules
  • Troubleshooting guide for common issues

11. Dependencies

11.1 Required Dependencies

The application MUST use the following NuGet packages:

  • Microsoft.Maui.Controls (≥8.0.0, <9.0.0)
  • CommunityToolkit.Mvvm (≥8.2.0)
  • sqlite-net-pcl (≥1.9.0)
  • SQLitePCLRaw.bundle_green (≥2.1.0)

11.2 Testing Dependencies

The application MUST use the following packages for testing:

  • xUnit (≥2.6.0)
  • NSubstitute (≥5.1.0)
  • FluentAssertions (≥6.12.0)
  • Coverlet.Collector (≥6.0.0)

11.3 Dependency Management

The application MUST:

  • Pin major versions to prevent breaking changes
  • Review and update dependencies quarterly
  • Address security vulnerabilities within 30 days of disclosure

The application MUST NOT:

  • Use pre-release or beta packages in production builds
  • Include unnecessary dependencies

12. Compliance and Standards

12.1 Coding Standards

The application MUST adhere to:

  • C# coding conventions (Microsoft official style guide)
  • .NET naming conventions
  • EditorConfig rules defined in repository

12.2 Accessibility Standards

The application MUST comply with:

  • WCAG 2.1 Level AA
  • Section 508 (U.S. accessibility requirements)
  • iOS Accessibility Guidelines
  • macOS Accessibility Guidelines

13. Future Enhancements

The following features MAY be implemented in future versions:

13.1 Statistics Dashboard

  • Display aggregate usage statistics
  • Track most common estimates
  • Show humorous mode discovery rate
  • Calculate average shake intensity

13.2 Customization

  • Allow user-defined estimate pools
  • Configurable sensitivity thresholds
  • Custom color themes

13.3 Social Features

  • Share estimates to clipboard
  • Export history as text/image
  • Team synchronization mode

13.4 Localization

  • Finnish translation (fi-FI)
  • Additional language support

14. Acceptance Criteria

For the application to be considered complete and ready for release, it MUST:

  • Build successfully on all target platforms without errors
  • Pass all automated tests with ≥95% code coverage
  • Function correctly on iOS 15+ devices with accurate shake detection
  • Persist settings and history across app restarts
  • Display estimates within 200ms of shake completion
  • Correctly implement easter egg (15-second humorous mode)
  • Meet WCAG 2.1 Level AA accessibility standards
  • Complete security review with no high/critical vulnerabilities
  • Pass manual testing on representative devices
  • Include complete user and developer documentation

15. Glossary

  • Shake Intensity: Normalized measure of shake strength, range [0.0, 1.0]
  • Shake Duration: Time elapsed from shake start to shake stop
  • Easter Egg: Hidden humorous mode triggered by prolonged shaking (>15 seconds)
  • Estimate Pool: Predefined collection of possible time estimates for a given mode
  • Gentle Shake: Shake with intensity < 0.3
  • Hard Shake: Shake with intensity ≥ 0.7
  • LTS: Long-Term Support (.NET version with extended support period)

Document Version: 1.0 Last Updated: 2025-11-18 Status: Draft - Pending Implementation Prepared by: Claude Code Approved by: [Pending]


Revision History

Version Date Author Changes
1.0 2025-11-18 Claude Code Initial specification document

END OF SPECIFICATION