@deftai/directive-content 0.55.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 (250) hide show
  1. package/.agents/skills/deft/SKILL.md +6 -0
  2. package/.agents/skills/deft-directive-article-review/SKILL.md +11 -0
  3. package/.agents/skills/deft-directive-build/SKILL.md +10 -0
  4. package/.agents/skills/deft-directive-cost/SKILL.md +12 -0
  5. package/.agents/skills/deft-directive-debug/SKILL.md +13 -0
  6. package/.agents/skills/deft-directive-gh-arch/SKILL.md +11 -0
  7. package/.agents/skills/deft-directive-gh-slice/SKILL.md +10 -0
  8. package/.agents/skills/deft-directive-glossary/SKILL.md +10 -0
  9. package/.agents/skills/deft-directive-interview/SKILL.md +9 -0
  10. package/.agents/skills/deft-directive-pre-pr/SKILL.md +9 -0
  11. package/.agents/skills/deft-directive-refinement/SKILL.md +10 -0
  12. package/.agents/skills/deft-directive-release/SKILL.md +12 -0
  13. package/.agents/skills/deft-directive-review-cycle/SKILL.md +10 -0
  14. package/.agents/skills/deft-directive-setup/SKILL.md +10 -0
  15. package/.agents/skills/deft-directive-swarm/SKILL.md +10 -0
  16. package/.agents/skills/deft-directive-sync/SKILL.md +9 -0
  17. package/.agents/skills/deft-directive-triage/SKILL.md +9 -0
  18. package/.agents/skills/deft-directive-write-skill/SKILL.md +9 -0
  19. package/LICENSE.md +22 -0
  20. package/QUICK-START.md +167 -0
  21. package/UPGRADING.md +517 -0
  22. package/coding/build-output.md +28 -0
  23. package/coding/coding.md +235 -0
  24. package/coding/debugging.md +110 -0
  25. package/coding/holzmann.md +96 -0
  26. package/coding/hygiene.md +127 -0
  27. package/coding/security.md +158 -0
  28. package/coding/testing.md +162 -0
  29. package/coding/toolchain.md +44 -0
  30. package/commands.md +300 -0
  31. package/context/context.md +57 -0
  32. package/context/deterministic-split.md +67 -0
  33. package/context/examples.md +26 -0
  34. package/context/fractal-summaries.md +69 -0
  35. package/context/long-horizon.md +46 -0
  36. package/context/spec-deltas.md +177 -0
  37. package/context/tool-design.md +34 -0
  38. package/context/working-memory.md +62 -0
  39. package/contracts/boundary-maps.md +65 -0
  40. package/contracts/deterministic-questions.md +59 -0
  41. package/contracts/hierarchy.md +77 -0
  42. package/conventions/content-manifest.json +399 -0
  43. package/conventions/machine-generated-banner.md +130 -0
  44. package/conventions/references.md +120 -0
  45. package/conventions/rule-ownership.json +382 -0
  46. package/conventions/task-caching.md +43 -0
  47. package/conventions/vbrief-filenames.md +70 -0
  48. package/deployments/README.md +37 -0
  49. package/deployments/agentuity/README.md +138 -0
  50. package/deployments/agentuity/via-cli.md +380 -0
  51. package/deployments/agentuity/via-cloud.md +425 -0
  52. package/deployments/agentuity/via-github-actions.md +664 -0
  53. package/deployments/agentuity/via-gravity-network.md +606 -0
  54. package/deployments/agentuity/via-vpc.md +607 -0
  55. package/deployments/aws/README.md +38 -0
  56. package/deployments/aws/via-app-runner.md +612 -0
  57. package/deployments/aws/via-ecs-fargate.md +561 -0
  58. package/deployments/aws/via-elastic-beanstalk.md +628 -0
  59. package/deployments/aws/via-lambda.md +649 -0
  60. package/deployments/azure/README.md +37 -0
  61. package/deployments/azure/via-aks.md +390 -0
  62. package/deployments/azure/via-app-service.md +564 -0
  63. package/deployments/azure/via-container-apps.md +599 -0
  64. package/deployments/azure/via-functions.md +552 -0
  65. package/deployments/cloud-gov/README.md +63 -0
  66. package/deployments/cloud-gov/agents/compliance-docs.md +154 -0
  67. package/deployments/cloud-gov/agents.md +39 -0
  68. package/deployments/cloud-gov/cicd.md +64 -0
  69. package/deployments/cloud-gov/deployment.md +150 -0
  70. package/deployments/cloud-gov/logging.md +43 -0
  71. package/deployments/cloud-gov/manifest.md +121 -0
  72. package/deployments/cloud-gov/overview.md +58 -0
  73. package/deployments/cloud-gov/security.md +46 -0
  74. package/deployments/cloud-gov/services.md +72 -0
  75. package/deployments/cloud-gov/upstream/README.md +18 -0
  76. package/deployments/cloudflare/README.md +33 -0
  77. package/deployments/cloudflare/via-dashboard.md +83 -0
  78. package/deployments/cloudflare/via-git.md +90 -0
  79. package/deployments/cloudflare/via-github-actions.md +185 -0
  80. package/deployments/cloudflare/via-terraform.md +157 -0
  81. package/deployments/cloudflare/via-wrangler.md +165 -0
  82. package/deployments/fly-io/README.md +37 -0
  83. package/deployments/fly-io/via-dockerfile.md +648 -0
  84. package/deployments/fly-io/via-flyctl.md +653 -0
  85. package/deployments/fly-io/via-github-actions.md +695 -0
  86. package/deployments/fly-io/via-multi-region.md +598 -0
  87. package/deployments/google/README.md +34 -0
  88. package/deployments/google/via-app-engine.md +42 -0
  89. package/deployments/google/via-cloud-functions.md +23 -0
  90. package/deployments/google/via-cloud-run.md +330 -0
  91. package/deployments/google/via-gke.md +23 -0
  92. package/deployments/netlify/README.md +99 -0
  93. package/deployments/netlify/via-cli.md +17 -0
  94. package/deployments/netlify/via-functions.md +19 -0
  95. package/deployments/netlify/via-git.md +25 -0
  96. package/deployments/vercel/README.md +90 -0
  97. package/deployments/vercel/via-api.md +16 -0
  98. package/deployments/vercel/via-cli.md +17 -0
  99. package/deployments/vercel/via-git.md +24 -0
  100. package/docs/BROWNFIELD.md +179 -0
  101. package/docs/getting-started.md +137 -0
  102. package/docs/good-agents-md.md +137 -0
  103. package/events/README.md +89 -0
  104. package/events/event-record.schema.json +26 -0
  105. package/events/registry.json +166 -0
  106. package/events/registry.schema.json +71 -0
  107. package/glossary.md +145 -0
  108. package/incidents/README.md +81 -0
  109. package/incidents/_template.md +38 -0
  110. package/interfaces/cli.md +104 -0
  111. package/interfaces/rest.md +212 -0
  112. package/interfaces/tui.md +242 -0
  113. package/interfaces/web.md +123 -0
  114. package/languages/6502-DASM.md +132 -0
  115. package/languages/c.md +235 -0
  116. package/languages/commands.md +23 -0
  117. package/languages/cpp.md +132 -0
  118. package/languages/csharp.md +259 -0
  119. package/languages/dart.md +183 -0
  120. package/languages/delphi.md +218 -0
  121. package/languages/elixir.md +208 -0
  122. package/languages/go.md +78 -0
  123. package/languages/java.md +278 -0
  124. package/languages/javascript.md +163 -0
  125. package/languages/julia.md +175 -0
  126. package/languages/kotlin.md +193 -0
  127. package/languages/markdown.md +168 -0
  128. package/languages/mermaid.md +146 -0
  129. package/languages/officejs.md +392 -0
  130. package/languages/python.md +209 -0
  131. package/languages/r.md +163 -0
  132. package/languages/rust.md +216 -0
  133. package/languages/sql.md +216 -0
  134. package/languages/swift.md +153 -0
  135. package/languages/typescript.md +132 -0
  136. package/languages/vba.md +279 -0
  137. package/languages/vhdl.md +180 -0
  138. package/languages/visual-basic.md +151 -0
  139. package/languages/zig.md +196 -0
  140. package/meta/SOUL.md +27 -0
  141. package/meta/code-field.md +44 -0
  142. package/meta/morals.md +40 -0
  143. package/meta/philosophy.md +39 -0
  144. package/meta/project.md +49 -0
  145. package/meta/ralph.md +223 -0
  146. package/meta/security.md +80 -0
  147. package/meta/versioning.md +326 -0
  148. package/package.json +22 -0
  149. package/packs/lessons/lessons-pack-0.1.json +553 -0
  150. package/packs/patterns/patterns-pack-0.1.json +57 -0
  151. package/packs/rules/rules-pack-0.1.json +4767 -0
  152. package/packs/skills/skills-pack-0.1.json +262 -0
  153. package/packs/strategies/strategies-pack-0.1.json +167 -0
  154. package/packs/swarm-spec/swarm-spec-pack-0.1.json +17 -0
  155. package/patterns/executor-layer-credentials.md +227 -0
  156. package/patterns/llm-app.md +156 -0
  157. package/patterns/multi-agent.md +278 -0
  158. package/patterns/prompt-assembly-layer-ordering.md +154 -0
  159. package/patterns/role-as-overlay.md +179 -0
  160. package/platforms/2600.md +137 -0
  161. package/platforms/unity.md +329 -0
  162. package/references/composer-skill-porting.md +152 -0
  163. package/references/cost-models.md +163 -0
  164. package/references/ip-risk.md +246 -0
  165. package/references/plain-english-ux.md +275 -0
  166. package/resilience/context-pruning.md +67 -0
  167. package/resilience/continue-here.md +62 -0
  168. package/scm/changelog.md +276 -0
  169. package/scm/git.md +139 -0
  170. package/scm/github.md +265 -0
  171. package/secrets/.gitkeep +0 -0
  172. package/skills/deft-build/SKILL.md +20 -0
  173. package/skills/deft-directive-article-review/SKILL.md +156 -0
  174. package/skills/deft-directive-build/SKILL.md +302 -0
  175. package/skills/deft-directive-cost/SKILL.md +201 -0
  176. package/skills/deft-directive-debug/SKILL.md +140 -0
  177. package/skills/deft-directive-decompose/SKILL.md +96 -0
  178. package/skills/deft-directive-gh-arch/SKILL.md +160 -0
  179. package/skills/deft-directive-gh-slice/SKILL.md +199 -0
  180. package/skills/deft-directive-glossary/SKILL.md +118 -0
  181. package/skills/deft-directive-interview/SKILL.md +528 -0
  182. package/skills/deft-directive-pre-pr/SKILL.md +131 -0
  183. package/skills/deft-directive-probe/SKILL.md +127 -0
  184. package/skills/deft-directive-refinement/SKILL.md +403 -0
  185. package/skills/deft-directive-release/SKILL.md +266 -0
  186. package/skills/deft-directive-review-cycle/SKILL.md +401 -0
  187. package/skills/deft-directive-setup/SKILL.md +717 -0
  188. package/skills/deft-directive-swarm/SKILL.md +989 -0
  189. package/skills/deft-directive-sync/SKILL.md +288 -0
  190. package/skills/deft-directive-triage/SKILL.md +137 -0
  191. package/skills/deft-directive-write-skill/SKILL.md +169 -0
  192. package/skills/deft-interview/SKILL.md +16 -0
  193. package/skills/deft-pre-pr/SKILL.md +16 -0
  194. package/skills/deft-review-cycle/SKILL.md +16 -0
  195. package/skills/deft-roadmap-refresh/SKILL.md +16 -0
  196. package/skills/deft-setup/SKILL.md +20 -0
  197. package/skills/deft-swarm/SKILL.md +16 -0
  198. package/skills/deft-sync/SKILL.md +16 -0
  199. package/strategies/README.md +83 -0
  200. package/strategies/artifact-guards.md +85 -0
  201. package/strategies/bdd.md +115 -0
  202. package/strategies/brownfield.md +7 -0
  203. package/strategies/discuss.md +129 -0
  204. package/strategies/emit-hints.md +69 -0
  205. package/strategies/enterprise.md +193 -0
  206. package/strategies/interview.md +551 -0
  207. package/strategies/map.md +179 -0
  208. package/strategies/probe.md +151 -0
  209. package/strategies/rapid.md +155 -0
  210. package/strategies/research.md +155 -0
  211. package/strategies/roadmap.md +9 -0
  212. package/strategies/speckit.md +437 -0
  213. package/strategies/v0-20-contract.md +134 -0
  214. package/strategies/yolo.md +169 -0
  215. package/swarm/swarm.md +300 -0
  216. package/templates/COST-ESTIMATE.md +114 -0
  217. package/templates/PULL_REQUEST_TEMPLATE.md +35 -0
  218. package/templates/agent-prompt-preamble.md +409 -0
  219. package/templates/agents-entry.md +211 -0
  220. package/templates/agents-entry.placeholders.md +75 -0
  221. package/templates/embed.go +20 -0
  222. package/templates/embed_test.go +36 -0
  223. package/templates/make-spec-example.md +9 -0
  224. package/templates/make-spec.md +246 -0
  225. package/templates/project.md.template +52 -0
  226. package/templates/specification.md +1 -0
  227. package/templates/swarm-greptile-poller-prompt.md +556 -0
  228. package/templates/user.md.template +31 -0
  229. package/tools/RWLDL.md +80 -0
  230. package/tools/greptile.md +141 -0
  231. package/tools/installer.md +23 -0
  232. package/tools/taskfile-migration.md +32 -0
  233. package/tools/taskfile.md +185 -0
  234. package/tools/telemetry.md +285 -0
  235. package/vbrief/schemas/cache-meta.schema.json +137 -0
  236. package/vbrief/schemas/candidates.schema.json +130 -0
  237. package/vbrief/schemas/codebase-map.schema.json +213 -0
  238. package/vbrief/schemas/lessons-pack.schema.json +134 -0
  239. package/vbrief/schemas/patterns-pack.schema.json +84 -0
  240. package/vbrief/schemas/rules-pack.schema.json +105 -0
  241. package/vbrief/schemas/skills-pack.schema.json +94 -0
  242. package/vbrief/schemas/slices.schema.json +87 -0
  243. package/vbrief/schemas/strategies-pack.schema.json +89 -0
  244. package/vbrief/schemas/swarm-spec-pack.schema.json +84 -0
  245. package/vbrief/schemas/vbrief-core.schema.json +1022 -0
  246. package/vbrief/vbrief.md +684 -0
  247. package/verification/integration.md +76 -0
  248. package/verification/plan-checking.md +85 -0
  249. package/verification/uat.md +60 -0
  250. package/verification/verification.md +117 -0
@@ -0,0 +1,259 @@
1
+ # C# Standards
2
+
3
+ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
4
+
5
+ **⚠️ See also**: [main.md](../../main.md) | [PROJECT.md](../../PROJECT.md) | [telemetry.md](../tools/telemetry.md)
6
+
7
+ **Stack**: C# 12+/.NET 8+ (LTS), SDK-style projects; Web: ASP.NET Core/Minimal APIs; Testing: xUnit + NSubstitute + FluentAssertions; Analysis: Roslyn Analyzers, StyleCop.Analyzers
8
+
9
+ ## Standards
10
+
11
+ ### Documentation
12
+ - ! XML documentation comments (`///`) on all public types, methods, properties, and constants
13
+ - ! Document `<param>`, `<returns>`, `<exception>`, `<summary>` for public/protected members
14
+ - ~ Use `<see cref=""/>` and `<inheritdoc/>` to reduce duplication
15
+ - ~ Use `<remarks>` for complex behaviors or threading considerations
16
+
17
+ ### Testing
18
+ See [testing.md](../coding/testing.md).
19
+
20
+ - ! Use xUnit (`[Fact]`, `[Theory]`, `[InlineData]`)
21
+ - ! Use NSubstitute or Moq for mocking; FluentAssertions for readable assertions
22
+ - ≉ Use MSTest or NUnit for new code (maintain existing suites only)
23
+ - Files: `*Tests.cs` in a parallel `*.Tests` project
24
+
25
+ ### Coverage
26
+ - ! ≥85% coverage
27
+ - ! Count src/\*
28
+ - ! Exclude entry points, generated code, migrations, program bootstrapping
29
+
30
+ ### Style
31
+ - ! Use `.editorconfig` for code style (project root, checked in)
32
+ - ! Enable Roslyn analyzers and StyleCop.Analyzers as project dependencies
33
+ - ! Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions)
34
+ - ! SDK-style `.csproj` with `<Nullable>enable</Nullable>` and `<ImplicitUsings>enable</ImplicitUsings>`
35
+ - ! `<TreatWarningsAsErrors>true</TreatWarningsAsErrors>` in CI builds
36
+
37
+ ### Naming Conventions
38
+ - ! `PascalCase` for types, methods, properties, events, namespaces, public fields
39
+ - ! `camelCase` for parameters, local variables
40
+ - ! `_camelCase` for private fields: `private readonly ILogger _logger;`
41
+ - ! `IPascalCase` for interfaces: `IRepository`, `ILogger`
42
+ - ! `UPPER_SNAKE_CASE` only for interop constants; otherwise `PascalCase` for const
43
+ - ! Async methods suffixed with `Async`: `GetUserAsync()`, `SaveAsync()`
44
+ - ⊗ Hungarian notation or type prefixes (`strName`, `intCount`)
45
+
46
+ ### Modern Language Features (C# 12+)
47
+ - ! Use records for immutable data carriers: `record UserDto(long Id, string Name);`
48
+ - ! Use `required` properties for mandatory init-only data
49
+ - ! Use primary constructors for simple DI and parameter capture
50
+ - ! Use `init` accessors for immutable-after-construction properties
51
+ - ! Use pattern matching (`is`, `switch` expressions, list patterns)
52
+ - ! Use raw string literals (`"""`) for multi-line strings
53
+ - ~ Use `file`-scoped types for implementation-only helpers
54
+ - ~ Use collection expressions (`[1, 2, 3]`) where supported (C# 12+)
55
+ - ≉ Use verbose constructors + field assignments when primary constructors suffice
56
+
57
+ ### Nullable Reference Types
58
+ - ! Enable `<Nullable>enable</Nullable>` in all projects
59
+ - ! Annotate API boundaries with `?` for nullable; treat non-nullable as contract
60
+ - ! Handle `null` at system boundaries (deserialization, DB, external APIs)
61
+ - ⊗ Use `null!` (null-forgiving operator) except as last resort with documented reason
62
+ - ⊗ Return `null` from methods typed as non-nullable
63
+
64
+ ### Resource Management
65
+ - ! Use `using` declarations or `using` blocks for all `IDisposable` resources
66
+ - ! Implement `IAsyncDisposable` for types holding async resources
67
+ - ! Use `await using` for async disposal
68
+ - ⊗ Call `.Dispose()` manually in a `finally` block (use `using` instead)
69
+ - ⊗ Implement finalizers unless wrapping unmanaged resources directly
70
+
71
+ ### Error Handling
72
+ - ! Throw specific exception types: `ArgumentNullException`, `InvalidOperationException`, etc.
73
+ - ! Use `ArgumentNullException.ThrowIfNull()` (C# 10+) for guard clauses
74
+ - ! Include context in exception messages (what failed, relevant IDs)
75
+ - ⊗ Catch `Exception` or `SystemException` broadly — catch the most specific type
76
+ - ⊗ Swallow exceptions (empty catch blocks)
77
+ - ⊗ Use exceptions for flow control
78
+ - ~ Use Result/OneOf patterns for expected failures in domain logic
79
+ - ~ Log at the handling boundary, not at every catch-and-rethrow
80
+
81
+ ### Async/Await
82
+ - ! Use `async`/`await` for all I/O-bound operations
83
+ - ! Return `Task`/`ValueTask` — never `async void` (except event handlers)
84
+ - ! Use `CancellationToken` in all async public APIs
85
+ - ! Pass `CancellationToken` through the entire call chain
86
+ - ⊗ Use `.Result` or `.Wait()` on tasks (deadlock risk)
87
+ - ⊗ Use `Task.Run()` to wrap sync-over-async (hides problems)
88
+ - ~ Use `ValueTask` for hot-path methods that often complete synchronously
89
+ - ~ Use `ConfigureAwait(false)` in library code (not in app/UI code)
90
+
91
+ ### Dependency Injection
92
+ - ! Use constructor injection; ⊗ service locator pattern (`IServiceProvider.GetService`)
93
+ - ! Register services with appropriate lifetimes: `Singleton`, `Scoped`, `Transient`
94
+ - ! Inject interfaces, not implementations
95
+ - ⊗ Inject `IServiceProvider` into business logic classes
96
+ - ~ Use `IOptions<T>` / `IOptionsSnapshot<T>` for configuration binding
97
+ - ≉ Use `static` helper classes for behavior that should be injected
98
+
99
+ ### Collections & LINQ
100
+ - ! Prefer immutable collections for shared/public data: `IReadOnlyList<T>`, `IReadOnlyDictionary<K,V>`
101
+ - ! Use LINQ for declarative transforms; ⊗ for side-effectful iterations
102
+ - ~ Materialize queries early to avoid multiple enumeration (`.ToList()`, `.ToArray()`)
103
+ - ~ Use `Span<T>` / `ReadOnlySpan<T>` for performance-critical slicing
104
+ - ⊗ Return `IEnumerable<T>` backed by a deferred query from public APIs without documentation
105
+
106
+ ### Database (EF Core)
107
+ - ! Use parameterized queries (EF Core does this automatically)
108
+ - ! Use `AsNoTracking()` for read-only queries
109
+ - ! Use explicit transactions for multi-step writes
110
+ - ~ Use repository pattern or query objects; ≉ scatter `DbContext` calls across controllers
111
+ - ~ Use migrations for schema evolution
112
+ - ⊗ Use raw SQL with string interpolation (SQL injection risk — use `FromSqlInterpolated`)
113
+
114
+ ### Telemetry
115
+ - See [telemetry.md](../tools/telemetry.md)
116
+ - ~ Structured logging (Serilog or Microsoft.Extensions.Logging) for production
117
+ - ~ Sentry.io for error tracking
118
+ - ~ Prometheus/Grafana or Application Insights for metrics
119
+ - ? OpenTelemetry .NET for distributed tracing
120
+
121
+ ### Safety
122
+ - ⊗ Hardcode secrets, keys, or credentials in source
123
+ - ! Use User Secrets (dev), environment variables, or Azure Key Vault (prod)
124
+ - ! Validate all external input (model binding validation, FluentValidation)
125
+ - ~ Scan dependencies with `dotnet list package --vulnerable` or Snyk/OWASP
126
+
127
+ ## Commands
128
+
129
+ See [commands.md](./commands.md).
130
+
131
+ ## Patterns
132
+
133
+ ### Testing (xUnit + FluentAssertions + NSubstitute)
134
+ ```csharp
135
+ public class CalculatorTests {
136
+ private readonly Calculator _sut = new();
137
+
138
+ [Fact] public void Add_ReturnsSum() => _sut.Add(2, 3).Should().Be(5);
139
+
140
+ [Theory] [InlineData(0,1,1)] [InlineData(-1,1,0)]
141
+ public void Add_Parameterized(int a, int b, int expected) =>
142
+ _sut.Add(a, b).Should().Be(expected);
143
+
144
+ [Fact] public void Divide_ByZero_Throws() =>
145
+ ((Action)(() => _sut.Divide(10, 0))).Should().Throw<DivideByZeroException>();
146
+ }
147
+
148
+ public class UserServiceTests {
149
+ private readonly IUserRepository _repo = Substitute.For<IUserRepository>();
150
+ private readonly UserService _sut;
151
+ public UserServiceTests() => _sut = new UserService(_repo);
152
+
153
+ [Fact] public async Task GetByIdAsync_ExistingUser_ReturnsUser() {
154
+ var expected = new User(1, "Alice");
155
+ _repo.GetByIdAsync(1).Returns(expected);
156
+ (await _sut.GetByIdAsync(1)).Should().Be(expected);
157
+ await _repo.Received(1).GetByIdAsync(1);
158
+ }
159
+ }
160
+ ```
161
+
162
+ ### Records, Primary Constructors & Pattern Matching
163
+ ```csharp
164
+ public record UserDto(long Id, string Name, string Email);
165
+
166
+ public class CreateOrderRequest {
167
+ public required string ProductId { get; init; }
168
+ public required int Quantity { get; init; }
169
+ public string? Notes { get; init; }
170
+ }
171
+
172
+ public abstract record Result<T>;
173
+ public record Success<T>(T Value) : Result<T>;
174
+ public record Failure<T>(string Error, Exception? Cause = null) : Result<T>;
175
+
176
+ string Describe<T>(Result<T> r) => r switch {
177
+ Success<T> s => $"OK: {s.Value}", Failure<T> f => $"Error: {f.Error}", _ => "Unknown"
178
+ };
179
+
180
+ // Primary constructor DI (C# 12)
181
+ public class UserService(IUserRepository repo, ILogger<UserService> logger) {
182
+ public async Task<User?> GetByIdAsync(long id, CancellationToken ct = default) =>
183
+ await repo.GetByIdAsync(id, ct);
184
+ }
185
+ ```
186
+
187
+ ### Async/Await & Resources
188
+ ```csharp
189
+ // CancellationToken through entire chain
190
+ public async Task<IReadOnlyList<Order>> GetOrdersAsync(long userId, CancellationToken ct = default) {
191
+ await using var conn = await _dataSource.OpenConnectionAsync(ct);
192
+ return await conn.QueryAsync<Order>("SELECT * FROM orders WHERE user_id = @Id",
193
+ new { Id = userId }).ToListAsync(ct);
194
+ }
195
+
196
+ // using declarations for IDisposable/IAsyncDisposable
197
+ await using var stream = File.OpenRead(path);
198
+ using var reader = new StreamReader(stream);
199
+ var content = await reader.ReadToEndAsync();
200
+
201
+ // Minimal API
202
+ var app = WebApplication.CreateBuilder(args).Build();
203
+ app.MapGet("/users/{id}", async (long id, IUserService svc, CancellationToken ct) =>
204
+ await svc.GetByIdAsync(id, ct) is { } user ? Results.Ok(user) : Results.NotFound());
205
+ app.Run();
206
+ ```
207
+
208
+ ## Build Configuration
209
+
210
+ **`.csproj` key settings**:
211
+ - ! `<TargetFramework>net8.0</TargetFramework>`
212
+ - ! `<Nullable>enable</Nullable>`, `<ImplicitUsings>enable</ImplicitUsings>`
213
+ - ! `<TreatWarningsAsErrors>true</TreatWarningsAsErrors>`
214
+ - ! `<AnalysisLevel>latest-recommended</AnalysisLevel>`
215
+ - ! `StyleCop.Analyzers` as `PrivateAssets="all"` PackageReference
216
+
217
+ **Test project deps**: `Microsoft.NET.Test.Sdk`, `xunit`, `xunit.runner.visualstudio`, `NSubstitute`, `FluentAssertions`, `coverlet.collector`
218
+
219
+ **`.editorconfig` key rules**: `indent_size = 4`, `file_scoped` namespaces, `simple_using_statement`, `require_accessibility_modifiers = always`, `_camelCase` private fields
220
+
221
+ ## Anti-Patterns
222
+
223
+ Items marked ⊗ in Standards above are not repeated here.
224
+
225
+ - ≉ **Verbose constructors**: Use primary constructors (C# 12) or records
226
+ - ≉ **Manual null guards**: Use `ArgumentNullException.ThrowIfNull()`
227
+ - ≉ **`IEnumerable<T>` as public return**: Materialize or use `IReadOnlyList<T>`
228
+ - ≉ **God classes**: Keep <500 lines; extract services/handlers
229
+ - ≉ **`static` utility classes**: Inject via DI for testability
230
+
231
+ ## Hygiene
232
+
233
+ **Types:**
234
+ - ⊗ `object` as parameter or return type where a concrete or generic type is knowable
235
+ - ⊗ `dynamic` outside genuine late-binding scenarios (COM interop, DLR, legacy)
236
+ - ⊗ `null!` (null-forgiving operator) to suppress nullable warnings without a documented invariant
237
+ - ⊗ `#pragma warning disable` without an inline comment explaining why it is safe
238
+
239
+ **Error handling:**
240
+ - ⊗ Empty `catch {}` or `catch (Exception) { }` — handle or re-throw
241
+ - ⊗ `catch (Exception e) { }` that swallows without logging — use structured logging and propagate
242
+ - ⊗ Returning `null` or a default value from a public method to mask an exception
243
+
244
+ **Dead code:**
245
+ - ~ Roslyn IDE analyzers report unused private members; treat `IDE0051` as a warning-as-error in CI
246
+ - ~ Run `dotnet-unused` for projects with large public APIs to detect unreferenced symbols
247
+ - ⊗ `#pragma warning disable IDE0051` to hide dead code from analysis instead of deleting it
248
+
249
+ ## Compliance Checklist
250
+
251
+ - ! XML doc comments on all public APIs
252
+ - ! See [testing.md](../coding/testing.md) for testing requirements
253
+ - ! Use xUnit + FluentAssertions + NSubstitute
254
+ - ! Nullable reference types enabled; `TreatWarningsAsErrors` in CI
255
+ - ! Records for data carriers; primary constructors for simple DI
256
+ - ! `async`/`await` with `CancellationToken` for all I/O
257
+ - ! `using` declarations for all `IDisposable`/`IAsyncDisposable`
258
+ - ⊗ `async void`, `.Result`/`.Wait()`, service locator, null-forgiving `null!`
259
+ - ! Run `task check` before commit
@@ -0,0 +1,183 @@
1
+ # Dart Standards
2
+
3
+ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
4
+
5
+ **⚠️ See also**: [main.md](../../main.md) | [PROJECT.md](../../PROJECT.md)
6
+
7
+ **Stack**: Dart 3.x+; Framework: Flutter (mobile/web) or standalone; Testing: `package:test` / `flutter_test`; Lint: `analysis_options.yaml` + custom_lint; Format: `dart format`; Docs: dartdoc
8
+
9
+ ## Standards
10
+
11
+ ### Documentation
12
+ - ! dartdoc comments (`///`) on all public classes, functions, properties, and libraries
13
+ - ! Document parameters, return values, and exceptions for public API
14
+ - ! Library-level doc comments (`/// {@category ...}`) for package organization
15
+ - ~ Use `[ClassName]` and `[methodName]` for cross-references in doc comments
16
+ - ~ Include code examples in `/// ```dart` blocks
17
+
18
+ ### Testing
19
+ See [testing.md](../coding/testing.md).
20
+
21
+ - ! Use `package:test` (Dart) or `flutter_test` (Flutter) for unit tests
22
+ - ! Place tests in `test/` directory mirroring `lib/` structure
23
+ - ! Test widget trees with `testWidgets()` and `WidgetTester` (Flutter)
24
+ - ~ Use `mockito` or `mocktail` for mocking dependencies
25
+ - ~ Use golden tests for UI regression testing (Flutter)
26
+
27
+ ### Coverage
28
+ - ! ≥80% coverage (measured via `dart test --coverage` or `flutter test --coverage`)
29
+ - ! Count lib/**
30
+ - ! Exclude generated files (`*.g.dart`, `*.freezed.dart`), entry points
31
+
32
+ ### Style
33
+ - ! Follow [Effective Dart](https://dart.dev/effective-dart) guidelines
34
+ - ! Use `analysis_options.yaml` with recommended lints enabled
35
+ - ! Use `dart format` (or `flutter format`) for all code
36
+ - ! 2-space indentation
37
+ - ! Line length ≤80 characters
38
+ - ! Enable `strict-casts`, `strict-inference`, `strict-raw-types` in analysis options
39
+
40
+ ### Naming Conventions
41
+ - ! `lowerCamelCase` for variables, functions, parameters, named parameters
42
+ - ! `UpperCamelCase` for classes, enums, typedefs, extensions, mixins
43
+ - ! `lowerCamelCase` for library/package names and file names
44
+ - ! `SCREAMING_SNAKE_CASE` for compile-time constants only when following Flutter convention
45
+ - ! Prefix private members with `_`: `_internalState`
46
+ - ! Prefix boolean variables/getters with `is`, `has`, `can`: `isLoading`, `hasError`
47
+ - ⊗ Hungarian notation or type prefixes
48
+
49
+ ### Null Safety
50
+ - ! Use sound null safety (Dart 3.x enforces this)
51
+ - ! Use `?` for nullable types only when null is a valid state
52
+ - ! Use `late` only when initialization is guaranteed before access
53
+ - ! Prefer `??` (if-null) and `?.` (null-aware) over null checks
54
+ - ⊗ Force-unwrap (`!`) without prior null check or assertion
55
+ - ≉ `late` as a workaround for poor initialization design
56
+
57
+ ### Immutability
58
+ - ! Use `final` for variables that are assigned once
59
+ - ! Use `const` for compile-time constants and constructors
60
+ - ! Prefer immutable data classes (use `freezed` or manual `copyWith`)
61
+ - ≉ Mutable state where `final` + rebuild pattern suffices (esp. Flutter)
62
+
63
+ ### Classes & Types
64
+ - ! Use `sealed class` (Dart 3) for exhaustive type hierarchies
65
+ - ! Use `enum` with members for fixed sets of values
66
+ - ! Use extension types for zero-cost wrappers
67
+ - ! Use mixins for shared behavior across unrelated classes
68
+ - ~ Use `typedef` for complex function signatures
69
+ - ⊗ Deep inheritance hierarchies (>3 levels) — prefer composition
70
+
71
+ ### Async & Concurrency
72
+ - ! Use `async`/`await` for asynchronous operations
73
+ - ! Always handle errors from Futures (`try`/`catch` or `.catchError`)
74
+ - ! Use `Stream` for reactive data flows; `StreamController` for custom streams
75
+ - ! Close `StreamController` and cancel `StreamSubscription` to avoid leaks
76
+ - ⊗ Fire-and-forget Futures without error handling
77
+ - ~ Use `Isolate` for CPU-intensive work (keeps UI responsive in Flutter)
78
+ - ~ Use `compute()` helper for simple isolate tasks in Flutter
79
+
80
+ ### State Management (Flutter)
81
+ - ~ Choose one state management approach per project and document it
82
+ - ~ Options: Riverpod, Bloc/Cubit, Provider, signals
83
+ - ! Separate business logic from UI (no business logic in `build()`)
84
+ - ! Dispose controllers, streams, and subscriptions in `dispose()`
85
+ - ⊗ Calling `setState` from outside the widget or after disposal
86
+
87
+ ### Dependencies
88
+ - ! Pin dependency versions in `pubspec.yaml` (use `^` for semver ranges)
89
+ - ! Use `pubspec.lock` committed for applications (not for packages)
90
+ - ! Minimize dependencies; prefer `dart:*` core libraries
91
+ - ~ Use `dependency_overrides` only for testing, never in production
92
+ - ~ Run `dart pub outdated` regularly
93
+
94
+ ### Code Generation
95
+ - ! Use `build_runner` for code generation (`json_serializable`, `freezed`, etc.)
96
+ - ! Commit generated files or document regeneration in task commands
97
+ - ! Exclude generated files from lint and coverage
98
+
99
+ ### Security
100
+ - ⊗ Hardcode secrets or credentials in source (esp. Flutter — compiled but extractable)
101
+ - ! Validate all external inputs (user data, API responses, deep links)
102
+ - ~ Use `flutter_secure_storage` for sensitive data on device
103
+ - ~ Use certificate pinning for critical API connections
104
+
105
+ ### Telemetry
106
+ - ~ Use `package:logging` or structured logger for backend Dart
107
+ - ~ Use Firebase Crashlytics / Sentry for Flutter crash reporting
108
+ - ? OpenTelemetry for backend Dart services
109
+
110
+ ## Commands
111
+
112
+ See [commands.md](./commands.md).
113
+
114
+ ## Patterns
115
+
116
+ ### Sealed Class + Pattern Matching (Dart 3)
117
+ ```dart
118
+ sealed class Result<T> { const Result(); }
119
+ class Success<T> extends Result<T> { final T data; const Success(this.data); }
120
+ class Failure<T> extends Result<T> { final String message; const Failure(this.message); }
121
+
122
+ String display(Result<User> r) => switch (r) {
123
+ Success(data: final u) => 'Welcome, ${u.name}',
124
+ Failure(message: final m) => 'Error: $m',
125
+ };
126
+ ```
127
+
128
+ ### Testing (Flutter Widget)
129
+ ```dart
130
+ testWidgets('Counter increments', (tester) async {
131
+ await tester.pumpWidget(const MyApp());
132
+ expect(find.text('0'), findsOneWidget);
133
+ await tester.tap(find.byIcon(Icons.add));
134
+ await tester.pump();
135
+ expect(find.text('1'), findsOneWidget);
136
+ });
137
+ ```
138
+
139
+ ### Repository Pattern
140
+ ```dart
141
+ abstract interface class UserRepository {
142
+ Future<User?> findById(int id);
143
+ Future<List<User>> findAll({int limit = 20, int offset = 0});
144
+ }
145
+
146
+ class ApiUserRepository implements UserRepository {
147
+ final HttpClient _client;
148
+ ApiUserRepository(this._client);
149
+
150
+ @override
151
+ Future<User?> findById(int id) async {
152
+ final response = await _client.get(Uri.parse('/users/$id'));
153
+ if (response.statusCode == 404) return null;
154
+ return User.fromJson(jsonDecode(response.body));
155
+ }
156
+ }
157
+ ```
158
+
159
+ ### Extension Types (Dart 3)
160
+ ```dart
161
+ extension type UserId(int value) { factory UserId.parse(String s) => UserId(int.parse(s)); }
162
+ extension type Email(String value) { bool get isValid => value.contains('@'); }
163
+ ```
164
+
165
+ ## Anti-Patterns
166
+
167
+ Items marked ⊗ in Standards above are not repeated here.
168
+
169
+ - ≉ **`late` as lazy init workaround**: Design proper initialization
170
+ - ≉ **Deep inheritance (>3 levels)**: Prefer composition/mixins
171
+ - ≉ **`dynamic` type**: Use specific types; `Object?` if truly unknown
172
+ - ≉ **`print()` for logging**: Use `package:logging`
173
+
174
+ ## Compliance Checklist
175
+
176
+ - ! dartdoc on all public API
177
+ - ! See [testing.md](../coding/testing.md) for testing requirements
178
+ - ! Unit + widget tests; ≥80% coverage
179
+ - ! `dart format` + `dart analyze` with strict options enforced
180
+ - ! Effective Dart conventions; sound null safety; `final`/`const` by default
181
+ - ! Sealed classes for exhaustive hierarchies; pattern matching
182
+ - ⊗ `!` without check, fire-and-forget Futures, `dynamic`, business logic in `build()`
183
+ - ! Run `task check` before commit
@@ -0,0 +1,218 @@
1
+ # Delphi / Object Pascal Standards
2
+
3
+ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
4
+
5
+ **⚠️ See also**: [main.md](../../main.md) | [PROJECT.md](../../PROJECT.md) | [telemetry.md](../tools/telemetry.md)
6
+
7
+ **Stack**: Delphi 12+/Object Pascal, RAD Studio; GUI: VCL (Windows), FMX (cross-platform); DB: FireDAC; Testing: DUnitX
8
+
9
+ ## Standards
10
+
11
+ ### Documentation
12
+ - ! XML documentation comments (`///`) for all public types, methods, and properties
13
+ - ! Unit header comment: purpose, author, date, dependencies
14
+ - ~ Document preconditions, postconditions, and exceptions on public methods
15
+ - ~ Use `{$REGION}` / `{$ENDREGION}` to organize long units
16
+
17
+ ### Testing
18
+ See [testing.md](../coding/testing.md).
19
+
20
+ - ! Use DUnitX for all new test projects
21
+ - ≉ Use legacy DUnit for new code (maintain existing DUnit suites only)
22
+ - Files: `Test*.pas` or `*Tests.pas`
23
+
24
+ ### Coverage
25
+ - ! ≥85% coverage
26
+ - ! Count src/\*
27
+ - ! Exclude entry points, generated code, DFM/FMX form logic
28
+
29
+ ### Style
30
+ - ! Follow [Embarcadero Object Pascal Style Guide](https://docwiki.embarcadero.com/RADStudio/en/Delphi's_Object_Pascal_Style_Guide)
31
+ - ! Use PascalCase (InfixCaps) for all identifiers; ⊗ underscores (except header translations)
32
+ - ! Reserved words and keywords in lowercase (`begin`, `end`, `string`, `nil`)
33
+ - ! Two-space indentation (no tabs)
34
+ - ⊗ Hungarian notation (except header translations)
35
+ - ~ Use [Pascal Analyzer](https://www.peganza.com/) or [FixInsight](https://www.yourkit.com/) for static analysis
36
+
37
+ ### Naming Conventions
38
+ - ! Types prefixed with `T`: `TCustomer`, `TOrderStatus`
39
+ - ! Interfaces prefixed with `I`: `IRepository`, `ILogger`
40
+ - ! Exception types prefixed with `E`: `EInvalidArgument`, `ENotFound`
41
+ - ! Private fields prefixed with `F`: `FName`, `FCount`
42
+ - ! Enumeration members prefixed with 2–3 char mnemonic: `TColor = (clRed, clGreen, clBlue)`
43
+ - ! Component variables prefixed by type abbreviation: `btnSubmit`, `edtName`, `lblTitle`
44
+ - ~ Constants in PascalCase (not ALL_CAPS): `const MaxRetries = 3;`
45
+ - ~ Descriptive names; prefer `ObjectPointer` over `ObjPtr`
46
+
47
+ ### Types
48
+ - ! Use strong typing: enumerations, records, distinct types over raw integers/strings
49
+ - ! Use generics (`TList<T>`, `TDictionary<K,V>`, `TObjectList<T>`) over untyped containers
50
+ - ⊗ Use `Variant` / `OleVariant` except when required for COM interop
51
+ - ⊗ Use untyped containers (`TList`, `TStringList` for non-string data)
52
+ - ~ Use `TArray<T>` over dynamic array declarations
53
+ - ~ Use `Double` for floating-point; ≉ use `Real` (backward compat only)
54
+ - ~ Use `NativeInt`/`NativeUInt` for pointer-sized integers
55
+
56
+ ### Memory Management
57
+ - ! Every object you create, you must free (clear ownership model)
58
+ - ! Use `FreeAndNil` over bare `Free` for field cleanup in destructors
59
+ - ! Override `Destroy` (not `Free`); always mark with `override`
60
+ - ! Use `try..finally` to guarantee cleanup of locally created objects
61
+ - ⊗ Call `Destroy` directly; always use `Free` or `FreeAndNil`
62
+ - ~ Use TComponent ownership (`AOwner` parameter) for form/component lifecycles
63
+ - ~ Use interfaces (reference counting) for shared/cross-boundary objects
64
+ - ~ Use managed records (`class operator Initialize/Finalize`) for RAII patterns (Delphi 10.4+)
65
+ - ≉ Use `GetMem`/`FreeMem` unless writing low-level or performance-critical code
66
+
67
+ ### Interfaces
68
+ - ! Use interfaces for abstraction, testability, and dependency injection
69
+ - ! Declare interfaces in a shared unit separate from implementations
70
+ - ~ Use interface delegation (`implements` keyword) to compose behavior
71
+ - ~ Prefer interface references over class references for cross-module boundaries
72
+ - ⊗ Mix interface references and object references to the same instance (prevents double-free / ref-count issues)
73
+
74
+ ### Error Handling
75
+ - ! Use exceptions for exceptional/unexpected errors
76
+ - ! Derive custom exceptions from `Exception` or `EArgumentException`, etc.
77
+ - ! Use `try..except` with specific exception types; ⊗ bare `except` without re-raise
78
+ - ! Use `try..finally` for resource cleanup (separate from `try..except`)
79
+ - ⊗ Silently swallow exceptions (empty `except` blocks)
80
+ - ~ Use `EAbort` / `Abort` for non-error flow control (e.g., cancel operations)
81
+ - ~ Log exceptions with context before re-raising
82
+
83
+ ### Concurrency
84
+ - ! Use `TTask` / `TParallel` (Parallel Programming Library) for new async work
85
+ - ! Never access VCL/FMX controls from background threads; use `TThread.Synchronize` or `TThread.Queue`
86
+ - ~ Use `TThreadPool` for managing concurrent workloads
87
+ - ~ Use `TMonitor` or `TCriticalSection` for shared state protection
88
+ - ⊗ Use `Suspend`/`Resume` on threads (deprecated, unsafe)
89
+ - ≉ Directly subclass `TThread` when PPL tasks suffice
90
+
91
+ ### Database (FireDAC)
92
+ - ! Use parameterized queries; ⊗ string concatenation for SQL
93
+ - ! Use `TFDConnection` with connection definitions (not hard-coded connection strings)
94
+ - ~ Use `TFDQuery` over `TFDTable` for production code
95
+ - ~ Wrap multi-step operations in explicit transactions
96
+ - ⊗ Use BDE (Borland Database Engine) — fully deprecated
97
+
98
+ ### Telemetry
99
+ - See [telemetry.md](../tools/telemetry.md)
100
+ - ~ Structured logging (CodeSite, SmartInspect, or custom structured logger) for production
101
+ - ~ Sentry.io (via REST) or equivalent for error tracking
102
+ - ? OpenTelemetry (via REST integration) for distributed tracing
103
+
104
+ ### Safety
105
+ - ⊗ Hardcode API keys or secrets in source or shipped binaries
106
+ - ! Validate all external input (user input, file data, network responses)
107
+ - ~ Use `{$WARN}` directives to treat warnings as errors in CI
108
+ - ~ Enable range checking (`{$R+}`) and overflow checking (`{$Q+}`) in debug builds
109
+
110
+ ## Commands
111
+
112
+ See [commands.md](./commands.md).
113
+
114
+ ## Patterns
115
+
116
+ ### Testing (DUnitX)
117
+ ```pascal
118
+ unit TestCalculator;
119
+ interface
120
+ uses DUnitX.TestFramework, Calculator;
121
+ type
122
+ [TestFixture]
123
+ TTestCalculator = class
124
+ private
125
+ FSut: TCalculator;
126
+ public
127
+ [Setup] procedure Setup;
128
+ [TearDown] procedure TearDown;
129
+ [Test] procedure Add_TwoPositiveNumbers_ReturnsSum;
130
+ [Test] [TestCase('Zero','0,1,1')] [TestCase('Neg','-1,1,0')]
131
+ procedure Add_Parameterized(const A, B, Expected: Integer);
132
+ end;
133
+ implementation
134
+ procedure TTestCalculator.Setup; begin FSut := TCalculator.Create end;
135
+ procedure TTestCalculator.TearDown; begin FreeAndNil(FSut) end;
136
+ procedure TTestCalculator.Add_TwoPositiveNumbers_ReturnsSum;
137
+ begin Assert.AreEqual(5, FSut.Add(2, 3)) end;
138
+ procedure TTestCalculator.Add_Parameterized(const A, B, Expected: Integer);
139
+ begin Assert.AreEqual(Expected, FSut.Add(A, B)) end;
140
+ initialization
141
+ TDUnitX.RegisterTestFixture(TTestCalculator);
142
+ end.
143
+ ```
144
+
145
+ ### Interface-Based Design
146
+ ```pascal
147
+ unit Services.Interfaces;
148
+ interface
149
+ type
150
+ ILogger = interface
151
+ ['{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}']
152
+ procedure Info(const Msg: string);
153
+ procedure Error(const Msg: string; E: Exception = nil);
154
+ end;
155
+ IRepository<T: class> = interface
156
+ ['{B2C3D4E5-F6A7-8901-BCDE-F12345678901}']
157
+ function GetById(const Id: Integer): T;
158
+ function GetAll: TArray<T>;
159
+ procedure Save(const Entity: T);
160
+ procedure Delete(const Id: Integer);
161
+ end;
162
+ implementation
163
+ end.
164
+ ```
165
+
166
+ ### Resource Cleanup & Generics
167
+ ```pascal
168
+ procedure ProcessFile(const FileName: string);
169
+ var Stream: TFileStream; Reader: TStreamReader;
170
+ begin
171
+ Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
172
+ try
173
+ Reader := TStreamReader.Create(Stream);
174
+ try while not Reader.EndOfStream do ProcessLine(Reader.ReadLine);
175
+ finally FreeAndNil(Reader) end;
176
+ finally FreeAndNil(Stream) end;
177
+ end;
178
+
179
+ var Customers: TObjectList<TCustomer>;
180
+ begin
181
+ Customers := TObjectList<TCustomer>.Create(True); // OwnsObjects
182
+ try
183
+ for var C in Customers do DoWork(C);
184
+ finally Customers.Free end;
185
+ end;
186
+ ```
187
+
188
+ ### Async with PPL
189
+ ```pascal
190
+ procedure TMainForm.btnProcessClick(Sender: TObject);
191
+ begin
192
+ btnProcess.Enabled := False;
193
+ TTask.Run(procedure var R: string; begin
194
+ R := PerformHeavyWork;
195
+ TThread.Queue(nil, procedure begin lblResult.Caption := R; btnProcess.Enabled := True end);
196
+ end);
197
+ end;
198
+ ```
199
+
200
+ ## Anti-Patterns
201
+
202
+ Items marked ⊗ in Standards above are not repeated here.
203
+
204
+ - ≉ **`Application.ProcessMessages` in loops**: Use PPL/threads
205
+ - ≉ **Published fields without properties**: Use properties
206
+ - ≉ **Circular unit references**: Extract shared types to common unit
207
+
208
+ ## Compliance Checklist
209
+
210
+ - ! Follow Embarcadero Object Pascal Style Guide
211
+ - ! PascalCase identifiers; `T`/`I`/`E`/`F` prefixes
212
+ - ! See [testing.md](../coding/testing.md) for testing requirements
213
+ - ! Use DUnitX for unit tests
214
+ - ! Use `try..finally` for resource cleanup; `FreeAndNil` in destructors
215
+ - ! Use generics and interfaces for type safety and abstraction
216
+ - ⊗ Use `Variant`, `with`, global state, or BDE
217
+ - ⊗ Access UI from background threads
218
+ - ! Run `task check` before commit