{
  "skill_name": "ios-haptics",
  "evals": [
    {
      "id": 0,
      "name": "too-many-haptics-review",
      "prompt": "Our SwiftUI app fires UIImpactFeedbackGenerator(style: .heavy).impactOccurred() on every button tap, on every toggle change, on every scroll page, and when background sync finishes. Users complain it feels buzzy. Review this and rewrite the approach.",
      "expected_output": "Cuts haptics to meaningful causes: removes them from scrolling, background sync and toggles (toggles already play system haptics), keeps a few outcome haptics. Moves SwiftUI usage to sensoryFeedback tied to a trigger value (success, error, selection), avoids creating a generator per tap, keeps feedback in the UI layer, offers an in-app switch, pairs haptics with visual feedback, and recommends testing on a device because the simulator plays no haptics.",
      "files": [],
      "expectations": [
        "Removes haptics from scrolling and background sync",
        "Notes standard toggles already play haptics, avoiding doubles",
        "Uses sensoryFeedback with a trigger value in SwiftUI",
        "Uses notification-style feedback (success or error) for outcomes",
        "Mentions a user setting to turn haptics off or pairing with visual feedback",
        "Says haptics must be tested on a physical device"
      ]
    },
    {
      "id": 1,
      "name": "drag-snap-uikit",
      "prompt": "In a UIKit canvas editor, objects snap to guides while dragging. We want a crisp tick at each snap with minimal latency, iOS 17.5+. What should we use?",
      "expected_output": "Uses a feedback generator kept alive for the drag: UICanvasFeedbackGenerator alignmentOccurred(at:) for snapping to guides, or UIImpactFeedbackGenerator created with init(style:view:) and impactOccurred(intensity:at:) with the touch location. Calls prepare() when the drag begins, not right before firing, and fires once per snap from the UI layer.",
      "files": [],
      "expectations": [
        "Names UICanvasFeedbackGenerator or a view-attached UIImpactFeedbackGenerator",
        "Passes the touch location (alignmentOccurred(at:) or impactOccurred(intensity:at:))",
        "Calls prepare() at drag start to reduce latency",
        "Keeps one generator for the interaction instead of creating one per snap",
        "Fires once per snap rather than continuously"
      ]
    },
    {
      "id": 2,
      "name": "custom-pattern-core-haptics",
      "prompt": "Design wants a checkout success haptic: a sharp tap followed by a short soft swell, tunable by designers without app releases. How do we build this properly?",
      "expected_output": "Uses Core Haptics: checks supportsHaptics, creates an engine, sets stopped and reset handlers before start, restarts and recreates players after reset, stops the engine or enables auto shutdown for power. Builds a transient event plus a continuous event with a parameter curve, and stores the pattern in a bundled AHAP file loaded with playPattern(from:) or CHHapticPattern(contentsOf:). Pairs the haptic with visual confirmation and notes devices without haptics.",
      "files": [],
      "expectations": [
        "Checks hardware support with capabilitiesForHardware",
        "Sets stoppedHandler and resetHandler and restarts after reset",
        "Combines a transient event with a continuous event or curve",
        "Uses an AHAP file for designer tuning",
        "Stops the engine when idle or uses isAutoShutdownEnabled",
        "Keeps a visual confirmation alongside the haptic"
      ]
    }
  ]
}
