@mark-gozner/aigile-method 0.4.5

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 (143) hide show
  1. package/LICENSE.md +26 -0
  2. package/README.md +300 -0
  3. package/core/agent-teams/team-all.yaml +24 -0
  4. package/core/agent-teams/team-company.yaml +17 -0
  5. package/core/agent-teams/team-enterprise.yaml +17 -0
  6. package/core/agent-teams/team-fullstack.yaml +16 -0
  7. package/core/agent-teams/team-ide-minimal.yaml +10 -0
  8. package/core/agents/aigile-master.md +476 -0
  9. package/core/agents/aigile-orchestrator.agent.md +200 -0
  10. package/core/agents/analyst.md +45 -0
  11. package/core/agents/architect.md +43 -0
  12. package/core/agents/code-tour.agent.md +208 -0
  13. package/core/agents/dev.agent.md +145 -0
  14. package/core/agents/dev.md +130 -0
  15. package/core/agents/expert-react-frontend-engineer.agent.md +741 -0
  16. package/core/agents/pm.md +33 -0
  17. package/core/agents/po.md +35 -0
  18. package/core/agents/qa.md +38 -0
  19. package/core/agents/sm.md +31 -0
  20. package/core/agents/ui-expert.md +39 -0
  21. package/core/agents/ux-expert.md +31 -0
  22. package/core/checklists/architect-checklist.md +246 -0
  23. package/core/checklists/change-checklist.md +182 -0
  24. package/core/checklists/pm-checklist.md +286 -0
  25. package/core/checklists/po-master-checklist.md +291 -0
  26. package/core/checklists/story-dod-checklist.md +94 -0
  27. package/core/checklists/story-draft-checklist.md +153 -0
  28. package/core/core-config.yaml +22 -0
  29. package/core/data/aigile-kb.md +112 -0
  30. package/core/data/brainstorming-techniques.md +73 -0
  31. package/core/data/elicitation-methods.md +42 -0
  32. package/core/data/technical-preferences.md +52 -0
  33. package/core/data/test-levels-framework.md +43 -0
  34. package/core/data/test-priorities-matrix.md +26 -0
  35. package/core/instructions/csharp.instructions.md +656 -0
  36. package/core/instructions/dotnet/csharp.instructions.md +656 -0
  37. package/core/instructions/java/java.instructions.md +67 -0
  38. package/core/instructions/java/spring-boot.instructions.md +122 -0
  39. package/core/instructions/java.instructions.md +67 -0
  40. package/core/instructions/spring-boot.instructions.md +122 -0
  41. package/core/prompts/README.md +11 -0
  42. package/core/prompts/architecture/architecture-blueprint-generator.prompt.md +322 -0
  43. package/core/prompts/architecture/architecture-validation.prompt.md +71 -0
  44. package/core/prompts/architecture/file-tree-generator.prompt.md +405 -0
  45. package/core/prompts/architecture/technical-project-analyze.prompt.md +43 -0
  46. package/core/prompts/architecture-blueprint-generator.prompt.md +322 -0
  47. package/core/prompts/architecture-validation.prompt.md +71 -0
  48. package/core/prompts/code-review.prompt.md +107 -0
  49. package/core/prompts/confluence-in-md.prompt.md +167 -0
  50. package/core/prompts/copilot-instructions-blueprint-generator.prompt.md +294 -0
  51. package/core/prompts/create-implementation-plan.prompt.md +157 -0
  52. package/core/prompts/create-oo-component-documentation.prompt.md +193 -0
  53. package/core/prompts/file-tree-generator.prompt.md +405 -0
  54. package/core/prompts/generate-unit-tests.prompt.md +291 -0
  55. package/core/prompts/java/java-doc.prompt.md +24 -0
  56. package/core/prompts/java/java-junit.prompt.md +64 -0
  57. package/core/prompts/java/junit-5.prompt.md +64 -0
  58. package/core/prompts/java-doc.prompt.md +24 -0
  59. package/core/prompts/java-junit.prompt.md +64 -0
  60. package/core/prompts/junit-5.prompt.md +64 -0
  61. package/core/prompts/release-notes/README.md +11 -0
  62. package/core/prompts/release-notes/release-notes.prompt.md +723 -0
  63. package/core/prompts/release-notes.prompt.md +723 -0
  64. package/core/prompts/technical-project-analyze.prompt.md +43 -0
  65. package/core/tasks/advanced-elicitation.md +119 -0
  66. package/core/tasks/check-story-implemented.md +44 -0
  67. package/core/tasks/code-arch-review-with-github.md +40 -0
  68. package/core/tasks/create-architecture-doc.md +55 -0
  69. package/core/tasks/create-jira-epic-from-confluence.md +70 -0
  70. package/core/tasks/create-jira-story-from-confluence.md +39 -0
  71. package/core/tasks/create-jira-story-from-text.md +39 -0
  72. package/core/tasks/create-next-story.md +35 -0
  73. package/core/tasks/create-prd-doc.md +54 -0
  74. package/core/tasks/create-stories-from-epic.md +66 -0
  75. package/core/tasks/create-tasks-for-story.md +60 -0
  76. package/core/tasks/document-project.md +69 -0
  77. package/core/tasks/execute-checklist.md +37 -0
  78. package/core/tasks/explain-story-from-jira.md +44 -0
  79. package/core/tasks/facilitate-brainstorming-session.md +69 -0
  80. package/core/tasks/figma-audit-design-system.md +20 -0
  81. package/core/tasks/front-end-spec-from-design.md +33 -0
  82. package/core/tasks/gate.md +64 -0
  83. package/core/tasks/groom-jira-story.md +52 -0
  84. package/core/tasks/help.md +27 -0
  85. package/core/tasks/implement-freeform-work-item.md +30 -0
  86. package/core/tasks/implement-story-from-jira.md +63 -0
  87. package/core/tasks/implement-unit-tests.md +45 -0
  88. package/core/tasks/market-research-from-context7.md +37 -0
  89. package/core/tasks/review-story.md +30 -0
  90. package/core/tasks/sonarqube-hotspot-review.md +39 -0
  91. package/core/tasks/standup-digest.md +21 -0
  92. package/core/tasks/sync-jira-backlog.md +32 -0
  93. package/core/tasks/test-design.md +68 -0
  94. package/core/tasks/validate-next-story.md +37 -0
  95. package/core/tasks/verify-jira-story-e2e.md +45 -0
  96. package/core/templates/architecture-tmpl.yaml +651 -0
  97. package/core/templates/brainstorming-output-tmpl.yaml +156 -0
  98. package/core/templates/brownfield-architecture-tmpl.yaml +477 -0
  99. package/core/templates/brownfield-prd-tmpl.yaml +281 -0
  100. package/core/templates/front-end-architecture-tmpl.yaml +219 -0
  101. package/core/templates/front-end-spec-tmpl.yaml +350 -0
  102. package/core/templates/fullstack-architecture-tmpl.yaml +824 -0
  103. package/core/templates/market-research-tmpl.yaml +253 -0
  104. package/core/templates/prd-tmpl.yaml +203 -0
  105. package/core/templates/project-brief-tmpl.yaml +222 -0
  106. package/core/templates/qa-gate-tmpl.yaml +103 -0
  107. package/core/templates/story-tmpl.yaml +138 -0
  108. package/core/workflows/brownfield-fullstack.yaml +298 -0
  109. package/core/workflows/brownfield-service.yaml +188 -0
  110. package/core/workflows/brownfield-ui.yaml +198 -0
  111. package/core/workflows/greenfield-fullstack.yaml +241 -0
  112. package/core/workflows/greenfield-service.yaml +207 -0
  113. package/core/workflows/greenfield-ui.yaml +236 -0
  114. package/dist/agents/aigile-master.txt +500 -0
  115. package/dist/agents/aigile-orchestrator.agent.txt +224 -0
  116. package/dist/agents/analyst.txt +69 -0
  117. package/dist/agents/architect.txt +67 -0
  118. package/dist/agents/code-tour.agent.txt +232 -0
  119. package/dist/agents/dev.agent.txt +169 -0
  120. package/dist/agents/dev.txt +154 -0
  121. package/dist/agents/expert-react-frontend-engineer.agent.txt +765 -0
  122. package/dist/agents/pm.txt +57 -0
  123. package/dist/agents/po.txt +59 -0
  124. package/dist/agents/qa.txt +62 -0
  125. package/dist/agents/sm.txt +55 -0
  126. package/dist/agents/ui-expert.txt +63 -0
  127. package/dist/agents/ux-expert.txt +55 -0
  128. package/dist/dev-agent-bundle.txt +154 -0
  129. package/dist/teams/team-company.txt +10789 -0
  130. package/docs/mcp-servers.md +102 -0
  131. package/docs/orchestrator-guide.md +526 -0
  132. package/mcp/servers.json +108 -0
  133. package/mcp/servers.yaml +124 -0
  134. package/package.json +72 -0
  135. package/tools/cli.js +1864 -0
  136. package/tools/installer/README.md +24 -0
  137. package/tools/installer/lib/ide-setup.js +295 -0
  138. package/tools/installer/lib/installer.js +131 -0
  139. package/tools/md-assets/web-agent-startup-instructions.md +21 -0
  140. package/tools/postinstall.js +72 -0
  141. package/tools/shared/bannerArt.js +68 -0
  142. package/tools/validate-bundles.js +54 -0
  143. package/tools/verify-publish-registry.js +34 -0
@@ -0,0 +1,656 @@
1
+ ---
2
+ description: "This file provides guidelines for writing clean, maintainable, and idiomatic C# code with a focus on functional patterns and proper abstraction."
3
+ applyTo: '**/*.cs'
4
+ ---
5
+
6
+ # Role Definition:
7
+
8
+ - C# Language Expert
9
+ - Software Architect
10
+ - Code Quality Specialist
11
+
12
+ ## General:
13
+
14
+ **Description:**
15
+ C# code should be written to maximize readability, maintainability, and correctness while minimizing complexity and coupling. Prefer functional patterns and immutable data
16
+ where appropriate, and keep abstractions simple and focused.
17
+
18
+ **Requirements:**
19
+
20
+ - Write clear, self-documenting code
21
+ - Keep abstractions simple and focused
22
+ - Minimize dependencies and coupling
23
+ - Use modern C# features appropriately
24
+
25
+ ## Code Organization:
26
+
27
+ - Use meaningful names:
28
+ ```csharp
29
+ // Good: Clear intent
30
+ public async Task<Result<Order>> ProcessOrderAsync(OrderRequest request, CancellationToken cancellationToken)
31
+
32
+ // Avoid: Unclear abbreviations
33
+ public async Task<Result<T>> ProcAsync<T>(ReqDto r, CancellationToken ct)
34
+ ```
35
+ - Separate state from behavior:
36
+ ```csharp
37
+ // Good: Behavior separate from state
38
+ public sealed record Order(OrderId Id, List<OrderLine> Lines);
39
+
40
+ public static class OrderOperations
41
+ {
42
+ public static decimal CalculateTotal(Order order) =>
43
+ order.Lines.Sum(line => line.Price * line.Quantity);
44
+ }
45
+ ```
46
+ - Prefer pure methods:
47
+ ```csharp
48
+ // Good: Pure function
49
+ public static decimal CalculateTotalPrice(
50
+ IEnumerable<OrderLine> lines,
51
+ decimal taxRate) =>
52
+ lines.Sum(line => line.Price * line.Quantity) * (1 + taxRate);
53
+
54
+ // Avoid: Method with side effects
55
+ public void CalculateAndUpdateTotalPrice()
56
+ {
57
+ this.Total = this.Lines.Sum(l => l.Price * l.Quantity);
58
+ this.UpdateDatabase();
59
+ }
60
+ ```
61
+ - Use extension methods appropriately:
62
+ ```csharp
63
+ // Good: Extension method for domain-specific operations
64
+ public static class OrderExtensions
65
+ {
66
+ public static bool CanBeFulfilled(this Order order, Inventory inventory) =>
67
+ order.Lines.All(line => inventory.HasStock(line.ProductId, line.Quantity));
68
+ }
69
+ ```
70
+ - Design for testability:
71
+ ```csharp
72
+ // Good: Easy to test pure functions
73
+ public static class PriceCalculator
74
+ {
75
+ public static decimal CalculateDiscount(
76
+ decimal price,
77
+ int quantity,
78
+ CustomerTier tier) =>
79
+ // Pure calculation
80
+ }
81
+
82
+ // Avoid: Hard to test due to hidden dependencies
83
+ public decimal CalculateDiscount()
84
+ {
85
+ var user = _userService.GetCurrentUser(); // Hidden dependency
86
+ var settings = _configService.GetSettings(); // Hidden dependency
87
+ // Calculation
88
+ }
89
+ ```
90
+
91
+ ## Dependency Management:
92
+
93
+ - Minimize constructor injection:
94
+ ```csharp
95
+ // Good: Minimal dependencies
96
+ public sealed class OrderProcessor(IOrderRepository repository)
97
+ {
98
+ // Implementation
99
+ }
100
+
101
+ // Avoid: Too many dependencies
102
+ // Too many dependencies indicates possible design issues
103
+ public class OrderProcessor(
104
+ IOrderRepository repository,
105
+ ILogger logger,
106
+ IEmailService emailService,
107
+ IMetrics metrics,
108
+ IValidator validator)
109
+ {
110
+ // Implementation
111
+ }
112
+ ```
113
+ - Prefer composition with interfaces:
114
+ ```csharp
115
+ // Good: Composition with interfaces
116
+ public sealed class EnhancedLogger(ILogger baseLogger, IMetrics metrics) : ILogger
117
+ {
118
+ }
119
+ ```
120
+
121
+ ## Type Definitions:
122
+
123
+ - Prefer records for data types:
124
+ ```csharp
125
+ // Good: Immutable data type with value semantics
126
+ public sealed record CustomerDto(string Name, Email Email);
127
+
128
+ // Avoid: Class with mutable properties
129
+ public class Customer
130
+ {
131
+ public string Name { get; set; }
132
+ public string Email { get; set; }
133
+ }
134
+ ```
135
+ - Make classes sealed by default:
136
+ ```csharp
137
+ // Good: Make classes sealed by default
138
+ public sealed class OrderProcessor
139
+ {
140
+ // Implementation
141
+ }
142
+
143
+ // Only unsealed when inheritance is specifically designed for
144
+ public abstract class Repository<T>
145
+ {
146
+ // Base implementation
147
+ }
148
+ ```
149
+
150
+ ## Variable Declarations:
151
+
152
+ - Use var where possible:
153
+ ```csharp
154
+ // Good: Using var for type inference
155
+ var fruit = "Apple";
156
+ var number = 42;
157
+ var order = new Order(fruit, number);
158
+ ```
159
+
160
+ ## Control Flow:
161
+
162
+ - Prefer range indexers over LINQ:
163
+ ```csharp
164
+ // Good: Using range indexers with clear comments
165
+ var lastItem = items[^1]; // ^1 means "1 from the end"
166
+ var firstThree = items[..3]; // ..3 means "take first 3 items"
167
+ var slice = items[2..5]; // take items from index 2 to 4 (5 exclusive)
168
+
169
+ // Avoid: Using LINQ when range indexers are clearer
170
+ var lastItem = items.LastOrDefault();
171
+ var firstThree = items.Take(3).ToList();
172
+ var slice = items.Skip(2).Take(3).ToList();
173
+ ```
174
+ - Prefer collection initializers:
175
+ ```csharp
176
+ // Good: Using collection initializers
177
+ string[] fruits = ["Apple", "Banana", "Cherry"];
178
+
179
+ // Avoid: Using explicit initialization when type is clear
180
+ var fruits = new List<int>() {
181
+ "Apple",
182
+ "Banana",
183
+ "Cherry"
184
+ };
185
+ ```
186
+ - Use pattern matching effectively:
187
+ ```csharp
188
+ // Good: Clear pattern matching
189
+ public decimal CalculateDiscount(Customer customer) =>
190
+ customer switch
191
+ {
192
+ { Tier: CustomerTier.Premium } => 0.2m,
193
+ { OrderCount: > 10 } => 0.1m,
194
+ _ => 0m
195
+ };
196
+
197
+ // Avoid: Nested if statements
198
+ public decimal CalculateDiscount(Customer customer)
199
+ {
200
+ if (customer.Tier == CustomerTier.Premium)
201
+ return 0.2m;
202
+ if (customer.OrderCount > 10)
203
+ return 0.1m;
204
+ return 0m;
205
+ }
206
+ ```
207
+
208
+ ## Nullability:
209
+
210
+ - Mark nullable fields explicitly:
211
+ ```csharp
212
+ // Good: Explicit nullability
213
+ public class OrderProcessor
214
+ {
215
+ private readonly ILogger<OrderProcessor>? _logger;
216
+ private string? _lastError;
217
+
218
+ public OrderProcessor(ILogger<OrderProcessor>? logger = null)
219
+ {
220
+ _logger = logger;
221
+ }
222
+ }
223
+
224
+ // Avoid: Implicit nullability
225
+ public class OrderProcessor
226
+ {
227
+ private readonly ILogger<OrderProcessor> _logger; // Warning: Could be null
228
+ private string _lastError; // Warning: Could be null
229
+ }
230
+ ```
231
+ - Use null checks only when necessary for reference types and public methods:
232
+ ```csharp
233
+ // Good: Proper null checking
234
+ public void ProcessOrder(Order order)
235
+ {
236
+ ArgumentNullException.ThrowIfNull(order); // Appropriate for reference types
237
+
238
+ _logger?.LogInformation("Processing order {Id}", order.Id);
239
+ }
240
+
241
+ // Good: Using pattern matching for null checks
242
+ public decimal CalculateTotal(Order? order) =>
243
+ order switch
244
+ {
245
+ null => throw new ArgumentNullException(nameof(order)),
246
+ { Lines: null } => throw new ArgumentException("Order lines cannot be null", nameof(order)),
247
+ _ => order.Lines.Sum(l => l.Total)
248
+ };
249
+ // BAD: Avoid null checks for value types
250
+ public void ProcessOrder(int orderId)
251
+ {
252
+ ArgumentNullException.ThrowIfNull(order); // DON'T USE Null checks are unnecessary for value types
253
+ }
254
+
255
+ // Avoid: null checks for non-public methods
256
+ private void ProcessOrder(Order order)
257
+ {
258
+ ArgumentNullException.ThrowIfNull(order); // DON'T USE, ProcessOrder is private
259
+ }
260
+ ```
261
+ - Use null-forgiving operator when appropriate:
262
+ ```csharp
263
+ public class OrderValidator
264
+ {
265
+ private readonly IValidator<Order> _validator;
266
+
267
+ public OrderValidator(IValidator<Order> validator)
268
+ {
269
+ _validator = validator ?? throw new ArgumentNullException(nameof(validator));
270
+ }
271
+
272
+ public ValidationResult Validate(Order order)
273
+ {
274
+ // We know _validator can't be null due to constructor check
275
+ return _validator!.Validate(order);
276
+ }
277
+ }
278
+ ```
279
+ - Use nullability attributes:
280
+ ```csharp
281
+ public class StringUtilities
282
+ {
283
+ // Output is non-null if input is non-null
284
+ [return: NotNullIfNotNull(nameof(input))]
285
+ public static string? ToUpperCase(string? input) =>
286
+ input?.ToUpperInvariant();
287
+
288
+ // Method never returns null
289
+ [return: NotNull]
290
+ public static string EnsureNotNull(string? input) =>
291
+ input ?? string.Empty;
292
+
293
+ // Parameter must not be null when method returns true
294
+ public static bool TryParse(string? input, [NotNullWhen(true)] out string? result)
295
+ {
296
+ result = null;
297
+ if (string.IsNullOrEmpty(input))
298
+ return false;
299
+
300
+ result = input;
301
+ return true;
302
+ }
303
+ }
304
+ ```
305
+ - Use init-only properties with non-null validation:
306
+ ```csharp
307
+ // Good: Non-null validation in constructor
308
+ public sealed record Order
309
+ {
310
+ public required OrderId Id { get; init; }
311
+ public required ImmutableList<OrderLine> Lines { get; init; }
312
+
313
+ public Order()
314
+ {
315
+ Id = null!; // Will be set by required property
316
+ Lines = null!; // Will be set by required property
317
+ }
318
+
319
+ private Order(OrderId id, ImmutableList<OrderLine> lines)
320
+ {
321
+ Id = id;
322
+ Lines = lines;
323
+ }
324
+
325
+ public static Order Create(OrderId id, IEnumerable<OrderLine> lines) =>
326
+ new(id, lines.ToImmutableList());
327
+ }
328
+ ```
329
+ - Document nullability in interfaces:
330
+ ```csharp
331
+ public interface IOrderRepository
332
+ {
333
+ // Explicitly shows that null is a valid return value
334
+ Task<Order?> FindByIdAsync(OrderId id, CancellationToken ct = default);
335
+
336
+ // Method will never return null
337
+ [return: NotNull]
338
+ Task<IReadOnlyList<Order>> GetAllAsync(CancellationToken ct = default);
339
+
340
+ // Parameter cannot be null
341
+ Task SaveAsync([NotNull] Order order, CancellationToken ct = default);
342
+ }
343
+ ```
344
+
345
+ ## Safe Operations:
346
+
347
+ - Use Try methods for safer operations:
348
+ ```csharp
349
+ // Good: Using TryGetValue for dictionary access
350
+ if (dictionary.TryGetValue(key, out var value))
351
+ {
352
+ // Use value safely here
353
+ }
354
+ else
355
+ {
356
+ // Handle missing key case
357
+ }
358
+ ```
359
+ ```csharp
360
+ // Avoid: Direct indexing which can throw
361
+ var value = dictionary[key]; // Throws if key doesn't exist
362
+
363
+ // Good: Using Uri.TryCreate for URL parsing
364
+ if (Uri.TryCreate(urlString, UriKind.Absolute, out var uri))
365
+ {
366
+ // Use uri safely here
367
+ }
368
+ else
369
+ {
370
+ // Handle invalid URL case
371
+ }
372
+ ```
373
+ ```csharp
374
+ // Avoid: Direct Uri creation which can throw
375
+ var uri = new Uri(urlString); // Throws on invalid URL
376
+
377
+ // Good: Using int.TryParse for number parsing
378
+ if (int.TryParse(input, out var number))
379
+ {
380
+ // Use number safely here
381
+ }
382
+ else
383
+ {
384
+ // Handle invalid number case
385
+ }
386
+ ```
387
+ ```csharp
388
+ // Good: Combining Try methods with null coalescing
389
+ var value = dictionary.TryGetValue(key, out var result)
390
+ ? result
391
+ : defaultValue;
392
+
393
+ // Good: Using Try methods in LINQ with pattern matching
394
+ var validNumbers = strings
395
+ .Select(s => (Success: int.TryParse(s, out var num), Value: num))
396
+ .Where(x => x.Success)
397
+ .Select(x => x.Value);
398
+ ```
399
+
400
+ - Prefer Try methods over exception handling:
401
+ ```csharp
402
+ // Good: Using Try method
403
+ if (decimal.TryParse(priceString, out var price))
404
+ {
405
+ // Process price
406
+ }
407
+
408
+ // Avoid: Exception handling for expected cases
409
+ try
410
+ {
411
+ var price = decimal.Parse(priceString);
412
+ // Process price
413
+ }
414
+ catch (FormatException)
415
+ {
416
+ // Handle invalid format
417
+ }
418
+ ```
419
+
420
+ ## Asynchronous Programming:
421
+
422
+ - Use Task.FromResult for pre-computed values:
423
+ ```csharp
424
+ // Good: Return pre-computed value
425
+ public Task<int> GetDefaultQuantityAsync() =>
426
+ Task.FromResult(1);
427
+
428
+ // Better: Use ValueTask for zero allocations
429
+ public ValueTask<int> GetDefaultQuantityAsync() =>
430
+ new ValueTask<int>(1);
431
+
432
+ // Avoid: Unnecessary thread pool usage
433
+ public Task<int> GetDefaultQuantityAsync() =>
434
+ Task.Run(() => 1);
435
+ ```
436
+ - Always flow CancellationToken:
437
+ ```csharp
438
+ // Good: Propagate cancellation
439
+ public async Task<Order> ProcessOrderAsync(
440
+ OrderRequest request,
441
+ CancellationToken cancellationToken)
442
+ {
443
+ var order = await _repository.GetAsync(
444
+ request.OrderId,
445
+ cancellationToken);
446
+
447
+ await _processor.ProcessAsync(
448
+ order,
449
+ cancellationToken);
450
+
451
+ return order;
452
+ }
453
+ ```
454
+ - Prefer await:
455
+ ```csharp
456
+ // Good: Using await
457
+ public async Task<Order> ProcessOrderAsync(OrderId id)
458
+ {
459
+ var order = await _repository.GetAsync(id);
460
+ await _validator.ValidateAsync(order);
461
+ return order;
462
+ }
463
+ ```
464
+ - Never use Task.Result or Task.Wait:
465
+ ```csharp
466
+ // Good: Async all the way
467
+ public async Task<Order> GetOrderAsync(OrderId id)
468
+ {
469
+ return await _repository.GetAsync(id);
470
+ }
471
+
472
+ // Avoid: Blocking on async code
473
+ public Order GetOrder(OrderId id)
474
+ {
475
+ return _repository.GetAsync(id).Result; // Can deadlock
476
+ }
477
+ ```
478
+ - Use TaskCompletionSource correctly:
479
+ ```csharp
480
+ // Good: Using RunContinuationsAsynchronously
481
+ private readonly TaskCompletionSource<Order> _tcs =
482
+ new(TaskCreationOptions.RunContinuationsAsynchronously);
483
+
484
+ // Avoid: Default TaskCompletionSource can cause deadlocks
485
+ private readonly TaskCompletionSource<Order> _tcs = new();
486
+ ```
487
+ - Always dispose CancellationTokenSources:
488
+ ```csharp
489
+ // Good: Proper disposal of CancellationTokenSource
490
+ public async Task<Order> GetOrderWithTimeout(OrderId id)
491
+ {
492
+ using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
493
+ return await _repository.GetAsync(id, cts.Token);
494
+ }
495
+ ```
496
+ - Prefer async/await over direct Task return:
497
+ ```csharp
498
+ // Good: Using async/await
499
+ public async Task<Order> ProcessOrderAsync(OrderRequest request)
500
+ {
501
+ await _validator.ValidateAsync(request);
502
+ var order = await _factory.CreateAsync(request);
503
+ return order;
504
+ }
505
+
506
+ // Avoid: Manual task composition
507
+ public Task<Order> ProcessOrderAsync(OrderRequest request)
508
+ {
509
+ return _validator.ValidateAsync(request)
510
+ .ContinueWith(t => _factory.CreateAsync(request))
511
+ .Unwrap();
512
+ }
513
+ ```
514
+
515
+ ## Symbol References:
516
+
517
+ - Always use nameof operator:
518
+ ```csharp
519
+ // Good: Using nameof in attributes
520
+ public class OrderProcessor
521
+ {
522
+ [Required(ErrorMessage = "The {0} field is required")]
523
+ [Display(Name = nameof(OrderId))]
524
+ public string OrderId { get; init; }
525
+
526
+ [MemberNotNull(nameof(_repository))]
527
+ private void InitializeRepository()
528
+ {
529
+ _repository = new OrderRepository();
530
+ }
531
+
532
+ [NotifyPropertyChangedFor(nameof(FullName))]
533
+ public string FirstName
534
+ {
535
+ get => _firstName;
536
+ set => SetProperty(ref _firstName, value);
537
+ }
538
+ }
539
+ ```
540
+ - Use nameof with exceptions:
541
+ ```csharp
542
+ public class OrderService
543
+ {
544
+ public async Task<Order> GetOrderAsync(OrderId id, CancellationToken ct)
545
+ {
546
+ var order = await _repository.FindAsync(id, ct);
547
+
548
+ if (order is null)
549
+ throw new OrderNotFoundException(
550
+ $"Order with {nameof(id)} '{id}' not found");
551
+
552
+ if (!order.Lines.Any())
553
+ throw new InvalidOperationException(
554
+ $"{nameof(order.Lines)} cannot be empty");
555
+
556
+ return order;
557
+ }
558
+
559
+ public void ValidateOrder(Order order)
560
+ {
561
+ if (order.Lines.Count == 0)
562
+ throw new ArgumentException(
563
+ "Order must have at least one line",
564
+ nameof(order));
565
+ }
566
+ }
567
+ ```
568
+ - Use nameof in logging:
569
+ ```csharp
570
+ public class OrderProcessor
571
+ {
572
+ private readonly ILogger<OrderProcessor> _logger;
573
+
574
+ public async Task ProcessAsync(Order order)
575
+ {
576
+ _logger.LogInformation(
577
+ "Starting {Method} for order {OrderId}",
578
+ nameof(ProcessAsync),
579
+ order.Id);
580
+
581
+ try
582
+ {
583
+ await ProcessInternalAsync(order);
584
+ }
585
+ catch (Exception ex)
586
+ {
587
+ _logger.LogError(
588
+ ex,
589
+ "Error in {Method} for {Property} {Value}",
590
+ nameof(ProcessAsync),
591
+ nameof(order.Id),
592
+ order.Id);
593
+ throw;
594
+ }
595
+ }
596
+ }
597
+ ```
598
+
599
+ ### Usings and Namespaces:
600
+
601
+ - Use implicit usings:
602
+ ```csharp
603
+ // Good: Implicit
604
+ namespace MyNamespace
605
+ {
606
+ public class MyClass
607
+ {
608
+ // Implementation
609
+ }
610
+ }
611
+ // Avoid:
612
+ using System; // DON'T USE
613
+ using System.Collections.Generic; // DON'T USE
614
+ using System.IO; // DON'T USE
615
+ using System.Linq; // DON'T USE
616
+ using System.Net.Http; // DON'T USE
617
+ using System.Threading; // DON'T USE
618
+ using System.Threading.Tasks;// DON'T USE
619
+ using System.Net.Http.Json; // DON'T USE
620
+ using Microsoft.AspNetCore.Builder; // DON'T USE
621
+ using Microsoft.AspNetCore.Hosting; // DON'T USE
622
+ using Microsoft.AspNetCore.Http; // DON'T USE
623
+ using Microsoft.AspNetCore.Routing; // DON'T USE
624
+ using Microsoft.Extensions.Configuration; // DON'T USE
625
+ using Microsoft.Extensions.DependencyInjection; // DON'T USE
626
+ using Microsoft.Extensions.Hosting; // DON'T USE
627
+ using Microsoft.Extensions.Logging; // DON'T USE
628
+ using Good: Explicit usings; // DON'T USE
629
+
630
+ namespace MyNamespace
631
+ {
632
+ public class MyClass
633
+ {
634
+ // Implementation
635
+ }
636
+ }
637
+ ```
638
+ - Use file-scoped namespaces:
639
+ ```csharp
640
+ // Good: File-scoped namespace
641
+ namespace MyNamespace;
642
+
643
+ public class MyClass
644
+ {
645
+ // Implementation
646
+ }
647
+
648
+ // Avoid: Block-scoped namespace
649
+ namespace MyNamespace
650
+ {
651
+ public class MyClass
652
+ {
653
+ // Implementation
654
+ }
655
+ }
656
+ ```