@mmerterden/multi-agent-pipeline 20.36.0 → 20.37.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/docs/facts.json +2 -2
  3. package/docs/features.md +1 -1
  4. package/docs/recovery-guide.md +1 -1
  5. package/install/catalog-history.json +1 -1
  6. package/manifest.json +225 -148
  7. package/package.json +1 -1
  8. package/pipeline/commands/multi-agent/SKILL.md +33 -154
  9. package/pipeline/commands/multi-agent/analysis/SKILL.md +14 -68
  10. package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +5 -8
  11. package/pipeline/commands/multi-agent/autopilot-on/SKILL.md +38 -109
  12. package/pipeline/commands/multi-agent/channels/SKILL.md +38 -167
  13. package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +37 -144
  14. package/pipeline/commands/multi-agent/design-check/SKILL.md +27 -131
  15. package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +22 -48
  16. package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +37 -180
  17. package/pipeline/commands/multi-agent/jira/SKILL.md +16 -46
  18. package/pipeline/commands/multi-agent/manual-test/SKILL.md +12 -7
  19. package/pipeline/commands/multi-agent/refactor/SKILL.md +23 -184
  20. package/pipeline/commands/multi-agent/resume/SKILL.md +30 -136
  21. package/pipeline/commands/multi-agent/review/SKILL.md +24 -199
  22. package/pipeline/commands/multi-agent/setup/SKILL.md +25 -181
  23. package/pipeline/commands/multi-agent/stack/SKILL.md +9 -53
  24. package/pipeline/commands/multi-agent/status/SKILL.md +13 -2
  25. package/pipeline/commands/multi-agent/store-ready/SKILL.md +27 -226
  26. package/pipeline/commands/multi-agent/sync/SKILL.md +35 -164
  27. package/pipeline/commands/multi-agent/test-gen/SKILL.md +2 -4
  28. package/pipeline/commands/multi-agent/update/SKILL.md +18 -60
  29. package/pipeline/contract/CHANGELOG.md +9 -0
  30. package/pipeline/contract/fixtures/error-invalid-request.json +1 -1
  31. package/pipeline/contract/fixtures/error-unauthorized.json +1 -1
  32. package/pipeline/contract/fixtures/error-unsigned.json +1 -1
  33. package/pipeline/contract/fixtures/runs-awaiting-question.json +1 -1
  34. package/pipeline/contract/fixtures/runs-empty.json +1 -1
  35. package/pipeline/contract/fixtures/runs-failed.json +1 -1
  36. package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +1 -1
  37. package/pipeline/contract/fixtures/runs-pr-opened.json +1 -1
  38. package/pipeline/contract/fixtures/runs-running.json +1 -1
  39. package/pipeline/contract/manifest.json +5 -5
  40. package/pipeline/contract/types/index.d.ts +3 -2
  41. package/pipeline/multi-agent-refs/audit-guide.md +20 -0
  42. package/pipeline/multi-agent-refs/autopilot-on/details.md +148 -0
  43. package/pipeline/multi-agent-refs/channels/generator.md +14 -0
  44. package/pipeline/multi-agent-refs/channels/preview.md +13 -0
  45. package/pipeline/multi-agent-refs/channels/reference.md +46 -0
  46. package/pipeline/multi-agent-refs/complaint-analysis/phases.md +159 -0
  47. package/pipeline/multi-agent-refs/design-check/export.md +1 -0
  48. package/pipeline/multi-agent-refs/design-check/init-inventory.md +1 -1
  49. package/pipeline/multi-agent-refs/design-check/scope-and-ledger.md +64 -0
  50. package/pipeline/multi-agent-refs/features/analysis-command-notes.md +53 -0
  51. package/pipeline/multi-agent-refs/features/commit-multi-repo.md +63 -0
  52. package/pipeline/multi-agent-refs/features/dev-multi-repo.md +51 -0
  53. package/pipeline/multi-agent-refs/features/test-gap.md +40 -0
  54. package/pipeline/multi-agent-refs/features/worktree-finalize.md +1 -1
  55. package/pipeline/multi-agent-refs/garbage-collect/phases.md +60 -0
  56. package/pipeline/multi-agent-refs/ios-coding-standard/plan.md +71 -0
  57. package/pipeline/multi-agent-refs/ios-coding-standard/resolve-and-scan.md +135 -0
  58. package/pipeline/multi-agent-refs/jira/picker-detail.md +71 -0
  59. package/pipeline/multi-agent-refs/orchestrator/copilot-pipeline.md +88 -0
  60. package/pipeline/multi-agent-refs/orchestrator/dispatcher.md +96 -1
  61. package/pipeline/multi-agent-refs/orchestrator/phase-3-user-test.md +12 -9
  62. package/pipeline/multi-agent-refs/phases/phase-1-plan.md +4 -4
  63. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +8 -47
  64. package/pipeline/multi-agent-refs/phases/phase-3-review.md +21 -65
  65. package/pipeline/multi-agent-refs/phases/phase-4-commit.md +9 -59
  66. package/pipeline/multi-agent-refs/phases/phase-5-report.md +0 -31
  67. package/pipeline/multi-agent-refs/refactor/sweep.md +190 -0
  68. package/pipeline/multi-agent-refs/resume/details.md +115 -2
  69. package/pipeline/multi-agent-refs/review/inputs.md +33 -1
  70. package/pipeline/multi-agent-refs/review/module-guides.md +9 -1
  71. package/pipeline/multi-agent-refs/review/panel.md +75 -0
  72. package/pipeline/multi-agent-refs/review/valven.md +5 -1
  73. package/pipeline/multi-agent-refs/rules.md +1 -1
  74. package/pipeline/multi-agent-refs/setup/hooks-and-plugins.md +4 -0
  75. package/pipeline/multi-agent-refs/setup/token-save-flow.md +13 -0
  76. package/pipeline/multi-agent-refs/stack/background.md +72 -0
  77. package/pipeline/multi-agent-refs/store-ready/gates.md +139 -0
  78. package/pipeline/multi-agent-refs/store-ready/report.md +40 -2
  79. package/pipeline/multi-agent-refs/sync/office.md +10 -0
  80. package/pipeline/multi-agent-refs/sync/overview.md +61 -0
  81. package/pipeline/multi-agent-refs/sync/repo.md +91 -0
  82. package/pipeline/multi-agent-refs/update/details.md +83 -0
  83. package/pipeline/office/index.html +6 -3
  84. package/pipeline/office/toolkit.json +1 -1
  85. package/pipeline/rules/figma-pipeline.md +6 -3
  86. package/pipeline/schemas/prefs.schema.json +1 -1
  87. package/pipeline/schemas/runs-index.schema.json +2 -1
  88. package/pipeline/scripts/_memory-policy.mjs +27 -5
  89. package/pipeline/scripts/checkpoint-fold.sh +59 -0
  90. package/pipeline/scripts/contract-server.mjs +1 -1
  91. package/pipeline/scripts/gate-ledger.mjs +1 -1
  92. package/pipeline/scripts/office-control.mjs +41 -15
  93. package/pipeline/scripts/offload-ref.sh +1 -1
  94. package/pipeline/scripts/rework-rulings.mjs +5 -3
  95. package/pipeline/scripts/runs-index.mjs +34 -7
  96. package/pipeline/scripts/scope-check-gate.mjs +15 -2
  97. package/pipeline/scripts/status-overview.mjs +401 -0
  98. package/pipeline/scripts/user-test-handoff.sh +203 -0
  99. package/pipeline/scripts/validate-planning.mjs +5 -3
  100. package/pipeline/scripts/validate-triage.mjs +2 -1
  101. package/pipeline/scripts/write-state.mjs +13 -4
  102. package/pipeline/skills/.skill-manifest.json +64 -64
  103. package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +7 -70
  104. package/pipeline/skills/shared/core/apple-archive-compliance/references/examples.md +67 -0
  105. package/pipeline/skills/shared/core/apple-archive-compliance/references/version-history.md +8 -0
  106. package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +10 -72
  107. package/pipeline/skills/shared/core/google-play-compliance/references/examples.md +69 -0
  108. package/pipeline/skills/shared/core/google-play-compliance/references/notes.md +7 -0
  109. package/pipeline/skills/shared/core/google-play-compliance/references/version-history.md +5 -0
  110. package/pipeline/skills/shared/core/multi-agent/SKILL.md +39 -262
  111. package/pipeline/skills/shared/core/multi-agent-autopilot-on/SKILL.md +35 -73
  112. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +37 -337
  113. package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +27 -122
  114. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +8 -340
  115. package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +37 -180
  116. package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +12 -7
  117. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +23 -184
  118. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +14 -82
  119. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +25 -277
  120. package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +13 -2
  121. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +73 -217
  122. package/pipeline/skills/shared/external/alarmkit/SKILL.md +11 -162
  123. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-code.md +257 -0
  124. package/pipeline/skills/shared/external/android-architecture/SKILL.md +7 -58
  125. package/pipeline/skills/shared/external/android-architecture/references/code-examples.md +68 -0
  126. package/pipeline/skills/shared/external/app-intents/SKILL.md +3 -45
  127. package/pipeline/skills/shared/external/app-intents/references/code-examples.md +54 -0
  128. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +5 -81
  129. package/pipeline/skills/shared/external/app-store-optimization/references/engagement-and-localization.md +96 -0
  130. package/pipeline/skills/shared/external/app-store-review/SKILL.md +6 -112
  131. package/pipeline/skills/shared/external/app-store-review/references/monetization-and-submission.md +138 -0
  132. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +10 -117
  133. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models-code.md +186 -0
  134. package/pipeline/skills/shared/external/authentication/SKILL.md +3 -50
  135. package/pipeline/skills/shared/external/authentication/references/code-examples.md +59 -0
  136. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +3 -84
  137. package/pipeline/skills/shared/external/callkit-voip/references/code-examples.md +93 -0
  138. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +7 -263
  139. package/pipeline/skills/shared/external/ci-cd-pipelines/references/pipeline-examples.md +281 -0
  140. package/pipeline/skills/shared/external/clean-code/SKILL.md +8 -41
  141. package/pipeline/skills/shared/external/clean-code/references/code-examples.md +56 -0
  142. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +8 -146
  143. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-code.md +214 -0
  144. package/pipeline/skills/shared/external/compose-components/SKILL.md +6 -80
  145. package/pipeline/skills/shared/external/compose-components/references/code-examples.md +89 -0
  146. package/pipeline/skills/shared/external/compose-navigation/SKILL.md +5 -64
  147. package/pipeline/skills/shared/external/compose-navigation/references/code-examples.md +70 -0
  148. package/pipeline/skills/shared/external/core-data/SKILL.md +9 -157
  149. package/pipeline/skills/shared/external/core-data/references/core-data-code.md +221 -0
  150. package/pipeline/skills/shared/external/core-nfc/SKILL.md +3 -89
  151. package/pipeline/skills/shared/external/core-nfc/references/code-examples.md +98 -0
  152. package/pipeline/skills/shared/external/coreml/SKILL.md +17 -133
  153. package/pipeline/skills/shared/external/coreml/references/coreml-code.md +208 -0
  154. package/pipeline/skills/shared/external/css-modern/SKILL.md +8 -131
  155. package/pipeline/skills/shared/external/css-modern/references/code-examples.md +142 -0
  156. package/pipeline/skills/shared/external/database-patterns/SKILL.md +6 -103
  157. package/pipeline/skills/shared/external/database-patterns/references/orm-examples.md +112 -0
  158. package/pipeline/skills/shared/external/html-semantic/SKILL.md +7 -48
  159. package/pipeline/skills/shared/external/html-semantic/references/code-examples.md +54 -0
  160. package/pipeline/skills/shared/external/humanizer/SKILL.md +6 -19
  161. package/pipeline/skills/shared/external/humanizer/references/voice.md +24 -0
  162. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +13 -170
  163. package/pipeline/skills/shared/external/ios-accessibility/references/assistive-tech-review.md +224 -0
  164. package/pipeline/skills/shared/external/ios-localization/SKILL.md +2 -24
  165. package/pipeline/skills/shared/external/ios-localization/references/code-examples.md +30 -0
  166. package/pipeline/skills/shared/external/ios-networking/SKILL.md +3 -58
  167. package/pipeline/skills/shared/external/ios-networking/references/code-examples.md +67 -0
  168. package/pipeline/skills/shared/external/ios-security/SKILL.md +4 -64
  169. package/pipeline/skills/shared/external/ios-security/references/code-examples.md +74 -0
  170. package/pipeline/skills/shared/external/live-activities/SKILL.md +4 -90
  171. package/pipeline/skills/shared/external/live-activities/references/code-examples.md +108 -0
  172. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +9 -23
  173. package/pipeline/skills/shared/external/localization-reuse-map/references/project-settings.md +22 -0
  174. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +5 -95
  175. package/pipeline/skills/shared/external/mapkit-location/references/code-examples.md +117 -0
  176. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +7 -106
  177. package/pipeline/skills/shared/external/nextjs-app-router/references/app-router-examples.md +124 -0
  178. package/pipeline/skills/shared/external/permissionkit/SKILL.md +2 -31
  179. package/pipeline/skills/shared/external/permissionkit/references/code-examples.md +37 -0
  180. package/pipeline/skills/shared/external/play-store-review/SKILL.md +6 -74
  181. package/pipeline/skills/shared/external/play-store-review/references/signing-and-policies.md +83 -0
  182. package/pipeline/skills/shared/external/push-notifications/SKILL.md +8 -125
  183. package/pipeline/skills/shared/external/push-notifications/references/notification-code.md +176 -0
  184. package/pipeline/skills/shared/external/python-patterns/SKILL.md +7 -158
  185. package/pipeline/skills/shared/external/python-patterns/references/python-examples.md +176 -0
  186. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +7 -157
  187. package/pipeline/skills/shared/external/rest-api-design/references/api-examples.md +175 -0
  188. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +11 -230
  189. package/pipeline/skills/shared/external/swift-architecture/references/pattern-examples.md +295 -0
  190. package/pipeline/skills/shared/external/swift-codable/SKILL.md +17 -149
  191. package/pipeline/skills/shared/external/swift-codable/references/codable-recipes.md +207 -0
  192. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +12 -99
  193. package/pipeline/skills/shared/external/swift-concurrency/references/code-examples.md +100 -0
  194. package/pipeline/skills/shared/external/swift-concurrency/references/swift-6-2-additions.md +18 -0
  195. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +9 -78
  196. package/pipeline/skills/shared/external/swift-formatstyle/references/formatstyle-examples.md +113 -0
  197. package/pipeline/skills/shared/external/swift-language/SKILL.md +3 -56
  198. package/pipeline/skills/shared/external/swift-language/references/code-examples.md +65 -0
  199. package/pipeline/skills/shared/external/swift-testing-pro/SKILL.md +1 -0
  200. package/pipeline/skills/shared/external/swiftdata/SKILL.md +6 -122
  201. package/pipeline/skills/shared/external/swiftdata/references/code-examples.md +140 -0
  202. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +12 -139
  203. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/interop-code.md +198 -0
  204. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +9 -81
  205. package/pipeline/skills/shared/external/tailwind-css/references/code-examples.md +91 -0
  206. package/pipeline/skills/shared/external/testing-backend/SKILL.md +7 -207
  207. package/pipeline/skills/shared/external/testing-backend/references/testing-examples.md +225 -0
  208. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +8 -89
  209. package/pipeline/skills/shared/external/typescript-patterns/references/code-examples.md +100 -0
  210. package/pipeline/skills/shared/external/vision-framework/SKILL.md +2 -20
  211. package/pipeline/skills/shared/external/vision-framework/references/code-examples.md +26 -0
  212. package/pipeline/skills/shared/external/vue-composition/SKILL.md +7 -169
  213. package/pipeline/skills/shared/external/vue-composition/references/vue-examples.md +187 -0
  214. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +7 -174
  215. package/pipeline/skills/shared/external/web-accessibility/references/a11y-examples.md +192 -0
  216. package/pipeline/skills/shared/external/web-performance/SKILL.md +8 -66
  217. package/pipeline/skills/shared/external/web-performance/references/code-examples.md +77 -0
  218. package/pipeline/skills/shared/external/web-testing/SKILL.md +11 -186
  219. package/pipeline/skills/shared/external/web-testing/references/testing-examples.md +213 -0
  220. /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/format-and-output.md +0 -0
  221. /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/publish-and-snapshot.md +0 -0
  222. /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/sources-and-recipes.md +0 -0
@@ -0,0 +1,18 @@
1
+ # Other Swift 6.2 Additions
2
+
3
+ Smaller Swift 6.2 additions next to the approachable-concurrency defaults. Each is covered in more depth in
4
+ concurrency-patterns.md.
5
+
6
+ - `Task.immediate` (SE-0472) runs synchronously on the current actor until its
7
+ first suspension instead of being enqueued; `Task.immediateDetached` adds
8
+ detached semantics. Use it where the enqueue delay is visible to the user,
9
+ for example `Task.immediate { await search.apply(query) }`.
10
+ - `Observations { }` (SE-0475) turns reads of `@Observable` properties into an
11
+ `AsyncSequence` with transactional updates:
12
+ `for await elapsed in Observations({ player.elapsed }) { scrubber.move(to: elapsed) }`.
13
+ - Isolated conformances let a main-actor type conform to a protocol whose
14
+ requirements it can only meet on the main actor. The compiler allows the
15
+ conformance only where that isolation holds.
16
+ - SE-0473 adds `.epoch` to `ContinuousClock` and `SuspendingClock`, but the
17
+ iOS 26.4 SDK does not ship it yet ("value of type 'ContinuousClock' has no
18
+ member 'epoch'"); check your SDK before relying on it.
@@ -107,46 +107,14 @@ passRate.formatted(.percent) // "42%"
107
107
 
108
108
  Build exactly the fields you want; the locale decides order and punctuation.
109
109
 
110
- ```swift
111
- let launch = Date.now
112
- launch.formatted(.dateTime.day().month().year()) // "Mar 3, 2026" (order comes from the locale)
113
- launch.formatted(.dateTime.minute().hour()) // "4:05 PM"
114
- let spelledOut = Date.FormatStyle.dateTime.day().month(.wide).weekday(.wide)
115
- launch.formatted(spelledOut) // "Tuesday, March 3"
116
- ```
117
-
118
- Predefined combinations:
119
-
120
- ```swift
121
- launch.formatted(date: .long, time: .shortened) // "March 3, 2026 at 4:05 PM"
122
- launch.formatted(date: .abbreviated, time: .omitted) // "Mar 3, 2026"
123
- launch.formatted(.iso8601) // "2026-03-03T13:05:00Z"
124
- ```
125
-
126
- Relative to now:
127
-
128
- ```swift
129
- let dayBefore = Date.now.addingTimeInterval(-86_400)
130
- dayBefore.formatted(.relative(presentation: .named)) // "yesterday"
131
- let numericAgo = Date.RelativeFormatStyle(presentation: .numeric)
132
- dayBefore.formatted(numericAgo) // "1 day ago"
133
- ```
134
-
135
- Ranges and countdowns:
136
-
137
- ```swift
138
- let slot = launch..<launch.addingTimeInterval(5_400)
139
- let meetingSpan = Date.IntervalFormatStyle().day().month().minute().hour()
140
- slot.formatted(meetingSpan) // "Mar 3, 4:05 - 5:35 PM" (ICU prints an en dash)
141
-
142
- let untilDeparture = Date.now..<Date.now.addingTimeInterval(190_800)
143
- let countdown = Date.ComponentsFormatStyle(style: .wide, fields: [.hour, .day])
144
- untilDeparture.formatted(countdown) // "2 days, 5 hours"
145
- ```
110
+ The reference shows predefined combinations, relative-to-now formatting, and
111
+ ranges and countdowns.
146
112
 
147
113
  Related types: `Date.FormatStyle`, `Date.RelativeFormatStyle`,
148
114
  `Date.IntervalFormatStyle`, `Date.ComponentsFormatStyle`.
149
115
 
116
+ Code for this section: [FormatStyle examples](references/formatstyle-examples.md).
117
+
150
118
  ### Relative to a chosen reference (iOS 18+)
151
119
 
152
120
  `Date.AnchoredRelativeFormatStyle` describes one fixed date, the anchor,
@@ -166,28 +134,10 @@ style.format(meetup.addingTimeInterval(-3_600)) // "in 1 hour"
166
134
  A `Duration` (iOS 16+) can be shown as a clock reading with
167
135
  `Duration.TimeFormatStyle` or as labeled units with `Duration.UnitsFormatStyle`.
168
136
 
169
- ```swift
170
- let ride = Duration.seconds(7_384) // 2 h 3 min 4 s
171
- ride.formatted(.time(pattern: .hourMinuteSecond)) // "2:03:04"
172
- ride.formatted(.time(pattern: .hourMinute)) // "2:03"
173
- ride.formatted(.time(pattern: .minuteSecond)) // "123:04" (minutes are not wrapped into hours)
174
-
175
- let stopwatch = Duration.TimeFormatStyle.Pattern.minuteSecond(padMinuteToLength: 2, fractionalSecondsLength: 2)
176
- Duration.milliseconds(3_750).formatted(.time(pattern: stopwatch)) // "00:03.75"
177
- ```
178
-
179
- ```swift
180
- let clock: Set<Duration.UnitsFormatStyle.Unit> = [.hours, .minutes, .seconds]
181
- ride.formatted(.units(allowed: clock, width: .abbreviated)) // "2 hr, 3 min, 4 sec"
182
- ride.formatted(.units(allowed: clock, width: .wide, maximumUnitCount: 1)) // "2 hours"
183
-
184
- let rest = Duration.seconds(150)
185
- rest.formatted(.units(allowed: [.minutes, .seconds], width: .wide)) // "2 minutes, 30 seconds"
186
- rest.formatted(.units(allowed: [.minutes, .seconds], width: .narrow)) // "2m 30s"
187
- ```
188
-
189
137
  `maximumUnitCount` caps how many units appear.
190
138
 
139
+ Code for this section: [FormatStyle examples](references/formatstyle-examples.md).
140
+
191
141
  ## Measurements
192
142
 
193
143
  ```swift
@@ -297,33 +247,13 @@ Conform to `FormatStyle` and implement `format(_:)`. Add `ParseableFormatStyle`
297
247
  if the text must also be read back. `FormatStyle` inherits `Codable` and
298
248
  `Hashable`, so keep stored properties simple value types.
299
249
 
300
- ```swift
301
- struct CompactCountStyle: FormatStyle {
302
- func format(_ count: Int) -> String {
303
- switch abs(count) {
304
- case 1_000_000...: scaled(count, by: 1_000_000) + "M"
305
- case 1_000...: scaled(count, by: 1_000) + "K"
306
- default: count.formatted()
307
- }
308
- }
309
-
310
- private func scaled(_ count: Int, by divisor: Double) -> String {
311
- (Double(count) / divisor).formatted(.number.precision(.fractionLength(0...1)))
312
- }
313
- }
314
-
315
- extension FormatStyle where Self == CompactCountStyle {
316
- static var compactCount: CompactCountStyle { CompactCountStyle() }
317
- }
318
-
319
- let followers = 48_700.formatted(.compactCount) // "48.7K"
320
- ```
321
-
322
250
  The static member in the constrained extension is what enables the
323
251
  `.compactCount` dot syntax at call sites. (For real apps, `.notation(.compactName)`
324
252
  already does this with localized suffixes; a custom style earns its place when
325
253
  the rule is your own.)
326
254
 
255
+ Code for this section: [FormatStyle examples](references/formatstyle-examples.md).
256
+
327
257
  ## Common mistakes
328
258
 
329
259
  | Mistake | Fix |
@@ -349,6 +279,7 @@ the rule is your own.)
349
279
 
350
280
  ## References
351
281
 
282
+ - [FormatStyle examples](references/formatstyle-examples.md): open when formatting dates or durations beyond the quick reference, or when writing a custom FormatStyle.
352
283
  - [FormatStyle](https://developer.apple.com/documentation/foundation/formatstyle)
353
284
  - [IntegerFormatStyle](https://developer.apple.com/documentation/foundation/integerformatstyle)
354
285
  - [FloatingPointFormatStyle](https://developer.apple.com/documentation/foundation/floatingpointformatstyle)
@@ -0,0 +1,113 @@
1
+ # FormatStyle examples
2
+
3
+ <!-- toc -->
4
+ - [Dates](#dates)
5
+ - [Durations](#durations)
6
+ - [Custom FormatStyle](#custom-formatstyle)
7
+ <!-- /toc -->
8
+
9
+ Code for date, duration and custom FormatStyle formatting. SKILL.md keeps the quick reference and the locale rules.
10
+
11
+ ## Dates
12
+
13
+ Build exactly the fields you want; the locale decides order and punctuation.
14
+
15
+ ```swift
16
+ let launch = Date.now
17
+ launch.formatted(.dateTime.day().month().year()) // "Mar 3, 2026" (order comes from the locale)
18
+ launch.formatted(.dateTime.minute().hour()) // "4:05 PM"
19
+ let spelledOut = Date.FormatStyle.dateTime.day().month(.wide).weekday(.wide)
20
+ launch.formatted(spelledOut) // "Tuesday, March 3"
21
+ ```
22
+
23
+ Predefined combinations:
24
+
25
+ ```swift
26
+ launch.formatted(date: .long, time: .shortened) // "March 3, 2026 at 4:05 PM"
27
+ launch.formatted(date: .abbreviated, time: .omitted) // "Mar 3, 2026"
28
+ launch.formatted(.iso8601) // "2026-03-03T13:05:00Z"
29
+ ```
30
+
31
+ Relative to now:
32
+
33
+ ```swift
34
+ let dayBefore = Date.now.addingTimeInterval(-86_400)
35
+ dayBefore.formatted(.relative(presentation: .named)) // "yesterday"
36
+ let numericAgo = Date.RelativeFormatStyle(presentation: .numeric)
37
+ dayBefore.formatted(numericAgo) // "1 day ago"
38
+ ```
39
+
40
+ Ranges and countdowns:
41
+
42
+ ```swift
43
+ let slot = launch..<launch.addingTimeInterval(5_400)
44
+ let meetingSpan = Date.IntervalFormatStyle().day().month().minute().hour()
45
+ slot.formatted(meetingSpan) // "Mar 3, 4:05 - 5:35 PM" (ICU prints an en dash)
46
+
47
+ let untilDeparture = Date.now..<Date.now.addingTimeInterval(190_800)
48
+ let countdown = Date.ComponentsFormatStyle(style: .wide, fields: [.hour, .day])
49
+ untilDeparture.formatted(countdown) // "2 days, 5 hours"
50
+ ```
51
+
52
+ Related types: `Date.FormatStyle`, `Date.RelativeFormatStyle`,
53
+ `Date.IntervalFormatStyle`, `Date.ComponentsFormatStyle`.
54
+
55
+ ## Durations
56
+
57
+ A `Duration` (iOS 16+) can be shown as a clock reading with
58
+ `Duration.TimeFormatStyle` or as labeled units with `Duration.UnitsFormatStyle`.
59
+
60
+ ```swift
61
+ let ride = Duration.seconds(7_384) // 2 h 3 min 4 s
62
+ ride.formatted(.time(pattern: .hourMinuteSecond)) // "2:03:04"
63
+ ride.formatted(.time(pattern: .hourMinute)) // "2:03"
64
+ ride.formatted(.time(pattern: .minuteSecond)) // "123:04" (minutes are not wrapped into hours)
65
+
66
+ let stopwatch = Duration.TimeFormatStyle.Pattern.minuteSecond(padMinuteToLength: 2, fractionalSecondsLength: 2)
67
+ Duration.milliseconds(3_750).formatted(.time(pattern: stopwatch)) // "00:03.75"
68
+ ```
69
+
70
+ ```swift
71
+ let clock: Set<Duration.UnitsFormatStyle.Unit> = [.hours, .minutes, .seconds]
72
+ ride.formatted(.units(allowed: clock, width: .abbreviated)) // "2 hr, 3 min, 4 sec"
73
+ ride.formatted(.units(allowed: clock, width: .wide, maximumUnitCount: 1)) // "2 hours"
74
+
75
+ let rest = Duration.seconds(150)
76
+ rest.formatted(.units(allowed: [.minutes, .seconds], width: .wide)) // "2 minutes, 30 seconds"
77
+ rest.formatted(.units(allowed: [.minutes, .seconds], width: .narrow)) // "2m 30s"
78
+ ```
79
+
80
+ `maximumUnitCount` caps how many units appear.
81
+
82
+ ## Custom FormatStyle
83
+
84
+ Conform to `FormatStyle` and implement `format(_:)`. Add `ParseableFormatStyle`
85
+ if the text must also be read back. `FormatStyle` inherits `Codable` and
86
+ `Hashable`, so keep stored properties simple value types.
87
+
88
+ ```swift
89
+ struct CompactCountStyle: FormatStyle {
90
+ func format(_ count: Int) -> String {
91
+ switch abs(count) {
92
+ case 1_000_000...: scaled(count, by: 1_000_000) + "M"
93
+ case 1_000...: scaled(count, by: 1_000) + "K"
94
+ default: count.formatted()
95
+ }
96
+ }
97
+
98
+ private func scaled(_ count: Int, by divisor: Double) -> String {
99
+ (Double(count) / divisor).formatted(.number.precision(.fractionLength(0...1)))
100
+ }
101
+ }
102
+
103
+ extension FormatStyle where Self == CompactCountStyle {
104
+ static var compactCount: CompactCountStyle { CompactCountStyle() }
105
+ }
106
+
107
+ let followers = 48_700.formatted(.compactCount) // "48.7K"
108
+ ```
109
+
110
+ The static member in the constrained extension is what enables the
111
+ `.compactCount` dot syntax at call sites. (For real apps, `.notation(.compactName)`
112
+ already does this with localized suffixes; a custom style earns its place when
113
+ the rule is your own.)
@@ -299,41 +299,7 @@ can be dropped into a builder where that helps. More in
299
299
 
300
300
  ## Codable basics
301
301
 
302
- ```swift
303
- struct Venue: Codable {
304
- var venueName: String
305
- var seatCount: Int
306
- var isOutdoor: Bool
307
- var city: String
308
-
309
- enum CodingKeys: String, CodingKey {
310
- case venueName = "venue_name", seatCount = "seat_count", isOutdoor = "is_outdoor", location
311
- }
312
- enum LocationKeys: String, CodingKey { case city }
313
-
314
- init(from decoder: Decoder) throws {
315
- let c = try decoder.container(keyedBy: CodingKeys.self)
316
- venueName = try c.decode(String.self, forKey: .venueName)
317
- seatCount = try c.decodeIfPresent(Int.self, forKey: .seatCount) ?? 0
318
- if let flag = try? c.decode(Bool.self, forKey: .isOutdoor) {
319
- isOutdoor = flag
320
- } else {
321
- isOutdoor = (try c.decodeIfPresent(String.self, forKey: .isOutdoor)) == "true"
322
- }
323
- let place = try c.nestedContainer(keyedBy: LocationKeys.self, forKey: .location)
324
- city = try place.decode(String.self, forKey: .city)
325
- }
326
-
327
- func encode(to encoder: Encoder) throws {
328
- var c = encoder.container(keyedBy: CodingKeys.self)
329
- try c.encode(venueName, forKey: .venueName)
330
- try c.encode(seatCount, forKey: .seatCount)
331
- try c.encode(isOutdoor, forKey: .isOutdoor)
332
- var place = c.nestedContainer(keyedBy: LocationKeys.self, forKey: .location)
333
- try place.encode(city, forKey: .city)
334
- }
335
- }
336
- ```
302
+ Code: [Codable basics](references/code-examples.md#codable-basics).
337
303
 
338
304
  - A `CodingKeys: String, CodingKey` enum renames snake_case keys without a
339
305
  custom decoder.
@@ -379,27 +345,7 @@ let tagCounts = allTags.reduce(into: [:]) { tally, tag in tally[tag, default: 0]
379
345
  Prefer `.formatted()` to `DateFormatter` and `NumberFormatter`: it is typed,
380
346
  localized and short.
381
347
 
382
- ```swift
383
- import Foundation
384
-
385
- let now = Date()
386
- now.formatted()
387
- now.formatted(date: .abbreviated, time: .shortened)
388
- now.formatted(.dateTime.year().month().day())
389
- now.addingTimeInterval(-3600).formatted(.relative(presentation: .named))
390
-
391
- 19.99.formatted(.currency(code: "EUR"))
392
- 0.425.formatted(.percent)
393
- 42.5.formatted(.percent)
394
- 2_400_000.formatted(.number.notation(.compactName))
395
- Measurement(value: 12, unit: UnitLength.kilometers).formatted(.measurement(width: .abbreviated))
396
- Duration.seconds(4000).formatted(.time(pattern: .hourMinuteSecond))
397
- Int64(5_300_000).formatted(.byteCount(style: .file))
398
- ["oat", "rye", "spelt"].formatted(.list(type: .and))
399
-
400
- let cost = try Decimal("EUR 42.50", format: .currency(code: "EUR"))
401
- let day = try Date("Mar 4, 2026", strategy: .dateTime.month().day().year())
402
- ```
348
+ Code: [Formatting basics](references/code-examples.md#formatting-basics).
403
349
 
404
350
  `.percent` multiplies by 100, so `42.5` prints as `4,250%`; pass `0.425` for
405
351
  42.5%. `.compactName` turns 2,400,000 into `2.4M`. `Duration.formatted` needs
@@ -457,3 +403,4 @@ delimiter, so align the closing quotes with the text you want flush left.
457
403
  - [references/swift-attributes-interop.md](references/swift-attributes-interop.md):
458
404
  `@c`, module selectors, `@specialized`, `@inline(always)`, `@export`,
459
405
  `@section` and `@used`.
406
+ - [Code examples](references/code-examples.md): open for the full code behind Codable basics, Formatting basics.
@@ -0,0 +1,65 @@
1
+ # Swift Language Code Examples
2
+
3
+ Full code samples for the SKILL.md sections that link here. The rules and the decision guidance stay in SKILL.md; each heading below matches the SKILL.md section the code belongs to.
4
+
5
+ ## Codable basics
6
+
7
+ ```swift
8
+ struct Venue: Codable {
9
+ var venueName: String
10
+ var seatCount: Int
11
+ var isOutdoor: Bool
12
+ var city: String
13
+
14
+ enum CodingKeys: String, CodingKey {
15
+ case venueName = "venue_name", seatCount = "seat_count", isOutdoor = "is_outdoor", location
16
+ }
17
+ enum LocationKeys: String, CodingKey { case city }
18
+
19
+ init(from decoder: Decoder) throws {
20
+ let c = try decoder.container(keyedBy: CodingKeys.self)
21
+ venueName = try c.decode(String.self, forKey: .venueName)
22
+ seatCount = try c.decodeIfPresent(Int.self, forKey: .seatCount) ?? 0
23
+ if let flag = try? c.decode(Bool.self, forKey: .isOutdoor) {
24
+ isOutdoor = flag
25
+ } else {
26
+ isOutdoor = (try c.decodeIfPresent(String.self, forKey: .isOutdoor)) == "true"
27
+ }
28
+ let place = try c.nestedContainer(keyedBy: LocationKeys.self, forKey: .location)
29
+ city = try place.decode(String.self, forKey: .city)
30
+ }
31
+
32
+ func encode(to encoder: Encoder) throws {
33
+ var c = encoder.container(keyedBy: CodingKeys.self)
34
+ try c.encode(venueName, forKey: .venueName)
35
+ try c.encode(seatCount, forKey: .seatCount)
36
+ try c.encode(isOutdoor, forKey: .isOutdoor)
37
+ var place = c.nestedContainer(keyedBy: LocationKeys.self, forKey: .location)
38
+ try place.encode(city, forKey: .city)
39
+ }
40
+ }
41
+ ```
42
+
43
+ ## Formatting basics
44
+
45
+ ```swift
46
+ import Foundation
47
+
48
+ let now = Date()
49
+ now.formatted()
50
+ now.formatted(date: .abbreviated, time: .shortened)
51
+ now.formatted(.dateTime.year().month().day())
52
+ now.addingTimeInterval(-3600).formatted(.relative(presentation: .named))
53
+
54
+ 19.99.formatted(.currency(code: "EUR"))
55
+ 0.425.formatted(.percent)
56
+ 42.5.formatted(.percent)
57
+ 2_400_000.formatted(.number.notation(.compactName))
58
+ Measurement(value: 12, unit: UnitLength.kilometers).formatted(.measurement(width: .abbreviated))
59
+ Duration.seconds(4000).formatted(.time(pattern: .hourMinuteSecond))
60
+ Int64(5_300_000).formatted(.byteCount(style: .file))
61
+ ["oat", "rye", "spelt"].formatted(.list(type: .and))
62
+
63
+ let cost = try Decimal("EUR 42.50", format: .currency(code: "EUR"))
64
+ let day = try Date("Mar 4, 2026", strategy: .dateTime.month().day().year())
65
+ ```
@@ -6,6 +6,7 @@ metadata:
6
6
  source: "twostraws/Swift-Testing-Agent-Skill (MIT)"
7
7
  author: Paul Hudson
8
8
  version: "1.0"
9
+ not-for: swiftdata-pro
9
10
  ---
10
11
 
11
12
  Write and review Swift Testing code for correctness, modern API usage, and adherence to project conventions. Report only genuine problems - do not nitpick or invent issues.
@@ -41,47 +41,7 @@ reference semantics and a designated initializer. Model instances are not
41
41
  `Sendable`: to hand a model to another actor, pass its `PersistentIdentifier`
42
42
  (which is `Sendable`) and fetch it again from that actor's context.
43
43
 
44
- ```swift
45
- import SwiftData
46
- import Foundation
47
-
48
- @Model
49
- class Plant {
50
- var commonName: String
51
- var acquiredOn: Date
52
- var needsRepotting: Bool = false
53
- @Attribute(.externalStorage) var photo: Data?
54
- @Relationship(deleteRule: .cascade, inverse: \CareEvent.plant)
55
- var careEvents: [CareEvent] = []
56
- var bed: GardenBed?
57
- @Transient var isHighlighted: Bool = false
58
-
59
- init(commonName: String, acquiredOn: Date = .now) {
60
- self.commonName = commonName
61
- self.acquiredOn = acquiredOn
62
- }
63
- }
64
-
65
- @Model
66
- final class GardenBed {
67
- var label: String
68
- @Relationship(deleteRule: .nullify, inverse: \Plant.bed)
69
- var plants: [Plant] = []
70
- init(label: String) { self.label = label }
71
- }
72
-
73
- @Model
74
- final class CareEvent {
75
- var kind: String
76
- var loggedAt: Date
77
- var plant: Plant?
78
-
79
- init(kind: String, loggedAt: Date) {
80
- self.kind = kind
81
- self.loggedAt = loggedAt
82
- }
83
- }
84
- ```
44
+ Code: [Defining models](references/code-examples.md#defining-models).
85
45
 
86
46
  Rules that follow from the macro:
87
47
 
@@ -129,31 +89,9 @@ Indexes (`#Index`, iOS 18+) are covered in
129
89
 
130
90
  ## Container setup
131
91
 
132
- ```swift
133
- // Every model type the app stores, listed once.
134
- let simple = try ModelContainer(for: Plant.self, CareEvent.self, GardenBed.self)
135
-
136
- // Named store, shared with extensions, synced to a private CloudKit database.
137
- let config = ModelConfiguration(
138
- "Garden",
139
- isStoredInMemoryOnly: false,
140
- groupContainer: .identifier("group.example.garden"),
141
- cloudKitDatabase: .private("iCloud.example.garden")
142
- )
143
- let configured = try ModelContainer(for: Plant.self, configurations: config)
144
-
145
- // Versioned schema with a migration plan.
146
- let migrating = try ModelContainer(
147
- for: GardenSchemaV3.Plant.self,
148
- migrationPlan: GardenMigrationPlan.self
149
- )
150
-
151
- // Tests and previews: nothing touches disk.
152
- let scratch = try ModelContainer(
153
- for: Plant.self,
154
- configurations: ModelConfiguration(isStoredInMemoryOnly: true)
155
- )
156
- ```
92
+ List every stored model type once. Use a `ModelConfiguration` for a named, app-group or CloudKit-synced store, pass the versioned schema and migration plan when one exists, and use `isStoredInMemoryOnly: true` for tests and previews.
93
+
94
+ Code: [Container setup](references/code-examples.md#container-setup).
157
95
 
158
96
  ## CloudKit sync
159
97
 
@@ -312,62 +250,7 @@ try context.enumerate(sweep, batchSize: 1_000) { plant in
312
250
  Each shipped schema is an enum that conforms to `VersionedSchema` and nests its
313
251
  own model classes. The plan lists them oldest first and the stages between them.
314
252
 
315
- ```swift
316
- enum GardenSchemaV1: VersionedSchema {
317
- static let versionIdentifier = Schema.Version(1, 0, 0)
318
- static var models: [any PersistentModel.Type] { [Plant.self] }
319
-
320
- @Model final class Plant {
321
- var name: String
322
- init(name: String) { self.name = name }
323
- }
324
- }
325
-
326
- enum GardenSchemaV2: VersionedSchema {
327
- static let versionIdentifier = Schema.Version(2, 0, 0)
328
- static var models: [any PersistentModel.Type] { [Plant.self] }
329
-
330
- @Model final class Plant {
331
- @Attribute(originalName: "name") var commonName: String
332
- var sunlight: String = "partial"
333
- init(commonName: String) { self.commonName = commonName }
334
- }
335
- }
336
-
337
- enum GardenSchemaV3: VersionedSchema {
338
- static let versionIdentifier = Schema.Version(3, 0, 0)
339
- static var models: [any PersistentModel.Type] { [Plant.self] }
340
-
341
- @Model final class Plant {
342
- var commonName: String
343
- var sunlight: String = "partial"
344
- var sunlightHours: Int = 4
345
- init(commonName: String) { self.commonName = commonName }
346
- }
347
- }
348
-
349
- enum GardenMigrationPlan: SchemaMigrationPlan {
350
- static var schemas: [any VersionedSchema.Type] {
351
- [GardenSchemaV1.self, GardenSchemaV2.self, GardenSchemaV3.self]
352
- }
353
- static var stages: [MigrationStage] {
354
- [
355
- .lightweight(fromVersion: GardenSchemaV1.self, toVersion: GardenSchemaV2.self),
356
- .custom(
357
- fromVersion: GardenSchemaV2.self, toVersion: GardenSchemaV3.self,
358
- willMigrate: nil,
359
- didMigrate: { context in
360
- let plants = try context.fetch(FetchDescriptor<GardenSchemaV3.Plant>())
361
- for plant in plants {
362
- plant.sunlightHours = plant.sunlight == "full" ? 8 : 4
363
- }
364
- try context.save()
365
- }
366
- )
367
- ]
368
- }
369
- }
370
- ```
253
+ Code: [Schema versions and migration](references/code-examples.md#schema-versions-and-migration).
371
254
 
372
255
  A lightweight stage covers: new optional or defaulted properties, renames
373
256
  through `originalName`, removed properties, and new model types. Anything that
@@ -493,3 +376,4 @@ the main context. Shared preview containers and `PreviewModifier` traits are in
493
376
  predicate failures, what is supported, safe capture, debugging.
494
377
  - [references/indexing.md](references/indexing.md): `#Index`, compound indexes,
495
378
  when an index pays off, migration and verification.
379
+ - [Code examples](references/code-examples.md): open for the full code behind Defining models, Container setup, Schema versions and migration.