{
  "skill_name": "swift-concurrency",
  "evals": [
    {
      "id": 0,
      "name": "settings-plan-review",
      "prompt": "Check this plan for our podcast app on Swift 6.3 and Xcode 26: (1) turning on Approachable Concurrency is enough to make the whole app target main-actor isolated; (2) we will begin the Swift 6 migration at the Targeted strict-concurrency level; (3) waveform rendering is CPU heavy but can stay on the main actor, because nonisolated async functions hop to a background thread anyway. Correct what is wrong and say what we should do instead.",
      "expected_output": "Separates the two settings: Approachable Concurrency enables upcoming features, whereas inferring @MainActor everywhere needs the Default Actor Isolation build setting set to MainActor. Notes that the Swift 6 language mode (6.3 included) is complete checking with errors and that Targeted and Minimal are Swift 5 staging levels. Explains that with NonisolatedNonsendingByDefault a nonisolated async function keeps executing on whichever actor called it, so the rendering must be moved with @concurrent on a nonisolated function. Stays at the level of settings and code-level fixes.",
      "files": [],
      "expectations": [
        "Treats Approachable Concurrency and Default Actor Isolation as two separate settings, and only the latter, set to MainActor, gives main-actor-by-default",
        "States that in Swift 6 (and 6.3) mode checking is always complete and reports errors, while the Targeted and Minimal levels belong to Swift 5 staging",
        "Says a nonisolated async function inherits the calling actor, the nonisolated(nonsending) behavior, until @concurrent is added",
        "Moves the CPU-heavy rendering off the main actor with @concurrent in a nonisolated context",
        "Limits the answer to build settings and code-level changes, with no broader redesign of architecture or SwiftUI state"
      ]
    },
    {
      "id": 1,
      "name": "default-isolation-remediation",
      "prompt": "Our app target uses Default Actor Isolation = MainActor. We get errors on an @Observable PlaylistModel that conforms to our Archivable protocol, on an async render method of a plain WaveformRenderer class, and around a vendor analytics SDK we import with @preconcurrency. Give a remediation plan that keeps behavior the same, and tell us what is out of scope for this pass.",
      "expected_output": "Keeps PlaylistModel on the main actor and meets the protocol through a main-actor isolated conformance, written extension PlaylistModel: @MainActor Archivable. Explains that WaveformRenderer.render executes on its caller's actor under nonisolated(nonsending), so only CPU-heavy parts should move to a @concurrent nonisolated function. Prefers immutable values, actor isolation or locks over @unchecked Sendable. Treats the @preconcurrency import as temporary with a written removal plan, and leaves module layout, navigation and who owns which SwiftUI state to sibling skills.",
      "files": [],
      "expectations": [
        "Fixes the conformance with @MainActor on the type or the isolated form extension PlaylistModel: @MainActor Archivable",
        "Separates the case where WaveformRenderer may keep running on the calling actor from CPU-bound work that belongs in a @concurrent nonisolated function",
        "Reaches for immutable values, an actor or a lock before any @unchecked Sendable",
        "Keeps the @preconcurrency import only temporarily and asks for a written plan to drop it",
        "Hands module layout, navigation and fine-grained SwiftUI state ownership over to sibling skills"
      ]
    },
    {
      "id": 2,
      "name": "locks-versus-actors",
      "prompt": "Review this plan; the app's deployment range is iOS 16 up to iOS 26: an actor holds the frame-drop counter that a C audio callback increments synchronously; another actor guards its dictionary with an NSLock as extra protection; a Mutex stays locked while we await the network refresh; and NSLock is banned because it is not Sendable. What should change?",
      "expected_output": "Keeps actors for shared mutable state reached asynchronously where hops are acceptable, and replaces the counter with Atomic on iOS 18 or a lock for iOS 16-17 because the C callback is synchronous. Picks Mutex where iOS 18 is the floor and OSAllocatedUnfairLock for the iOS 16 and 17 range or when lock ownership should be asserted. Removes the NSLock from inside the actor and never holds a lock across await. Points out that NSLock does conform to Sendable, yet still favors the newer primitives that own their state.",
      "files": [],
      "expectations": [
        "Keeps an actor where every caller can await and the hop cost does not matter",
        "Chooses Mutex when iOS 18 is the minimum, OSAllocatedUnfairLock for iOS 16 and 17 or for ownership preconditions",
        "Uses Atomic for a simple scalar counter or flag instead of an actor or a full lock",
        "Rejects locks inside actors and any lock held across await",
        "Fixes the false statement that NSLock lacks Sendable, but still prefers the newer lock types that hold their state"
      ]
    }
  ]
}
