[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6H4A71JX01JR4VMSA4GDWC5":3,"skill-same:01M6H4A71JX01JR4VMSA4GDWC5":81},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":48,"commitSha":49,"skillDirectory":50,"forksCount":51,"repositoryHtmlUrl":52,"repositoryHomepageUrl":53,"ownerHtmlUrl":54,"ownerBlogUrl":55,"ownerDescription":6,"updatedAt":56,"install":57,"resources":70},"01M6H4A71JX01JR4VMSA4GDWC5","swift-lang",null,"Swift 6 language and tooling - concurrency model, Sendable, actors, replacing DispatchQueue and completion handlers with async\u002Fawait, XCTest basics, and xcodebuild. Use for Swift code that is not a SwiftUI view. For SwiftUI architecture and view-layer testing, see `swiftui-lang`.","eyelock\u002Fassistants","eyelock","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1277325?v=4","01M6H423MGYJ0P316VZ2MMH75N","David Collie","01M6H423RR18QA9N8S2F3J8S8X",1,"MIT","https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants\u002Fblob\u002Fdevelop\u002Fskills\u002Ftech\u002Fskills\u002Fswift-lang\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"swift","swift lang","basics","testing","await","for","layer","with","language","async","swiftui architecture","architecture","tooling","use","view","swiftui","model","concurrency","code","2026-11-10 10:12:30",false,"---\nname: swift-lang\ndescription: Swift 6 language and tooling - concurrency model, Sendable, actors, replacing DispatchQueue and completion handlers with async\u002Fawait, XCTest basics, and xcodebuild. Use for Swift code that is not a SwiftUI view. For SwiftUI architecture and view-layer testing, see `swiftui-lang`.\n---\n\n# Swift Development\n\nFor SwiftUI-specific architecture (ViewModel extraction, DI, ViewInspector, snapshot testing, coverage targets by layer), load the `swiftui-lang` skill.\n\n## Swift 6 Concurrency\n\nSwift 6 enforces data isolation at compile time. Every type must be either `Sendable` or confined to an actor.\n\n**Actors** isolate mutable state:\n```swift\nactor MyService {\n    private var cache: [String: Data] = [:]\n\n    func store(_ data: Data, for key: String) {\n        cache[key] = data\n    }\n\n    func fetch(key: String) -> Data? {\n        cache[key]\n    }\n}\n```\n\nCallers outside the actor `await` its methods; the hop onto the actor makes them asynchronous without marking them `async`.\n\n**`@MainActor`** for UI-bound types:\n```swift\n@MainActor\nfinal class ViewModel: ObservableObject {\n    @Published var items: [Item] = []\n}\n```\n\n**`Sendable`** for types crossing actor boundaries — must be value types or immutable:\n```swift\nstruct Config: Sendable {\n    let baseURL: URL\n    let timeout: TimeInterval\n}\n```\n\n**Rules:**\n- Prefer value types (`struct`) over reference types (`class`) for `Sendable` conformance\n- Mark `@Observable` types as `@MainActor` when they drive UI\n- Use `async\u002Fawait` — avoid `DispatchQueue` and callback chains\n- Never use `nonisolated(unsafe)` without a clear documented reason\n\n### Enforce strict concurrency at compile time\n\nManual review cannot catch every missed `@Sendable` on a closure handed to an Apple SDK that dispatches on a background queue. The only durable enforcement is the build flag:\n\n```swift\n\u002F\u002F Package.swift\n.target(\n    name: \"App\",\n    swiftSettings: [.enableExperimentalFeature(\"StrictConcurrency=complete\")]\n)\n```\n\nUntil the project compiles cleanly under `StrictConcurrency=complete`, treat every closure literal written inside a `@MainActor` scope as a latent EXC_BREAKPOINT — see `swiftui-lang` for the per-call-site rule.\n\n### Pick one async primitive\n\n`DispatchQueue.main.asyncAfter`, `Task.sleep(nanoseconds:)`, `Timer.scheduledTimer`, and bare GCD coexisting in the same codebase is a smell. Default to `async\u002Fawait`; reach for `Timer` only for periodic UI ticks. New code should not introduce GCD.\n\n`Task.sleep` used to wait for \"something to be ready\" (connect, callback drain, settle) is a race-condition workaround, not coordination. It will go flaky under load and mask the next race. Replace with an explicit signal: a continuation, an `AsyncStream`, or a state observer.\n\n## Error handling — `try?` is a regression amplifier\n\n`try?` converts loud failures into silent ones. The user sees \"nothing happened\" and there is nothing to debug. Reserve it for cases where the failure genuinely has no consequence (e.g. best-effort cache prime). For anything user-visible — git, subprocess, filesystem, network — surface the error:\n\n```swift\n\u002F\u002F Bad — silent\nlet branches = try? await git.listBranches()\n\n\u002F\u002F Good — log and propagate or present\ndo {\n    let branches = try await git.listBranches()\n    ...\n} catch {\n    logger.error(\"git listBranches failed: \\(error)\")\n    throw error  \u002F\u002F or surface to the user\n}\n```\n\n## Testing with XCTest\n\n```swift\nfinal class MyServiceTests: XCTestCase {\n    func testFetch_AfterStore_ReturnsStoredData() async {\n        let service = MyService()\n        let data = Data(\"value\".utf8)\n        await service.store(data, for: \"key\")\n\n        let result = await service.fetch(key: \"key\")\n\n        XCTAssertEqual(result, data)\n    }\n}\n```\n\n**Rules:**\n- Test names describe the scenario: `test\u003CSubject>_\u003CCondition>_\u003CExpectedResult>`\n- Async tests are `async` (add `throws` when the code under test throws) — no `XCTestExpectation` for async work\n- Create shared fixtures in `setUp()` and release them in `tearDown()`, not in property initializers\n- Test at the unit boundary — mock only at system edges (network, filesystem)\n\n## xcodebuild Tooling\n\nPrefer `make` targets over direct `xcodebuild` invocations. Projects expose:\n\n```bash\nmake build         # xcodebuild build\nmake test          # xcodebuild test\nmake lint          # SwiftLint\nmake format        # SwiftFormat (fix)\nmake format-check  # SwiftFormat (check only, for CI)\nmake check         # build + lint + format-check + test\n```\n\nRunning directly when needed:\n```bash\nxcodebuild build -scheme MyApp -destination 'platform=macOS'\nxcodebuild test  -scheme MyApp -destination 'platform=macOS'\n```\n\n## Code Signing (macOS)\n\n- Debug builds: automatic signing, any team\n- Release\u002Fdistribution builds: specific team ID, provisioning profile\n- Notarization required for distribution outside the App Store\n- Entitlements (`*.entitlements`) must match capabilities declared in the target\n\nNever hardcode signing identity strings — use `CODE_SIGN_IDENTITY=` with build setting variables.\n","# Swift Development\n\nFor SwiftUI-specific architecture (ViewModel extraction, DI, ViewInspector, snapshot testing, coverage targets by layer), load the `swiftui-lang` skill.\n\n## Swift 6 Concurrency\n\nSwift 6 enforces data isolation at compile time. Every type must be either `Sendable` or confined to an actor.\n\n**Actors** isolate mutable state:\n```swift\nactor MyService {\n    private var cache: [String: Data] = [:]\n\n    func store(_ data: Data, for key: String) {\n        cache[key] = data\n    }\n\n    func fetch(key: String) -> Data? {\n        cache[key]\n    }\n}\n```\n\nCallers outside the actor `await` its methods; the hop onto the actor makes them asynchronous without marking them `async`.\n\n**`@MainActor`** for UI-bound types:\n```swift\n@MainActor\nfinal class ViewModel: ObservableObject {\n    @Published var items: [Item] = []\n}\n```\n\n**`Sendable`** for types crossing actor boundaries — must be value types or immutable:\n```swift\nstruct Config: Sendable {\n    let baseURL: URL\n    let timeout: TimeInterval\n}\n```\n\n**Rules:**\n- Prefer value types (`struct`) over reference types (`class`) for `Sendable` conformance\n- Mark `@Observable` types as `@MainActor` when they drive UI\n- Use `async\u002Fawait` — avoid `DispatchQueue` and callback chains\n- Never use `nonisolated(unsafe)` without a clear documented reason\n\n### Enforce strict concurrency at compile time\n\nManual review cannot catch every missed `@Sendable` on a closure handed to an Apple SDK that dispatches on a background queue. The only durable enforcement is the build flag:\n\n```swift\n\u002F\u002F Package.swift\n.target(\n    name: \"App\",\n    swiftSettings: [.enableExperimentalFeature(\"StrictConcurrency=complete\")]\n)\n```\n\nUntil the project compiles cleanly under `StrictConcurrency=complete`, treat every closure literal written inside a `@MainActor` scope as a latent EXC_BREAKPOINT — see `swiftui-lang` for the per-call-site rule.\n\n### Pick one async primitive\n\n`DispatchQueue.main.asyncAfter`, `Task.sleep(nanoseconds:)`, `Timer.scheduledTimer`, and bare GCD coexisting in the same codebase is a smell. Default to `async\u002Fawait`; reach for `Timer` only for periodic UI ticks. New code should not introduce GCD.\n\n`Task.sleep` used to wait for \"something to be ready\" (connect, callback drain, settle) is a race-condition workaround, not coordination. It will go flaky under load and mask the next race. Replace with an explicit signal: a continuation, an `AsyncStream`, or a state observer.\n\n## Error handling — `try?` is a regression amplifier\n\n`try?` converts loud failures into silent ones. The user sees \"nothing happened\" and there is nothing to debug. Reserve it for cases where the failure genuinely has no consequence (e.g. best-effort cache prime). For anything user-visible — git, subprocess, filesystem, network — surface the error:\n\n```swift\n\u002F\u002F Bad — silent\nlet branches = try? await git.listBranches()\n\n\u002F\u002F Good — log and propagate or present\ndo {\n    let branches = try await git.listBranches()\n    ...\n} catch {\n    logger.error(\"git listBranches failed: \\(error)\")\n    throw error  \u002F\u002F or surface to the user\n}\n```\n\n## Testing with XCTest\n\n```swift\nfinal class MyServiceTests: XCTestCase {\n    func testFetch_AfterStore_ReturnsStoredData() async {\n        let service = MyService()\n        let data = Data(\"value\".utf8)\n        await service.store(data, for: \"key\")\n\n        let result = await service.fetch(key: \"key\")\n\n        XCTAssertEqual(result, data)\n    }\n}\n```\n\n**Rules:**\n- Test names describe the scenario: `test\u003CSubject>_\u003CCondition>_\u003CExpectedResult>`\n- Async tests are `async` (add `throws` when the code under test throws) — no `XCTestExpectation` for async work\n- Create shared fixtures in `setUp()` and release them in `tearDown()`, not in property initializers\n- Test at the unit boundary — mock only at system edges (network, filesystem)\n\n## xcodebuild Tooling\n\nPrefer `make` targets over direct `xcodebuild` invocations. Projects expose:\n\n```bash\nmake build         # xcodebuild build\nmake test          # xcodebuild test\nmake lint          # SwiftLint\nmake format        # SwiftFormat (fix)\nmake format-check  # SwiftFormat (check only, for CI)\nmake check         # build + lint + format-check + test\n```\n\nRunning directly when needed:\n```bash\nxcodebuild build -scheme MyApp -destination 'platform=macOS'\nxcodebuild test  -scheme MyApp -destination 'platform=macOS'\n```\n\n## Code Signing (macOS)\n\n- Debug builds: automatic signing, any team\n- Release\u002Fdistribution builds: specific team ID, provisioning profile\n- Notarization required for distribution outside the App Store\n- Entitlements (`*.entitlements`) must match capabilities declared in the target\n\nNever hardcode signing identity strings — use `CODE_SIGN_IDENTITY=` with build setting variables.\n",{"name":5,"description":7},"develop","5f79513fe27520bf03af784e8df568a04931c48d","skills\u002Ftech\u002Fskills\u002Fswift-lang",0,"https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants","https:\u002F\u002Feyelock.github.io\u002Fassistants\u002F","https:\u002F\u002Fgithub.com\u002Feyelock","http:\u002F\u002Fwww.eyelock.net\u002Fblog","2026-11-14 00:30:01",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add eyelock\u002Fassistants --skill swift-lang",{"tool":63,"command":64},"bunx","bunx skills add eyelock\u002Fassistants --skill swift-lang",{"tool":66,"command":67},"pnpm","pnpm dlx skills add eyelock\u002Fassistants --skill swift-lang","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants\u002Fblob\u002Fdevelop\u002Fskills\u002Ftech\u002Fskills\u002Fswift-lang\u002FSKILL.md",true,[71,77],{"path":72,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":75,"sourceHtmlUrl":76},"evals\u002Feval_queries.json","REFERENCE","参考文档",1052,"https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants\u002Fblob\u002Fdevelop\u002Fskills\u002Ftech\u002Fskills\u002Fswift-lang\u002Fevals\u002Feval_queries.json",{"path":78,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":79,"sourceHtmlUrl":80},"evals\u002Fevals.json",3601,"https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants\u002Fblob\u002Fdevelop\u002Fskills\u002Ftech\u002Fskills\u002Fswift-lang\u002Fevals\u002Fevals.json",[82,88,113,130,142,155],{"skillNo":83,"name":84,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":43},"01M6H46CHAJFE20J3Q118P9PW9","doctor","https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants\u002Fblob\u002Fdevelop\u002Fplugins\u002Fwheelhouse\u002Fskills\u002Fdoctor\u002FSKILL.md",[],[84],{"skillNo":89,"name":90,"nameZh":6,"description":91,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":94,"publishedAt":43},"01M6H45X8QJZTQAPN56WZ8V111","add-seat","Add a named seat to a Wheelhouse - a crew member, a standing role (such as a dispatcher) or a worker - as a ynh harness with its charter, standing orders and only the tools its job needs, named from the Wheelhouse's roster. Use when asked to add, create or set up a seat, role, worker or agent in a Wheelhouse (a release manager, a PR watcher, a dispatcher, a designer, more workers), or to give a role a name, or to start on a Wheelhouse's team (its starter team), one role at a time. Also use to trial, make official or drop a seat.","https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants\u002Fblob\u002Fdevelop\u002Fplugins\u002Fwheelhouse\u002Fskills\u002Fadd-seat\u002FSKILL.md",[],[95,96,97,98,99,37,100,101,102,31,103,104,105,106,107,108,109,110,111,112],"add","add seat","harness","SET","roster","release manager","workers","team","create","watcher","starter","when","more","worker","up","only","pr","as",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":43},"01M6H4BWCVR2YJVP8RW878NYDP","voice","How voices work - what a voice skill contains, how to write a new one, and how several voices compose into one reply. Use whenever drafting a reply in a named voice, or when asked to create or change a voice.","https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants\u002Fblob\u002Fdevelop\u002Fskills\u002Fvoice\u002Fskills\u002Fvoice\u002FSKILL.md",[],[115,103,120,121,122,123,37,124,125,126,127,128,106,129],"how to","work","change","voice skill","compose","how","write","reply","new","drafting",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":136,"publishedAt":43},"01M6H4BRVA87C6T495HCFNDQ7Z","voice-warm","A friendly voice that acknowledges the person and their effort. Compose with direct for friendly but brief.","https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants\u002Fblob\u002Fdevelop\u002Fskills\u002Fvoice\u002Fskills\u002Fvoice-warm\u002FSKILL.md",[],[137,115,138,31,139,124,140,29,141],"voice warm","person","brief","direct","but",{"skillNo":143,"name":144,"nameZh":6,"description":145,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":146,"categories":147,"keywords":148,"publishedAt":43},"01M6H4BNFQ64X65YZDM9QMD61B","voice-formal","A careful, complete voice for people outside the team - customers, partners, senior stakeholders.","https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants\u002Fblob\u002Fdevelop\u002Fskills\u002Fvoice\u002Fskills\u002Fvoice-formal\u002FSKILL.md",[],[149,115,102,150,151,152,153,154,29],"voice formal","complete","senior","careful","partners","people",{"skillNo":156,"name":157,"nameZh":6,"description":158,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":159,"categories":160,"keywords":161,"publishedAt":43},"01M6H4BHXE6KSNBY92TBFZY7QD","voice-direct","A plain, brief voice that leads with the answer. The default when no voice is named.","https:\u002F\u002Fgithub.com\u002Feyelock\u002Fassistants\u002Fblob\u002Fdevelop\u002Fskills\u002Fvoice\u002Fskills\u002Fvoice-direct\u002FSKILL.md",[],[162,140,115,31,139,163,164,165,106,166],"voice direct","leads","answer","default","plain"]