@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,450 @@
1
+ ---
2
+ name: csharp-patterns
3
+ description: "Loaded when user asks about C# or .NET development patterns"
4
+ effort: medium
5
+ user-invocable: false
6
+ ---
7
+
8
+ # C# / .NET Patterns
9
+
10
+ ## Project Structure
11
+
12
+ ### Solution Layout
13
+ ```
14
+ MyApp.sln
15
+ Directory.Build.props # Shared build properties
16
+ Directory.Packages.props # Central package management
17
+ src/
18
+ MyApp.Api/ # ASP.NET Core host (Controllers, Middleware, Program.cs)
19
+ MyApp.Application/ # Use cases, MediatR handlers, Behaviors
20
+ MyApp.Domain/ # Entities, value objects, domain events
21
+ MyApp.Infrastructure/ # EF Core, external services
22
+ tests/
23
+ MyApp.UnitTests/
24
+ MyApp.IntegrationTests/
25
+ ```
26
+
27
+ ### Directory.Build.props
28
+ ```xml
29
+ <Project>
30
+ <PropertyGroup>
31
+ <TargetFramework>net9.0</TargetFramework>
32
+ <Nullable>enable</Nullable>
33
+ <ImplicitUsings>enable</ImplicitUsings>
34
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
35
+ <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
36
+ <AnalysisLevel>latest-recommended</AnalysisLevel>
37
+ </PropertyGroup>
38
+ </Project>
39
+ ```
40
+
41
+ ### Central Package Management (Directory.Packages.props)
42
+ ```xml
43
+ <Project>
44
+ <PropertyGroup>
45
+ <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
46
+ </PropertyGroup>
47
+ <ItemGroup>
48
+ <PackageVersion Include="MediatR" Version="12.4.1" />
49
+ <PackageVersion Include="FluentValidation" Version="11.11.0" />
50
+ <PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
51
+ </ItemGroup>
52
+ </Project>
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Idioms / Code Style
58
+
59
+ ### Nullable Reference Types
60
+ ```csharp
61
+ public class Order
62
+ {
63
+ public required string Id { get; init; }
64
+ public string? Notes { get; set; } // explicitly nullable
65
+ public required Customer Customer { get; init; } // never null
66
+ public string Summary => $"Order {Id}: {Notes ?? "no notes"}";
67
+ }
68
+ ```
69
+
70
+ ### Records
71
+ ```csharp
72
+ public record Money(decimal Amount, string Currency)
73
+ {
74
+ public Money Add(Money other) => Currency != other.Currency
75
+ ? throw new InvalidOperationException("Currency mismatch")
76
+ : this with { Amount = Amount + other.Amount };
77
+ }
78
+
79
+ public record CreateOrderRequest(string CustomerId, List<OrderLineDto> Lines);
80
+ public record OrderLineDto(string ProductId, int Quantity);
81
+ ```
82
+
83
+ ### Pattern Matching
84
+ ```csharp
85
+ public decimal CalculateDiscount(Customer c) => c switch
86
+ {
87
+ { Tier: CustomerTier.Gold, TotalSpent: > 10_000m } => 0.20m,
88
+ { Tier: CustomerTier.Gold } => 0.15m,
89
+ { Tier: CustomerTier.Silver } => 0.10m,
90
+ { IsNewCustomer: true } => 0.05m,
91
+ _ => 0m
92
+ };
93
+
94
+ // List patterns (.NET 8+)
95
+ public string Describe(int[] v) => v switch
96
+ {
97
+ [] => "empty", [var x] => $"one: {x}", [var f, .., var l] => $"{f}..{l}",
98
+ };
99
+ ```
100
+
101
+ ### LINQ
102
+ ```csharp
103
+ var activeUsers = users
104
+ .Where(u => u.IsActive)
105
+ .OrderByDescending(u => u.LastLogin)
106
+ .Select(u => new UserDto(u.Id, u.Name))
107
+ .ToList();
108
+ ```
109
+
110
+ ### Async/Await
111
+ ```csharp
112
+ // Always: Async suffix, CancellationToken parameter, never .Result/.Wait()
113
+ public async Task<Order?> GetOrderAsync(string id, CancellationToken ct = default)
114
+ => await _db.Orders.Include(o => o.Lines).FirstOrDefaultAsync(o => o.Id == id, ct);
115
+
116
+ // Parallel independent tasks
117
+ var ordersTask = _orderRepo.GetRecentAsync(ct);
118
+ var statsTask = _statsService.ComputeAsync(ct);
119
+ await Task.WhenAll(ordersTask, statsTask);
120
+ ```
121
+
122
+ ### Primary Constructors (C# 12)
123
+ ```csharp
124
+ public class OrderService(IOrderRepository repo, ILogger<OrderService> logger, IPublisher pub)
125
+ {
126
+ public async Task<Order> CreateAsync(CreateOrderRequest req, CancellationToken ct)
127
+ {
128
+ logger.LogInformation("Creating order for {CustomerId}", req.CustomerId);
129
+ var order = Order.Create(req);
130
+ await repo.AddAsync(order, ct);
131
+ await pub.Publish(new OrderCreatedEvent(order.Id), ct);
132
+ return order;
133
+ }
134
+ }
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Error Handling
140
+
141
+ ### Result Pattern
142
+ ```csharp
143
+ public sealed class Result<T>
144
+ {
145
+ public T? Value { get; }
146
+ public Error? Error { get; }
147
+ public bool IsSuccess => Error is null;
148
+ private Result(T value) => Value = value;
149
+ private Result(Error error) => Error = error;
150
+ public static Result<T> Success(T value) => new(value);
151
+ public static Result<T> Failure(Error error) => new(error);
152
+ public TOut Match<TOut>(Func<T, TOut> ok, Func<Error, TOut> err) =>
153
+ IsSuccess ? ok(Value!) : err(Error!);
154
+ }
155
+ public record Error(string Code, string Message);
156
+ ```
157
+
158
+ ### FluentValidation + MediatR Pipeline
159
+ ```csharp
160
+ public class CreateOrderValidator : AbstractValidator<CreateOrderRequest>
161
+ {
162
+ public CreateOrderValidator()
163
+ {
164
+ RuleFor(x => x.CustomerId).NotEmpty().MaximumLength(36);
165
+ RuleForEach(x => x.Lines).ChildRules(line =>
166
+ {
167
+ line.RuleFor(l => l.ProductId).NotEmpty();
168
+ line.RuleFor(l => l.Quantity).GreaterThan(0).LessThanOrEqualTo(1000);
169
+ });
170
+ }
171
+ }
172
+
173
+ public class ValidationBehavior<TReq, TRes>(IEnumerable<IValidator<TReq>> validators)
174
+ : IPipelineBehavior<TReq, TRes> where TReq : IRequest<TRes>
175
+ {
176
+ public async Task<TRes> Handle(TReq req, RequestHandlerDelegate<TRes> next, CancellationToken ct)
177
+ {
178
+ var failures = validators.Select(v => v.Validate(req)).SelectMany(r => r.Errors).ToList();
179
+ return failures.Count > 0 ? throw new ValidationException(failures) : await next();
180
+ }
181
+ }
182
+ ```
183
+
184
+ ### IAsyncDisposable
185
+ ```csharp
186
+ public sealed class TempFileHandle(string path) : IAsyncDisposable
187
+ {
188
+ public async ValueTask DisposeAsync()
189
+ {
190
+ if (File.Exists(path)) await Task.Run(() => File.Delete(path));
191
+ }
192
+ }
193
+ // Usage: await using var handle = new TempFileHandle("/tmp/export.csv");
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Testing Patterns
199
+
200
+ ### xUnit + NSubstitute + FluentAssertions
201
+ ```csharp
202
+ public class OrderServiceTests
203
+ {
204
+ private readonly IOrderRepository _repo = Substitute.For<IOrderRepository>();
205
+ private readonly IPublisher _pub = Substitute.For<IPublisher>();
206
+ private readonly OrderService _sut;
207
+ public OrderServiceTests() => _sut = new(_repo, Substitute.For<ILogger<OrderService>>(), _pub);
208
+
209
+ [Fact]
210
+ public async Task CreateAsync_ValidRequest_ReturnsOrder()
211
+ {
212
+ var order = await _sut.CreateAsync(new("cust-1", [new("prod-1", 2)]), CancellationToken.None);
213
+ order.Should().NotBeNull();
214
+ order.Lines.Should().ContainSingle().Which.Quantity.Should().Be(2);
215
+ await _repo.Received(1).AddAsync(Arg.Any<Order>(), Arg.Any<CancellationToken>());
216
+ }
217
+
218
+ [Theory]
219
+ [InlineData(0)]
220
+ [InlineData(-1)]
221
+ public async Task CreateAsync_InvalidQuantity_Throws(int qty)
222
+ {
223
+ var act = () => _sut.CreateAsync(new("cust-1", [new("prod-1", qty)]), CancellationToken.None);
224
+ await act.Should().ThrowAsync<ValidationException>();
225
+ }
226
+ }
227
+ ```
228
+
229
+ ### WebApplicationFactory (Integration)
230
+ ```csharp
231
+ public class OrdersApiTests(WebApplicationFactory<Program> factory)
232
+ : IClassFixture<WebApplicationFactory<Program>>
233
+ {
234
+ [Fact]
235
+ public async Task PostOrder_Returns201()
236
+ {
237
+ var client = factory.WithWebHostBuilder(b => b.ConfigureServices(s =>
238
+ {
239
+ s.RemoveAll<DbContext>();
240
+ s.AddDbContext<AppDbContext>(o => o.UseInMemoryDatabase("test"));
241
+ })).CreateClient();
242
+
243
+ var response = await client.PostAsJsonAsync("/api/orders",
244
+ new { CustomerId = "cust-1", Lines = new[] { new { ProductId = "prod-1", Quantity = 2 } } });
245
+ response.StatusCode.Should().Be(HttpStatusCode.Created);
246
+ }
247
+ }
248
+ ```
249
+
250
+ ### Testcontainers
251
+ ```csharp
252
+ public class PostgresFixture : IAsyncLifetime
253
+ {
254
+ private readonly PostgreSqlContainer _pg = new PostgreSqlBuilder().WithDatabase("testdb").Build();
255
+ public string ConnectionString => _pg.GetConnectionString();
256
+ public Task InitializeAsync() => _pg.StartAsync();
257
+ public Task DisposeAsync() => _pg.DisposeAsync().AsTask();
258
+ }
259
+ ```
260
+
261
+ ---
262
+
263
+ ## Common Frameworks
264
+
265
+ ### ASP.NET Core Minimal API
266
+ ```csharp
267
+ var builder = WebApplication.CreateBuilder(args);
268
+ builder.Services.AddEndpointsApiExplorer();
269
+ builder.Services.AddSwaggerGen();
270
+ builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));
271
+ var app = builder.Build();
272
+
273
+ app.MapGet("/api/orders/{id}", async (string id, ISender sender, CancellationToken ct) =>
274
+ await sender.Send(new GetOrderQuery(id), ct) is { } order ? Results.Ok(order) : Results.NotFound());
275
+
276
+ app.MapPost("/api/orders", async (CreateOrderRequest req, ISender sender, CancellationToken ct) =>
277
+ (await sender.Send(new CreateOrderCommand(req), ct)).Match(
278
+ o => Results.Created($"/api/orders/{o.Id}", o),
279
+ e => Results.Problem(e.Message, statusCode: 400)));
280
+ app.Run();
281
+ ```
282
+
283
+ ### Entity Framework Core
284
+ ```csharp
285
+ public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
286
+ {
287
+ public DbSet<Order> Orders => Set<Order>();
288
+ protected override void OnModelCreating(ModelBuilder mb)
289
+ {
290
+ mb.Entity<Order>(b =>
291
+ {
292
+ b.HasKey(o => o.Id);
293
+ b.Property(o => o.Id).HasMaxLength(36);
294
+ b.HasMany(o => o.Lines).WithOne().HasForeignKey(l => l.OrderId);
295
+ b.HasIndex(o => o.CustomerId);
296
+ b.Property(o => o.Total).HasPrecision(18, 2);
297
+ });
298
+ mb.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);
299
+ }
300
+ }
301
+ ```
302
+
303
+ ### MediatR (CQRS)
304
+ ```csharp
305
+ public record CreateOrderCommand(CreateOrderRequest Request) : IRequest<Result<Order>>;
306
+
307
+ public class CreateOrderHandler(IOrderRepository repo, IPublisher pub)
308
+ : IRequestHandler<CreateOrderCommand, Result<Order>>
309
+ {
310
+ public async Task<Result<Order>> Handle(CreateOrderCommand cmd, CancellationToken ct)
311
+ {
312
+ var order = Order.Create(cmd.Request);
313
+ await repo.AddAsync(order, ct);
314
+ await pub.Publish(new OrderCreatedEvent(order.Id), ct);
315
+ return Result<Order>.Success(order);
316
+ }
317
+ }
318
+ ```
319
+
320
+ ### Polly (Resilience)
321
+ ```csharp
322
+ builder.Services.AddHttpClient("Payments", c => c.BaseAddress = new Uri("https://api.payments.com"))
323
+ .AddResilienceHandler("default", p =>
324
+ {
325
+ p.AddRetry(new() { MaxRetryAttempts = 3, Delay = TimeSpan.FromMilliseconds(500),
326
+ BackoffType = DelayBackoffType.Exponential,
327
+ ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
328
+ .HandleResult(r => r.StatusCode >= HttpStatusCode.InternalServerError) });
329
+ p.AddCircuitBreaker(new() { FailureRatio = 0.5, SamplingDuration = TimeSpan.FromSeconds(30),
330
+ BreakDuration = TimeSpan.FromSeconds(15) });
331
+ p.AddTimeout(TimeSpan.FromSeconds(5));
332
+ });
333
+ ```
334
+
335
+ ### MassTransit (Messaging)
336
+ ```csharp
337
+ builder.Services.AddMassTransit(x =>
338
+ {
339
+ x.AddConsumer<OrderCreatedConsumer>();
340
+ x.UsingRabbitMq((ctx, cfg) => { cfg.Host("rabbitmq://localhost"); cfg.ConfigureEndpoints(ctx); });
341
+ });
342
+ ```
343
+
344
+ ---
345
+
346
+ ## Performance Tips
347
+
348
+ ### Span<T> -- Zero-Allocation Parsing
349
+ ```csharp
350
+ public static ReadOnlySpan<char> ExtractDomain(ReadOnlySpan<char> email)
351
+ {
352
+ int at = email.IndexOf('@');
353
+ return at >= 0 ? email[(at + 1)..] : ReadOnlySpan<char>.Empty;
354
+ }
355
+ // Stack-allocated buffer: Span<byte> buf = stackalloc byte[256];
356
+ ```
357
+
358
+ ### ValueTask -- Cache-Hit Fast Path
359
+ ```csharp
360
+ public ValueTask<Product?> GetProductAsync(string id, CancellationToken ct)
361
+ {
362
+ if (_cache.TryGetValue(id, out var cached)) return ValueTask.FromResult<Product?>(cached);
363
+ return new ValueTask<Product?>(LoadFromDbAsync(id, ct));
364
+ }
365
+ ```
366
+
367
+ ### Source Generators
368
+ ```csharp
369
+ // JSON -- avoids runtime reflection
370
+ [JsonSerializable(typeof(Order))]
371
+ [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
372
+ public partial class AppJsonContext : JsonSerializerContext;
373
+
374
+ // Logging -- avoids boxing
375
+ public static partial class Log
376
+ {
377
+ [LoggerMessage(Level = LogLevel.Information, Message = "Order {OrderId} created")]
378
+ public static partial void OrderCreated(ILogger logger, string orderId);
379
+ }
380
+ ```
381
+
382
+ ### BenchmarkDotNet
383
+ ```csharp
384
+ [MemoryDiagnoser, SimpleJob(RuntimeMoniker.Net90)]
385
+ public class ParsingBenchmarks
386
+ {
387
+ private readonly string _email = "user@example.com";
388
+ [Benchmark(Baseline = true)] public string Sub() => _email[(_email.IndexOf('@') + 1)..];
389
+ [Benchmark] public ReadOnlySpan<char> Span() => ExtractDomain(_email.AsSpan());
390
+ }
391
+ // dotnet run -c Release --project Benchmarks
392
+ ```
393
+
394
+ ---
395
+
396
+ ## Build / Package Management
397
+
398
+ ### dotnet CLI
399
+ ```bash
400
+ dotnet new sln -n MyApp && dotnet new webapi -n MyApp.Api -o src/MyApp.Api
401
+ dotnet build -c Release
402
+ dotnet test -c Release --collect:"XPlat Code Coverage"
403
+ dotnet publish src/MyApp.Api -c Release -o ./publish
404
+ dotnet ef migrations add Init --project src/MyApp.Infrastructure --startup-project src/MyApp.Api
405
+ ```
406
+
407
+ ### .editorconfig
408
+ ```ini
409
+ [*.cs]
410
+ dotnet_sort_system_directives_first = true
411
+ csharp_style_namespace_declarations = file_scoped:error
412
+ csharp_prefer_primary_constructors = true:suggestion
413
+ dotnet_diagnostic.CA1848.severity = warning
414
+ ```
415
+
416
+ ### CI (GitHub Actions)
417
+ ```yaml
418
+ steps:
419
+ - uses: actions/checkout@v4
420
+ - uses: actions/setup-dotnet@v4
421
+ with: { dotnet-version: '9.0.x' }
422
+ - run: dotnet restore
423
+ - run: dotnet build --no-restore -c Release -warnaserror
424
+ - run: dotnet test --no-build -c Release --collect:"XPlat Code Coverage"
425
+ - run: dotnet publish src/MyApp.Api -c Release -o publish --no-build
426
+ ```
427
+
428
+ ### Dockerfile
429
+ ```dockerfile
430
+ FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
431
+ WORKDIR /src
432
+ COPY . .
433
+ RUN dotnet publish src/MyApp.Api -c Release -o /app
434
+ FROM mcr.microsoft.com/dotnet/aspnet:9.0
435
+ COPY --from=build /app /app
436
+ WORKDIR /app
437
+ ENTRYPOINT ["dotnet", "MyApp.Api.dll"]
438
+ ```
439
+
440
+ ---
441
+
442
+ ## Anti-Patterns
443
+ - `async void` outside event handlers -- always return `Task`
444
+ - Blocking with `.Result` / `.Wait()` -- deadlock risk
445
+ - Missing `CancellationToken` propagation through the call chain
446
+ - Catching bare `Exception` without re-throw or structured logging
447
+ - Service locator via `IServiceProvider.GetService` in business logic
448
+ - Exposing `IQueryable` from repositories -- leaks persistence details
449
+ - Public setters on domain entities -- use methods + private setters
450
+ - String concatenation in hot paths -- use `StringBuilder` or string handlers