@softspark/ai-toolkit 1.0.0

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 (327) hide show
  1. package/AGENTS.md +412 -0
  2. package/CHANGELOG.md +68 -0
  3. package/LICENSE +21 -0
  4. package/README.md +632 -0
  5. package/action.yml +53 -0
  6. package/app/.claude-plugin/plugin.json +44 -0
  7. package/app/ARCHITECTURE.md +306 -0
  8. package/app/CLAUDE.md.template +23 -0
  9. package/app/agents/ai-engineer.md +128 -0
  10. package/app/agents/backend-specialist.md +193 -0
  11. package/app/agents/business-intelligence.md +54 -0
  12. package/app/agents/chaos-monkey.md +67 -0
  13. package/app/agents/chief-of-staff.md +51 -0
  14. package/app/agents/code-archaeologist.md +127 -0
  15. package/app/agents/code-reviewer.md +184 -0
  16. package/app/agents/command-expert.md +131 -0
  17. package/app/agents/data-analyst.md +205 -0
  18. package/app/agents/data-scientist.md +151 -0
  19. package/app/agents/database-architect.md +317 -0
  20. package/app/agents/debugger.md +238 -0
  21. package/app/agents/devops-implementer.md +194 -0
  22. package/app/agents/documenter.md +364 -0
  23. package/app/agents/explorer-agent.md +145 -0
  24. package/app/agents/fact-checker.md +172 -0
  25. package/app/agents/frontend-specialist.md +209 -0
  26. package/app/agents/game-developer.md +216 -0
  27. package/app/agents/incident-responder.md +226 -0
  28. package/app/agents/infrastructure-architect.md +127 -0
  29. package/app/agents/infrastructure-validator.md +247 -0
  30. package/app/agents/llm-ops-engineer.md +237 -0
  31. package/app/agents/mcp-expert.md +228 -0
  32. package/app/agents/mcp-server-architect.md +195 -0
  33. package/app/agents/mcp-testing-engineer.md +292 -0
  34. package/app/agents/meta-architect.md +58 -0
  35. package/app/agents/ml-engineer.md +136 -0
  36. package/app/agents/mobile-developer.md +190 -0
  37. package/app/agents/night-watchman.md +55 -0
  38. package/app/agents/nlp-engineer.md +154 -0
  39. package/app/agents/orchestrator.md +437 -0
  40. package/app/agents/performance-optimizer.md +254 -0
  41. package/app/agents/predictive-analyst.md +57 -0
  42. package/app/agents/product-manager.md +194 -0
  43. package/app/agents/project-planner.md +287 -0
  44. package/app/agents/prompt-engineer.md +103 -0
  45. package/app/agents/qa-automation-engineer.md +182 -0
  46. package/app/agents/rag-engineer.md +201 -0
  47. package/app/agents/research-synthesizer.md +138 -0
  48. package/app/agents/search-specialist.md +101 -0
  49. package/app/agents/security-architect.md +62 -0
  50. package/app/agents/security-auditor.md +293 -0
  51. package/app/agents/seo-specialist.md +111 -0
  52. package/app/agents/system-governor.md +57 -0
  53. package/app/agents/tech-lead.md +62 -0
  54. package/app/agents/technical-researcher.md +103 -0
  55. package/app/agents/test-engineer.md +264 -0
  56. package/app/constitution.md +38 -0
  57. package/app/hooks/_profile-check.sh +11 -0
  58. package/app/hooks/guard-destructive.sh +74 -0
  59. package/app/hooks/guard-path.sh +73 -0
  60. package/app/hooks/post-tool-use.sh +35 -0
  61. package/app/hooks/pre-compact.sh +31 -0
  62. package/app/hooks/quality-check.sh +22 -0
  63. package/app/hooks/quality-gate.sh +49 -0
  64. package/app/hooks/save-session.sh +24 -0
  65. package/app/hooks/session-end.sh +37 -0
  66. package/app/hooks/session-start.sh +29 -0
  67. package/app/hooks/subagent-start.sh +16 -0
  68. package/app/hooks/subagent-stop.sh +16 -0
  69. package/app/hooks/track-usage.sh +50 -0
  70. package/app/hooks/user-prompt-submit.sh +25 -0
  71. package/app/hooks.json +178 -0
  72. package/app/mcp-defaults.json +23 -0
  73. package/app/output-styles/golden-rules.md +43 -0
  74. package/app/plugins/README.md +19 -0
  75. package/app/plugins/csharp-pack/README.md +11 -0
  76. package/app/plugins/csharp-pack/plugin.json +18 -0
  77. package/app/plugins/enterprise-pack/README.md +16 -0
  78. package/app/plugins/enterprise-pack/hooks/output-style.sh +6 -0
  79. package/app/plugins/enterprise-pack/hooks/status-line.sh +8 -0
  80. package/app/plugins/enterprise-pack/plugin.json +24 -0
  81. package/app/plugins/frontend-pack/README.md +14 -0
  82. package/app/plugins/frontend-pack/plugin.json +22 -0
  83. package/app/plugins/java-pack/README.md +11 -0
  84. package/app/plugins/java-pack/plugin.json +18 -0
  85. package/app/plugins/kotlin-pack/README.md +11 -0
  86. package/app/plugins/kotlin-pack/plugin.json +18 -0
  87. package/app/plugins/memory-pack/README.md +24 -0
  88. package/app/plugins/memory-pack/hooks/observation-capture.sh +67 -0
  89. package/app/plugins/memory-pack/hooks/session-summary.sh +71 -0
  90. package/app/plugins/memory-pack/plugin.json +22 -0
  91. package/app/plugins/memory-pack/scripts/init_db.py +81 -0
  92. package/app/plugins/memory-pack/scripts/strip_private.py +22 -0
  93. package/app/plugins/memory-pack/skills/mem-search/SKILL.md +70 -0
  94. package/app/plugins/research-pack/README.md +14 -0
  95. package/app/plugins/research-pack/plugin.json +22 -0
  96. package/app/plugins/ruby-pack/README.md +11 -0
  97. package/app/plugins/ruby-pack/plugin.json +18 -0
  98. package/app/plugins/rust-pack/README.md +11 -0
  99. package/app/plugins/rust-pack/plugin.json +18 -0
  100. package/app/plugins/security-pack/README.md +15 -0
  101. package/app/plugins/security-pack/plugin.json +23 -0
  102. package/app/plugins/swift-pack/README.md +11 -0
  103. package/app/plugins/swift-pack/plugin.json +18 -0
  104. package/app/rules/claude-toolkit-rules.md +21 -0
  105. package/app/rules/git-conventions.md +5 -0
  106. package/app/rules/quality-gates.md +10 -0
  107. package/app/skills/_lib/__init__.py +1 -0
  108. package/app/skills/_lib/detect_utils.py +150 -0
  109. package/app/skills/agent-creator/SKILL.md +82 -0
  110. package/app/skills/analyze/SKILL.md +92 -0
  111. package/app/skills/analyze/scripts/complexity.py +165 -0
  112. package/app/skills/api-patterns/SKILL.md +305 -0
  113. package/app/skills/app-builder/SKILL.md +187 -0
  114. package/app/skills/architecture-audit/SKILL.md +141 -0
  115. package/app/skills/architecture-decision/SKILL.md +55 -0
  116. package/app/skills/architecture-decision/templates/adr-template.md +36 -0
  117. package/app/skills/biz-scan/SKILL.md +30 -0
  118. package/app/skills/briefing/SKILL.md +27 -0
  119. package/app/skills/build/SKILL.md +97 -0
  120. package/app/skills/build/scripts/detect-build.py +151 -0
  121. package/app/skills/chaos/SKILL.md +32 -0
  122. package/app/skills/ci/SKILL.md +77 -0
  123. package/app/skills/ci/scripts/ci-detect.py +135 -0
  124. package/app/skills/ci/templates/github-actions-node.yml +38 -0
  125. package/app/skills/ci/templates/github-actions-python.yml +42 -0
  126. package/app/skills/ci-cd-patterns/SKILL.md +299 -0
  127. package/app/skills/clean-code/SKILL.md +110 -0
  128. package/app/skills/clean-code/reference/dart.md +18 -0
  129. package/app/skills/clean-code/reference/go.md +23 -0
  130. package/app/skills/clean-code/reference/php.md +32 -0
  131. package/app/skills/clean-code/reference/python.md +180 -0
  132. package/app/skills/clean-code/reference/typescript.md +26 -0
  133. package/app/skills/command-creator/SKILL.md +83 -0
  134. package/app/skills/commit/SKILL.md +98 -0
  135. package/app/skills/commit/scripts/pre-commit-check.py +87 -0
  136. package/app/skills/commit/templates/conventional-commit.md +52 -0
  137. package/app/skills/csharp-patterns/SKILL.md +450 -0
  138. package/app/skills/database-patterns/SKILL.md +297 -0
  139. package/app/skills/debug/SKILL.md +154 -0
  140. package/app/skills/debug/scripts/error-parser.py +187 -0
  141. package/app/skills/debugging-tactics/SKILL.md +136 -0
  142. package/app/skills/deploy/SKILL.md +130 -0
  143. package/app/skills/deploy/scripts/pre_deploy_check.py +171 -0
  144. package/app/skills/deploy/templates/deployment-checklist.md +31 -0
  145. package/app/skills/design-an-interface/SKILL.md +105 -0
  146. package/app/skills/design-engineering/SKILL.md +260 -0
  147. package/app/skills/docker-devops/SKILL.md +303 -0
  148. package/app/skills/docs/SKILL.md +145 -0
  149. package/app/skills/docs/scripts/doc-inventory.py +176 -0
  150. package/app/skills/docs/templates/adr-template.md +36 -0
  151. package/app/skills/docs/templates/readme-template.md +67 -0
  152. package/app/skills/documentation-standards/SKILL.md +191 -0
  153. package/app/skills/ecommerce-patterns/SKILL.md +209 -0
  154. package/app/skills/evaluate/SKILL.md +132 -0
  155. package/app/skills/evolve/SKILL.md +27 -0
  156. package/app/skills/explain/SKILL.md +54 -0
  157. package/app/skills/explain/scripts/dependency-graph.py +215 -0
  158. package/app/skills/explore/SKILL.md +112 -0
  159. package/app/skills/explore/scripts/visualize.py +117 -0
  160. package/app/skills/fix/SKILL.md +78 -0
  161. package/app/skills/fix/scripts/error-classifier.py +191 -0
  162. package/app/skills/flutter-patterns/SKILL.md +254 -0
  163. package/app/skills/git-mastery/SKILL.md +70 -0
  164. package/app/skills/grill-me/SKILL.md +38 -0
  165. package/app/skills/health/SKILL.md +91 -0
  166. package/app/skills/health/scripts/health_check.py +162 -0
  167. package/app/skills/hive-mind/SKILL.md +56 -0
  168. package/app/skills/hook-creator/SKILL.md +107 -0
  169. package/app/skills/index/SKILL.md +74 -0
  170. package/app/skills/instinct-review/SKILL.md +77 -0
  171. package/app/skills/java-patterns/SKILL.md +442 -0
  172. package/app/skills/kotlin-patterns/SKILL.md +446 -0
  173. package/app/skills/lint/SKILL.md +103 -0
  174. package/app/skills/lint/scripts/detect-linters.py +112 -0
  175. package/app/skills/mcp-patterns/SKILL.md +270 -0
  176. package/app/skills/mem-search/SKILL.md +70 -0
  177. package/app/skills/migrate/SKILL.md +90 -0
  178. package/app/skills/migrate/scripts/migration-status.py +195 -0
  179. package/app/skills/migration-patterns/SKILL.md +260 -0
  180. package/app/skills/night-watch/SKILL.md +28 -0
  181. package/app/skills/observability-patterns/SKILL.md +203 -0
  182. package/app/skills/onboard/SKILL.md +76 -0
  183. package/app/skills/orchestrate/SKILL.md +86 -0
  184. package/app/skills/panic/SKILL.md +30 -0
  185. package/app/skills/performance-profiling/SKILL.md +59 -0
  186. package/app/skills/plan/SKILL.md +110 -0
  187. package/app/skills/plan/templates/plan-template.md +40 -0
  188. package/app/skills/plan-writing/SKILL.md +201 -0
  189. package/app/skills/plugin-creator/SKILL.md +78 -0
  190. package/app/skills/pr/SKILL.md +129 -0
  191. package/app/skills/pr/scripts/pr-summary.py +175 -0
  192. package/app/skills/prd-to-issues/SKILL.md +108 -0
  193. package/app/skills/prd-to-plan/SKILL.md +120 -0
  194. package/app/skills/predict/SKILL.md +30 -0
  195. package/app/skills/qa-session/SKILL.md +110 -0
  196. package/app/skills/rag-patterns/SKILL.md +203 -0
  197. package/app/skills/refactor/SKILL.md +124 -0
  198. package/app/skills/refactor/scripts/refactor-scan.py +210 -0
  199. package/app/skills/refactor-plan/SKILL.md +112 -0
  200. package/app/skills/repeat/SKILL.md +149 -0
  201. package/app/skills/research-mastery/SKILL.md +56 -0
  202. package/app/skills/review/SKILL.md +141 -0
  203. package/app/skills/review/scripts/diff-analyzer.py +170 -0
  204. package/app/skills/rollback/SKILL.md +87 -0
  205. package/app/skills/rollback/scripts/rollback_info.py +149 -0
  206. package/app/skills/ruby-patterns/SKILL.md +454 -0
  207. package/app/skills/rust-patterns/SKILL.md +446 -0
  208. package/app/skills/search/SKILL.md +64 -0
  209. package/app/skills/security-patterns/SKILL.md +91 -0
  210. package/app/skills/security-patterns/reference/authentication.md +37 -0
  211. package/app/skills/security-patterns/reference/authorization.md +22 -0
  212. package/app/skills/security-patterns/reference/input-validation.md +30 -0
  213. package/app/skills/security-patterns/reference/oauth-csrf-audit.md +131 -0
  214. package/app/skills/skill-creator/SKILL.md +154 -0
  215. package/app/skills/skill-creator/templates/dashboard/index.html +130 -0
  216. package/app/skills/skill-creator/templates/reasoning-engine/assets/example.json +12 -0
  217. package/app/skills/skill-creator/templates/reasoning-engine/search.py +110 -0
  218. package/app/skills/subagent-development/SKILL.md +225 -0
  219. package/app/skills/subagent-development/reference/code-quality-reviewer-prompt.md +145 -0
  220. package/app/skills/subagent-development/reference/implementer-prompt.md +118 -0
  221. package/app/skills/subagent-development/reference/spec-reviewer-prompt.md +100 -0
  222. package/app/skills/swarm/SKILL.md +81 -0
  223. package/app/skills/swift-patterns/SKILL.md +500 -0
  224. package/app/skills/tdd/SKILL.md +174 -0
  225. package/app/skills/tdd/reference/deep-modules.md +32 -0
  226. package/app/skills/tdd/reference/interface-design.md +32 -0
  227. package/app/skills/tdd/reference/mocking.md +52 -0
  228. package/app/skills/tdd/reference/refactoring.md +10 -0
  229. package/app/skills/tdd/reference/tests.md +59 -0
  230. package/app/skills/teams/SKILL.md +101 -0
  231. package/app/skills/test/SKILL.md +107 -0
  232. package/app/skills/test/scripts/detect-runner.py +113 -0
  233. package/app/skills/testing-patterns/SKILL.md +73 -0
  234. package/app/skills/testing-patterns/reference/flutter-testing.md +33 -0
  235. package/app/skills/testing-patterns/reference/go-testing.md +52 -0
  236. package/app/skills/testing-patterns/reference/php-phpunit.md +39 -0
  237. package/app/skills/testing-patterns/reference/python-pytest.md +228 -0
  238. package/app/skills/testing-patterns/reference/typescript-vitest.md +50 -0
  239. package/app/skills/triage-issue/SKILL.md +120 -0
  240. package/app/skills/typescript-patterns/SKILL.md +256 -0
  241. package/app/skills/ubiquitous-language/SKILL.md +74 -0
  242. package/app/skills/verification-before-completion/SKILL.md +108 -0
  243. package/app/skills/workflow/SKILL.md +250 -0
  244. package/app/skills/write-a-prd/SKILL.md +129 -0
  245. package/app/skills/write-a-prd/reference/visual-companion.md +78 -0
  246. package/app/skills/write-a-prd/scripts/frame-template.html +111 -0
  247. package/app/skills/write-a-prd/scripts/visual-server.cjs +79 -0
  248. package/app/templates/skill/generator/SKILL.md.template +40 -0
  249. package/app/templates/skill/knowledge/SKILL.md.template +52 -0
  250. package/app/templates/skill/linter/SKILL.md.template +34 -0
  251. package/app/templates/skill/reviewer/SKILL.md.template +51 -0
  252. package/app/templates/skill/workflow/SKILL.md.template +49 -0
  253. package/benchmarks/README.md +111 -0
  254. package/benchmarks/ecosystem-dashboard.json +148 -0
  255. package/benchmarks/ecosystem-harvest.json +148 -0
  256. package/benchmarks/results.json +38 -0
  257. package/benchmarks/run.py +351 -0
  258. package/bin/ai-toolkit.js +345 -0
  259. package/kb/best-practices/README.md +11 -0
  260. package/kb/howto/README.md +11 -0
  261. package/kb/procedures/maintenance-sop.md +306 -0
  262. package/kb/reference/agents-catalog.md +124 -0
  263. package/kb/reference/anti-pattern-registry-format.md +221 -0
  264. package/kb/reference/architecture-overview.md +232 -0
  265. package/kb/reference/benchmark-config.md +62 -0
  266. package/kb/reference/ci-integration.md +66 -0
  267. package/kb/reference/claude-ecosystem-benchmark-snapshot.md +80 -0
  268. package/kb/reference/claude-ecosystem-expansion-foundations.md +102 -0
  269. package/kb/reference/commands-catalog.md +21 -0
  270. package/kb/reference/distribution-model.md +63 -0
  271. package/kb/reference/global-install-model.md +56 -0
  272. package/kb/reference/hierarchical-override-pattern.md +200 -0
  273. package/kb/reference/hooks-catalog.md +306 -0
  274. package/kb/reference/integrations.md +88 -0
  275. package/kb/reference/language-packs.md +52 -0
  276. package/kb/reference/merge-friendly-install-model.md +58 -0
  277. package/kb/reference/plugin-pack-conventions.md +151 -0
  278. package/kb/reference/quick-wins-implementation-summary.md +70 -0
  279. package/kb/reference/skill-templates.md +50 -0
  280. package/kb/reference/skills-catalog.md +215 -0
  281. package/kb/reference/skills-unification.md +57 -0
  282. package/kb/reference/stats.md +69 -0
  283. package/kb/reference/sync.md +76 -0
  284. package/kb/troubleshooting/README.md +11 -0
  285. package/llms-full.txt +3068 -0
  286. package/llms.txt +39 -0
  287. package/package.json +75 -0
  288. package/scripts/_common.py +160 -0
  289. package/scripts/add_rule.py +50 -0
  290. package/scripts/benchmark_config.py +127 -0
  291. package/scripts/benchmark_ecosystem.py +288 -0
  292. package/scripts/check_deps.py +260 -0
  293. package/scripts/create_skill.py +118 -0
  294. package/scripts/doctor.py +504 -0
  295. package/scripts/eject.py +113 -0
  296. package/scripts/emission.py +256 -0
  297. package/scripts/evaluate_skills.py +260 -0
  298. package/scripts/frontmatter.py +58 -0
  299. package/scripts/generate_agents_md.py +91 -0
  300. package/scripts/generate_aider_conf.py +51 -0
  301. package/scripts/generate_cline.py +35 -0
  302. package/scripts/generate_copilot.py +30 -0
  303. package/scripts/generate_cursor_rules.py +35 -0
  304. package/scripts/generate_gemini.py +28 -0
  305. package/scripts/generate_llms_txt.py +164 -0
  306. package/scripts/generate_roo_modes.py +80 -0
  307. package/scripts/generate_windsurf.py +35 -0
  308. package/scripts/generator_base.py +140 -0
  309. package/scripts/harvest_ecosystem.py +50 -0
  310. package/scripts/inject_rule_cli.py +101 -0
  311. package/scripts/inject_section_cli.py +47 -0
  312. package/scripts/injection.py +180 -0
  313. package/scripts/install.py +236 -0
  314. package/scripts/install_git_hooks.py +71 -0
  315. package/scripts/install_steps/__init__.py +5 -0
  316. package/scripts/install_steps/ai_tools.py +261 -0
  317. package/scripts/install_steps/hooks.py +90 -0
  318. package/scripts/install_steps/markers.py +79 -0
  319. package/scripts/install_steps/symlinks.py +87 -0
  320. package/scripts/merge-hooks.py +192 -0
  321. package/scripts/plugin.py +642 -0
  322. package/scripts/plugin_schema.py +138 -0
  323. package/scripts/remove_rule.py +58 -0
  324. package/scripts/stats.py +81 -0
  325. package/scripts/sync.py +215 -0
  326. package/scripts/uninstall.py +292 -0
  327. package/scripts/validate.py +700 -0
@@ -0,0 +1,500 @@
1
+ ---
2
+ name: swift-patterns
3
+ description: "Loaded when user asks about Swift or iOS development patterns"
4
+ effort: medium
5
+ user-invocable: false
6
+ ---
7
+
8
+ # Swift / iOS Patterns
9
+
10
+ ## Project Structure
11
+
12
+ ### Swift Package (SPM)
13
+
14
+ ```
15
+ MyPackage/
16
+ ├── Package.swift
17
+ ├── Sources/
18
+ │ ├── MyLibrary/
19
+ │ └── MyExecutable/
20
+ ├── Tests/
21
+ │ └── MyLibraryTests/
22
+ └── Plugins/
23
+ ```
24
+
25
+ ```swift
26
+ // swift-tools-version: 5.10
27
+ import PackageDescription
28
+
29
+ let package = Package(
30
+ name: "MyPackage",
31
+ platforms: [.iOS(.v17), .macOS(.v14)],
32
+ products: [
33
+ .library(name: "MyLibrary", targets: ["MyLibrary"]),
34
+ ],
35
+ dependencies: [
36
+ .package(url: "https://github.com/apple/swift-algorithms", from: "1.2.0"),
37
+ ],
38
+ targets: [
39
+ .target(name: "MyLibrary",
40
+ dependencies: [.product(name: "Algorithms", package: "swift-algorithms")]),
41
+ .testTarget(name: "MyLibraryTests", dependencies: ["MyLibrary"]),
42
+ ]
43
+ )
44
+ ```
45
+
46
+ ### Xcode Project Layout
47
+
48
+ ```
49
+ MyApp/
50
+ ├── MyApp/
51
+ │ ├── App/ # Entry point, ContentView
52
+ │ ├── Features/ # Feature modules (Views, ViewModels, Models)
53
+ │ ├── Core/ # Networking, Storage, Extensions
54
+ │ └── Resources/ # Assets.xcassets, Info.plist
55
+ ├── MyAppTests/
56
+ └── MyAppUITests/
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Idioms / Code Style
62
+
63
+ ### Optionals
64
+
65
+ ```swift
66
+ // guard-let for early exit
67
+ func process(user: User?) {
68
+ guard let user else { return }
69
+ print(user.name)
70
+ }
71
+
72
+ // Optional chaining + nil coalescing
73
+ let name = user?.profile?.displayName ?? "Anonymous"
74
+
75
+ // map/flatMap on optionals
76
+ let length: Int? = optionalString.map { $0.count }
77
+ // Never force-unwrap in production: user!.name
78
+ ```
79
+
80
+ ### Protocol-Oriented Programming
81
+
82
+ ```swift
83
+ protocol Cacheable: Identifiable where ID: Hashable {
84
+ var cacheKey: String { get }
85
+ }
86
+
87
+ extension Cacheable where ID == String {
88
+ var cacheKey: String { id }
89
+ }
90
+ ```
91
+
92
+ ### Value Types vs Reference Types
93
+
94
+ Use structs by default (value semantics, thread-safe). Use classes when identity matters, shared mutable state is intentional, inheritance is needed, or ObjC interop is required.
95
+
96
+ ### Property Wrappers
97
+
98
+ ```swift
99
+ @propertyWrapper
100
+ struct Clamped<Value: Comparable> {
101
+ var wrappedValue: Value {
102
+ didSet { wrappedValue = min(max(wrappedValue, range.lowerBound), range.upperBound) }
103
+ }
104
+ let range: ClosedRange<Value>
105
+
106
+ init(wrappedValue: Value, _ range: ClosedRange<Value>) {
107
+ self.range = range
108
+ self.wrappedValue = min(max(wrappedValue, range.lowerBound), range.upperBound)
109
+ }
110
+ }
111
+
112
+ struct Volume {
113
+ @Clamped(0...100) var level: Int = 50
114
+ }
115
+ ```
116
+
117
+ ### Result Builders
118
+
119
+ ```swift
120
+ @resultBuilder
121
+ struct ArrayBuilder<Element> {
122
+ static func buildBlock(_ components: [Element]...) -> [Element] { components.flatMap { $0 } }
123
+ static func buildExpression(_ expression: Element) -> [Element] { [expression] }
124
+ static func buildOptional(_ component: [Element]?) -> [Element] { component ?? [] }
125
+ }
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Error Handling
131
+
132
+ ### throws / try / catch
133
+
134
+ ```swift
135
+ enum NetworkError: Error, LocalizedError {
136
+ case invalidURL
137
+ case timeout(seconds: Int)
138
+ case serverError(statusCode: Int)
139
+
140
+ var errorDescription: String? {
141
+ switch self {
142
+ case .invalidURL: "Invalid URL."
143
+ case .timeout(let s): "Timed out after \(s)s."
144
+ case .serverError(let code): "Server returned \(code)."
145
+ }
146
+ }
147
+ }
148
+
149
+ do {
150
+ let user = try fetchUser(id: "123")
151
+ } catch let error as NetworkError {
152
+ handleNetworkError(error)
153
+ } catch {
154
+ handleUnexpected(error)
155
+ }
156
+
157
+ let user = try? fetchUser(id: "123") // nil on error
158
+ ```
159
+
160
+ ### Result Type
161
+
162
+ ```swift
163
+ switch fetchData(from: url) {
164
+ case .success(let data): process(data)
165
+ case .failure(let error): showError(error)
166
+ }
167
+ ```
168
+
169
+ ### Typed Throws (Swift 6) and Async Throws
170
+
171
+ ```swift
172
+ func load() throws(DatabaseError) -> [Item] { /* compiler-enforced error type */ }
173
+
174
+ func fetchUser(id: String) async throws -> User {
175
+ let (data, response) = try await URLSession.shared.data(from: url)
176
+ guard let http = response as? HTTPURLResponse, http.statusCode == 200 else {
177
+ throw NetworkError.serverError(statusCode: 0)
178
+ }
179
+ return try JSONDecoder().decode(User.self, from: data)
180
+ }
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Testing
186
+
187
+ ### XCTest
188
+
189
+ ```swift
190
+ final class UserServiceTests: XCTestCase {
191
+ var sut: UserService!
192
+ var mockRepo: MockUserRepository!
193
+
194
+ override func setUp() {
195
+ mockRepo = MockUserRepository()
196
+ sut = UserService(repository: mockRepo)
197
+ }
198
+
199
+ func testFetchUser_success() async throws {
200
+ mockRepo.stubbedUser = User(id: "1", name: "Alice")
201
+ let user = try await sut.fetchUser(id: "1")
202
+ XCTAssertEqual(user.name, "Alice")
203
+ }
204
+
205
+ func testFetchUser_notFound_throws() async {
206
+ mockRepo.shouldFail = true
207
+ do {
208
+ _ = try await sut.fetchUser(id: "999")
209
+ XCTFail("Expected error")
210
+ } catch {
211
+ XCTAssertTrue(error is UserService.Error)
212
+ }
213
+ }
214
+ }
215
+ ```
216
+
217
+ ### Swift Testing Framework (Swift 6+)
218
+
219
+ ```swift
220
+ import Testing
221
+
222
+ @Suite("UserService")
223
+ struct UserServiceTests {
224
+ @Test("fetches user by ID")
225
+ func fetchUser() async throws {
226
+ let mockRepo = MockUserRepository()
227
+ mockRepo.stubbedUser = User(id: "1", name: "Alice")
228
+ let sut = UserService(repository: mockRepo)
229
+ let user = try await sut.fetchUser(id: "1")
230
+ #expect(user.name == "Alice")
231
+ }
232
+
233
+ @Test("throws on missing user", arguments: ["999", ""])
234
+ func fetchMissingUser(id: String) async {
235
+ let sut = UserService(repository: MockUserRepository())
236
+ await #expect(throws: UserService.Error.self) {
237
+ try await sut.fetchUser(id: id)
238
+ }
239
+ }
240
+ }
241
+ ```
242
+
243
+ ### Protocol-Based Mocking
244
+
245
+ ```swift
246
+ protocol UserRepository {
247
+ func fetch(id: String) async throws -> User
248
+ }
249
+
250
+ final class MockUserRepository: UserRepository {
251
+ var stubbedUser: User?
252
+ var shouldFail = false
253
+ private(set) var fetchCallCount = 0
254
+
255
+ func fetch(id: String) async throws -> User {
256
+ fetchCallCount += 1
257
+ if shouldFail { throw NSError(domain: "", code: 0) }
258
+ return stubbedUser ?? User(id: id, name: "Default")
259
+ }
260
+ }
261
+ ```
262
+
263
+ ### UI Testing
264
+
265
+ ```swift
266
+ func testLoginFlow() {
267
+ let app = XCUIApplication()
268
+ app.launchArguments = ["--uitesting"]
269
+ app.launch()
270
+ app.textFields["email"].tap()
271
+ app.textFields["email"].typeText("user@example.com")
272
+ app.secureTextFields["password"].typeText("pass")
273
+ app.buttons["Sign In"].tap()
274
+ XCTAssertTrue(app.staticTexts["Welcome"].waitForExistence(timeout: 5))
275
+ }
276
+ ```
277
+
278
+ ---
279
+
280
+ ## Common Frameworks
281
+
282
+ ### SwiftUI + @Observable (iOS 17+)
283
+
284
+ ```swift
285
+ @Observable
286
+ final class UserViewModel {
287
+ var users: [User] = []
288
+ var isLoading = false
289
+ private let service: UserService
290
+
291
+ init(service: UserService) { self.service = service }
292
+
293
+ func load() async {
294
+ isLoading = true
295
+ defer { isLoading = false }
296
+ users = (try? await service.fetchAll()) ?? []
297
+ }
298
+ }
299
+
300
+ struct UserListView: View {
301
+ @State private var vm: UserViewModel
302
+
303
+ init(service: UserService) {
304
+ _vm = State(initialValue: UserViewModel(service: service))
305
+ }
306
+
307
+ var body: some View {
308
+ NavigationStack {
309
+ List(vm.users) { user in
310
+ NavigationLink(value: user) { Text(user.name) }
311
+ }
312
+ .navigationTitle("Users")
313
+ .navigationDestination(for: User.self) { UserDetailView(user: $0) }
314
+ .task { await vm.load() }
315
+ }
316
+ }
317
+ }
318
+ ```
319
+
320
+ ### Combine
321
+
322
+ ```swift
323
+ class SearchVM: ObservableObject {
324
+ @Published var query = ""
325
+ @Published var results: [Item] = []
326
+ private var cancellables = Set<AnyCancellable>()
327
+
328
+ init(service: SearchService) {
329
+ $query
330
+ .debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
331
+ .removeDuplicates()
332
+ .filter { !$0.isEmpty }
333
+ .flatMap { service.search(query: $0) }
334
+ .receive(on: DispatchQueue.main)
335
+ .sink(receiveCompletion: { _ in },
336
+ receiveValue: { [weak self] in self?.results = $0 })
337
+ .store(in: &cancellables)
338
+ }
339
+ }
340
+ ```
341
+
342
+ ### Structured Concurrency
343
+
344
+ ```swift
345
+ func fetchAllProfiles(ids: [String]) async throws -> [Profile] {
346
+ try await withThrowingTaskGroup(of: Profile.self) { group in
347
+ for id in ids { group.addTask { try await fetchProfile(id: id) } }
348
+ return try await group.reduce(into: []) { $0.append($1) }
349
+ }
350
+ }
351
+
352
+ // AsyncStream for bridging callbacks
353
+ let locations = AsyncStream<Location> { continuation in
354
+ manager.onUpdate = { continuation.yield($0) }
355
+ continuation.onTermination = { _ in manager.stop() }
356
+ }
357
+ ```
358
+
359
+ ### SwiftData
360
+
361
+ ```swift
362
+ @Model
363
+ final class Item {
364
+ var title: String
365
+ var timestamp: Date
366
+ @Relationship(deleteRule: .cascade) var tags: [Tag]
367
+ init(title: String) { self.title = title; self.timestamp = .now; self.tags = [] }
368
+ }
369
+
370
+ struct ItemListView: View {
371
+ @Query(sort: \Item.timestamp, order: .reverse) private var items: [Item]
372
+ @Environment(\.modelContext) private var context
373
+
374
+ var body: some View {
375
+ List(items) { Text($0.title) }
376
+ }
377
+ }
378
+ ```
379
+
380
+ ### Vapor (Server-Side)
381
+
382
+ ```swift
383
+ app.get("users", ":id") { req async throws -> User in
384
+ guard let id = req.parameters.get("id", as: UUID.self) else { throw Abort(.badRequest) }
385
+ guard let user = try await User.find(id, on: req.db) else { throw Abort(.notFound) }
386
+ return user
387
+ }
388
+ ```
389
+
390
+ ---
391
+
392
+ ## Performance
393
+
394
+ ### Copy-on-Write
395
+
396
+ Array, String, Dictionary use COW automatically. For custom value types:
397
+
398
+ ```swift
399
+ struct LargeData {
400
+ private final class Storage { var buffer: [UInt8]; init(_ b: [UInt8]) { buffer = b } }
401
+ private var storage: Storage
402
+
403
+ var buffer: [UInt8] {
404
+ get { storage.buffer }
405
+ set {
406
+ if !isKnownUniquelyReferenced(&storage) { storage = Storage(newValue) }
407
+ else { storage.buffer = newValue }
408
+ }
409
+ }
410
+ }
411
+ ```
412
+
413
+ ### ARC Retain Cycles
414
+
415
+ ```swift
416
+ // weak — closure may outlive self
417
+ service.fetch { [weak self] result in
418
+ guard let self else { return }
419
+ self.update(with: result)
420
+ }
421
+
422
+ // unowned — self guaranteed to outlive closure
423
+ lazy var tick: () -> Void = { [unowned self] in self.count += 1 }
424
+ ```
425
+
426
+ ### Sendable and Actors
427
+
428
+ ```swift
429
+ struct Config: Sendable { let apiURL: URL; let timeout: TimeInterval }
430
+
431
+ actor ImageCache {
432
+ private var cache: [URL: Data] = [:]
433
+ func image(for url: URL) -> Data? { cache[url] }
434
+ func store(_ data: Data, for url: URL) { cache[url] = data }
435
+ }
436
+ ```
437
+
438
+ ### Instruments
439
+
440
+ | Instrument | Use For |
441
+ |---|---|
442
+ | Time Profiler | CPU bottlenecks |
443
+ | Allocations | Memory growth |
444
+ | Leaks | Retain cycles |
445
+ | SwiftUI | View body re-evaluations |
446
+ | Core Animation | FPS, offscreen rendering |
447
+
448
+ Profile on device (not simulator). Use `os_signpost` for custom spans.
449
+
450
+ ---
451
+
452
+ ## Build / Package Management
453
+
454
+ ### SPM Commands
455
+
456
+ ```bash
457
+ swift package resolve # Resolve deps
458
+ swift build -c release # Release build
459
+ swift test --filter MyTests # Filtered test run
460
+ ```
461
+
462
+ ### xcconfig
463
+
464
+ ```
465
+ // Shared.xcconfig
466
+ SWIFT_VERSION = 5.10
467
+ IPHONEOS_DEPLOYMENT_TARGET = 17.0
468
+ SWIFT_STRICT_CONCURRENCY = complete
469
+
470
+ // Debug.xcconfig
471
+ #include "Shared.xcconfig"
472
+ SWIFT_OPTIMIZATION_LEVEL = -Onone
473
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG
474
+
475
+ // Release.xcconfig
476
+ #include "Shared.xcconfig"
477
+ SWIFT_OPTIMIZATION_LEVEL = -O
478
+ SWIFT_COMPILATION_MODE = wholemodule
479
+ ```
480
+
481
+ ### Tuist
482
+
483
+ Define targets in `Project.swift` using `ProjectDescription`. Map each app, framework, and test target with `bundleId`, `sources`, and `dependencies`. Use `.external(name:)` for SPM deps and `.target(name:)` for internal.
484
+
485
+ Schemes: separate Debug/Release/Testing. Enable ASan + TSan in test schemes.
486
+
487
+ ---
488
+
489
+ ## Anti-Patterns
490
+
491
+ | Anti-Pattern | Problem | Fix |
492
+ |---|---|---|
493
+ | Force unwrap `!` | Runtime crash | `guard let`, `if let`, `??` |
494
+ | Massive view controller | Untestable | MVVM, composable views |
495
+ | Stringly-typed APIs | No compiler checks | Enums, phantom types |
496
+ | Ignoring `@MainActor` | Off-main-thread UI | Annotate view models |
497
+ | Retain cycles | Memory leaks | `[weak self]` / `[unowned self]` |
498
+ | Blocking main thread | UI freezes | `async/await`, `Task { }` |
499
+ | `UserDefaults` for secrets | Insecure | Keychain (`SecItemAdd`) |
500
+ | `@ObservedObject` for owned state | Object recreated | `@StateObject` or `@State` + `@Observable` |
@@ -0,0 +1,174 @@
1
+ ---
2
+ name: tdd
3
+ description: "Test-driven development with red-green-refactor loop and vertical slices. Use when user wants TDD, test-first development, red-green-refactor, or building features with tests driving the implementation."
4
+ user-invocable: true
5
+ effort: high
6
+ argument-hint: "[feature or behavior to implement]"
7
+ allowed-tools: Read, Write, Edit, Grep, Glob, Bash, Agent
8
+ ---
9
+
10
+ # Test-Driven Development
11
+
12
+ $ARGUMENTS
13
+
14
+ Build features using strict RED → GREEN → REFACTOR cycles with vertical slices.
15
+
16
+ ## Usage
17
+
18
+ ```
19
+ /tdd [feature or behavior to implement]
20
+ ```
21
+
22
+ ## The Iron Law
23
+
24
+ ```
25
+ NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
26
+ ```
27
+
28
+ Write code before the test? **Delete it. Start over.**
29
+
30
+ **No exceptions:**
31
+ - Don't keep it as "reference"
32
+ - Don't "adapt" it while writing tests
33
+ - Don't look at it
34
+ - Delete means delete
35
+
36
+ Implement fresh from tests. Period.
37
+
38
+ **Violating the letter of this rule is violating the spirit of this rule.**
39
+
40
+ ## Philosophy
41
+
42
+ **Core principle**: Tests verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't.
43
+
44
+ **Good tests**: Integration-style, exercise real code paths through public APIs. Describe _what_ the system does, not _how_. Read like specifications. Survive refactors.
45
+
46
+ **Bad tests**: Coupled to implementation. Mock internal collaborators, test private methods, verify through external means. Warning sign: test breaks on refactor but behavior is unchanged.
47
+
48
+ See [reference/tests.md](reference/tests.md) for examples, [reference/mocking.md](reference/mocking.md) for mocking guidelines.
49
+
50
+ ## Anti-Pattern: Horizontal Slices
51
+
52
+ **DO NOT write all tests first, then all implementation.**
53
+
54
+ ```
55
+ WRONG (horizontal):
56
+ RED: test1, test2, test3, test4, test5
57
+ GREEN: impl1, impl2, impl3, impl4, impl5
58
+
59
+ RIGHT (vertical):
60
+ RED→GREEN: test1→impl1
61
+ RED→GREEN: test2→impl2
62
+ RED→GREEN: test3→impl3
63
+ ```
64
+
65
+ Tests written in bulk test _imagined_ behavior. Vertical slices let each test respond to what you learned from the previous cycle.
66
+
67
+ ## Workflow
68
+
69
+ ### 1. Planning
70
+
71
+ Before writing any code:
72
+
73
+ - [ ] Confirm with user what interface changes are needed
74
+ - [ ] Confirm which behaviors to test (prioritize — you can't test everything)
75
+ - [ ] Identify opportunities for [deep modules](reference/deep-modules.md)
76
+ - [ ] Design interfaces for [testability](reference/interface-design.md)
77
+ - [ ] List behaviors to test (not implementation steps)
78
+ - [ ] Get user approval
79
+
80
+ ### 2. Tracer Bullet
81
+
82
+ Write ONE test that confirms ONE thing:
83
+
84
+ ```
85
+ RED: Write test for first behavior → test fails
86
+ GREEN: Write minimal code to pass → test passes
87
+ ```
88
+
89
+ This proves the path works end-to-end.
90
+
91
+ ### 3. Incremental Loop
92
+
93
+ For each remaining behavior:
94
+
95
+ ```
96
+ RED: Write next test → fails
97
+ GREEN: Minimal code to pass → passes
98
+ ```
99
+
100
+ | Rule | Description |
101
+ |------|-------------|
102
+ | One at a time | One test per cycle |
103
+ | Minimal | Only enough code to pass current test |
104
+ | No anticipation | Don't code for future tests |
105
+ | Behavioral | Tests focus on observable behavior |
106
+
107
+ ### 4. Refactor
108
+
109
+ After all tests pass, look for [refactor candidates](reference/refactoring.md):
110
+
111
+ - [ ] Extract duplication
112
+ - [ ] Deepen modules (complexity behind simple interfaces)
113
+ - [ ] Apply SOLID where natural
114
+ - [ ] Run tests after each refactor step
115
+
116
+ **Never refactor while RED.** Get to GREEN first.
117
+
118
+ ## Checklist Per Cycle
119
+
120
+ ```
121
+ [ ] Test describes behavior, not implementation
122
+ [ ] Test uses public interface only
123
+ [ ] Test would survive internal refactor
124
+ [ ] Code is minimal for this test
125
+ [ ] No speculative features added
126
+ ```
127
+
128
+ ## Rules
129
+
130
+ - One RED→GREEN cycle at a time — never batch
131
+ - Tests assert on observable outcomes, not internal state
132
+ - Mock only at system boundaries (see [reference/mocking.md](reference/mocking.md))
133
+ - Each cycle leaves the codebase in a working state
134
+
135
+ ## Red Flags — STOP and Start Over
136
+
137
+ If you catch yourself doing ANY of these, **delete the code and restart with TDD**:
138
+
139
+ - Writing production code before a failing test
140
+ - Writing tests after implementation
141
+ - Test passes immediately (you're testing existing behavior — fix the test)
142
+ - Can't explain why the test failed
143
+ - Tests added "later"
144
+ - Rationalizing "just this once"
145
+ - "I already manually tested it"
146
+ - "Keep as reference" or "adapt existing code"
147
+
148
+ ## Common Rationalizations
149
+
150
+ | Excuse | Reality |
151
+ |--------|---------|
152
+ | "Too simple to test" | Simple code breaks. Test takes 30 seconds. |
153
+ | "I'll test after" | Tests passing immediately prove nothing. |
154
+ | "Tests after achieve same goals" | Tests-after = "what does this do?" Tests-first = "what should this do?" |
155
+ | "Already manually tested" | Ad-hoc ≠ systematic. No record, can't re-run. |
156
+ | "Deleting X hours is wasteful" | Sunk cost fallacy. Keeping unverified code is technical debt. |
157
+ | "Need to explore first" | Fine. Throw away exploration, start with TDD. |
158
+ | "TDD will slow me down" | TDD faster than debugging. Pragmatic = test-first. |
159
+ | "This is different because..." | No. Apply the Iron Law. |
160
+
161
+ ## Verification Checklist
162
+
163
+ Before marking work complete:
164
+
165
+ - [ ] Every new function/method has a test
166
+ - [ ] Watched each test fail before implementing
167
+ - [ ] Each test failed for expected reason (feature missing, not typo)
168
+ - [ ] Wrote minimal code to pass each test
169
+ - [ ] All tests pass
170
+ - [ ] Output pristine (no errors, warnings)
171
+ - [ ] Tests use real code (mocks only at system boundaries)
172
+ - [ ] Edge cases and errors covered
173
+
174
+ Can't check all boxes? You skipped TDD. Start over.
@@ -0,0 +1,32 @@
1
+ # Deep Modules
2
+
3
+ From "A Philosophy of Software Design" (John Ousterhout):
4
+
5
+ **Deep module** = small interface + lots of implementation
6
+
7
+ ```
8
+ ┌─────────────────────┐
9
+ │ Small Interface │ ← Few methods, simple params
10
+ ├─────────────────────┤
11
+ │ │
12
+ │ │
13
+ │ Deep Implementation│ ← Complex logic hidden
14
+ │ │
15
+ │ │
16
+ └─────────────────────┘
17
+ ```
18
+
19
+ **Shallow module** = large interface + little implementation (avoid)
20
+
21
+ ```
22
+ ┌─────────────────────────────────┐
23
+ │ Large Interface │ ← Many methods, complex params
24
+ ├─────────────────────────────────┤
25
+ │ Thin Implementation │ ← Just passes through
26
+ └─────────────────────────────────┘
27
+ ```
28
+
29
+ When designing interfaces, ask:
30
+ - Can I reduce the number of methods?
31
+ - Can I simplify the parameters?
32
+ - Can I hide more complexity inside?